# Claude Code 的 /simplify 讓四個 AI 代理並行整理變更的程式碼 — 之後再交給 /code-review 檢查

> Claude Code 的 /simplify skill 會讓四個 AI 代理並行審查變更的程式碼並套用修正，之後再用 /code-review 檢查修改後的程式碼有沒有錯誤。

- Source: https://oharu121.com/zh-tw/blog/claude-code-simplify-parallel-cleanup-agents-code-review/
- Published: 2026-10-27T00:43:04+09:00
- Tags: Claude Code, Claude

---
## 引言

`/simplify` 是 Claude Code 內建的 skill。這個 skill 我已經用了好幾個星期，卻不知道它到底在做什麼。我只知道它還有個雙胞胎 skill 叫 `/code-review`，很多人建議把兩者搭配使用。這兩個 skill 看起來很像，但它們各自怎麼分工，我卻說不上來。

**`/simplify` 是只做程式碼整理的審查**。四個 AI 代理會同時運行，讀取差異，各自負責一個角度：重複使用、簡化、效率，以及抽象層級，也就是判斷各項變更是否放在正確的分層。它們的修正會直接寫進工作目錄，不會先列出來讓使用者挑選要套用哪些。

`/simplify` 不會去挑程式碼的錯誤，所以 **`/code-review` 要在它之後執行**，檢查它處理過的程式碼。我用這個部落格的一個真實的 commit 把兩者都執行了一次，看看各自能抓到什麼。

## /simplify 的運作方式

`/simplify` 是 Claude Code 內建（bundled）的 skill。內建 skill 是一段寫在 Claude Code 裡的提示詞，告訴模型怎麼用自己的工具完成審查和修正。[指令參考文件](https://code.claude.com/docs/en/commands)對它的說明如下（中譯）：

> 審查變更過的程式碼，找出可以整理的地方並套用修正。四個審查用的 AI 代理會並行執行，涵蓋既有輔助函式的重複使用、簡化、效率，以及變更是否位於正確的抽象層級。這項審查不找正確性方面的錯誤，要找錯誤請使用 `/code-review`。

`/simplify` 載入的提示詞分成三個階段：

1. **收集差異**。以 upstream 分支為基準執行 `git diff`，再加上尚未 commit 的變更；如果以參數傳入路徑或 pull request，就改以那個目標為準。
2. **審查**。四個 AI 代理同時啟動，並被交付上個步驟收集的差異以及應該以哪個角度進行審查。
3. **套用**。針對同一行的審查意見會先合併成一項，再逐項直接套用到工作目錄。

每個 AI 代理都會從提示詞拿到一份分工說明：

| AI 代理 | 提示詞要它找什麼 | 下文實測中的例子 |
| --- | --- | --- |
| 重複使用 | 新程式碼是否重寫了專案裡已經有的輔助函式；會去搜尋共用模組和鄰近的檔案 | `scripts/indexnow.ts` 也建立了 `new URL(SITE)`，但沒有地方匯出解析好的結果可以直接匯入 |
| 簡化 | 多餘或可推導的狀態、只差一點的複製貼上、過深的巢狀、遺留的無用程式碼 | `resolveMark` 組出一個物件，唯一的呼叫端卻馬上把它拆開 |
| 效率 | 重複的運算或 I/O、可以並行卻依序執行的步驟、加在頻繁執行路徑上的工作 | `luminance(DARK_BACKGROUND)` 在每一頁的每個圖示上都重算一次，其實可以在模組載入時算一次就好 |
| 抽象層級 | 只在表面修補症狀、根本原因其實在更深一層；或在共用程式碼上疊加特殊情況 | 部落格舊的主機名稱寫死在 logo 對照表裡，而不是放在 `site.ts` |

提示詞也寫明了，主代理在套用階段可以略過哪些審查意見，以下是原文的中譯：

> 如果某項審查意見的修正會改變預期的行為、需要在審查的差異之外大幅改動，或是被判斷為誤報，就可以直接略過。只要記錄略過了哪些審查意見即可，不必逐條說明為什麼不採用。

找錯誤的工作則交給同樣內建的 `/code-review` skill：

| | `/simplify` | `/code-review` |
| --- | --- | --- |
| 尋找的內容 | 重複使用、簡化、效率、抽象層級 | 正確性方面的錯誤；依模型和 effort 等級，也會涵蓋程式碼整理 |
| 是否修改檔案 | 一律套用自己的修正 | 只回報，除非傳入 `--fix` |
| 執行方式 | 四個審查用的 AI 代理並行執行 | 擁有獨立脈絡視窗的背景子代理 |
| 接受的參數 | 路徑，或 pull request 的編號或網址 | `low` 到 `max` 或 `ultra` 的 effort 等級、`--fix`、`--comment`、`--max-findings`，以及 pull request、分支或路徑 |

> **小心喔**
>
> **較早的文章描述的是另一個 /simplify**
>
> `/simplify` 的行為[改過好幾次](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md)：
>
> 1. 2.1.63：新增 `/simplify`。
> 2. 2.1.147：改名為 `/code-review`，並移除程式碼整理的行為。
> 3. 2.1.152：`/simplify` 回來了，改為呼叫 `/code-review --fix`。
> 4. 2.1.154：又改回只做程式碼整理的審查。
>
> **所以舊文章的描述可能不同**，例如 [2026 年 3 月的一篇文章](https://batsov.com/articles/2026/03/11/essential-claude-code-skills-and-commands/)寫的就是三個 AI 代理，而不是四個。

[2026 年 3 月那篇文章](https://batsov.com/articles/2026/03/11/essential-claude-code-skills-and-commands/)出自 Ruby 程式碼分析與格式化工具 RuboCop 的作者 Bozhidar Batsov。他說 `/simplify` 是「我最常用的 skill」，會在「完成較大規模的重構之後，或一次接受一批 AI 產生的程式碼之後」馬上執行它（引文為中譯）。

## 拿真實的 commit 來測試 /simplify

我挑的是一個已經正式上線的 commit。這個部落格有一個 rehype 外掛（在建置時加工 HTML 的外掛）`rehype-link-icons.ts`，會在連結旁邊畫出[品牌的 logo](/zh-tw/blog/astro-rehype-plugin-link-brand-icons-svg-sprite-csp/)；這個 commit 替它加了四個新的 logo：Qiita、Zenn、DevelopersIO，以及在這個部落格上其他文章的連結加上的印章。

**我在另一個工作樹裡，把過去的 commit 重新套用成還沒 commit 的變更**，這樣就能放手讓 `/simplify` 去修改，也不會影響到真正的程式碼以及正在進行的工作：

```bash
git worktree add --detach ../simplify-trial <commit>^
git -C ../simplify-trial cherry-pick -n <commit>
```

接著在 `../simplify-trial` 工作樹裡，用 Claude Code 2.1.310 執行：

```text
/simplify src/lib/rehype-link-icons.ts
```

四個 AI 代理一共回報了九項審查意見，`/simplify` 套用了其中三項：

| AI 代理 | 審查意見 | 已套用 |
| --- | --- | --- |
| 重複使用 | 0 | 0 |
| 簡化 | 3 | 2 |
| 效率 | 0 | 0 |
| 抽象層級 | 6 | 1 |

重複使用和效率兩列是 0，因為這兩個 AI 代理提出的都只是觀察（像前面表格裡的例子），**沒有這次差異需要修改的地方**。

### 套用的三項修正

最大的一項就是上表簡化那一列的例子，刪掉了 `MarkSymbol` 型別。這個型別唯一的用途，是把 `id` 欄位從 `resolveMark` 傳給唯一呼叫它的地方。負責組出 sprite（集中放置所有 logo 的隱藏 `<svg>`）的程式碼，一拿到回傳值就立刻把它拆開：

```ts title="src/lib/rehype-link-icons.ts (before)"
function resolveMark(key: MarkKey): MarkSymbol {
  if (isLocal(key)) return { id: symbolId(key), ...LOCAL_MARKS[key]() };
  return { id: symbolId(key), viewBox: "0 0 24 24", children: [markPath(key)] };
}
// …
children: [...used].map((key) => {
  const { id, viewBox, children } = resolveMark(key);
  return element("symbol", { id, viewBox }, children);
}),
```

`/simplify` 把 `resolveMark` 換成直接回傳 `<symbol>` 節點的 `symbol()`，`MarkSymbol` 型別也就不需要了：

```ts title="src/lib/rehype-link-icons.ts (after)"
function symbol(key: MarkKey): HastNode {
  const { viewBox, children } = isLocal(key)
    ? LOCAL_MARKS[key]()
    : { viewBox: "0 0 24 24", children: [markPath(key)] };
  return element("symbol", { id: symbolId(key), viewBox }, children);
}
// …
children: [...used].map(symbol),
```

另外兩項比較小：

- **favicon 的讀取方式**：外掛會從 favicon 讀取印章的形狀。原本 `<svg>` 標籤用另外一行讀取，`<circle>`、`<g>`、`<path>` 則用同一個 `.map`；現在四個標籤都用同一個 `.map` 讀取，結果不變。
- **舊的主機名稱**：部落格舊的網址 `oharu-tech-blog.vercel.app` 原本直接寫在 logo 對照表裡，但網站的網址都應該放在 `site.ts`。這就是上表抽象層級那一列的例子。現在它移到 `site.ts` 的 `LEGACY_HOSTS`，以後網址有變動，只要改 `site.ts` 一個檔案就好。

### 略過的六項

`/simplify` 略過的六項審查意見，以及略過的原因：

| 審查意見的建議 | 略過的原因 |
| --- | --- |
| 讓自行繪製的 logo（DevelopersIO 和印章）也經過對比度檢查 | 會改變行為：深色模式下這兩個 logo 會被改色 |
| 先解析連結再分類，讓 `./other/` 這類連結也加上印章 | 會改變行為：目前沒有圖示的連結會多出印章 |
| 拿掉每個圖示外層 `<svg>` 上 24×24 的 `viewBox` | 會改變行為：圖示顯示的大小可能改變 |
| 讓品牌產生器直接把印章形狀輸出成模組，而不是用正規表示式解析 `public/favicon.svg` | 超出差異範圍：要改的是另一個產生 favicon 的腳本 |
| 在既有的節點建構函式裡也改用新的 `element()` 輔助函式 | 超出差異範圍：要改的是這次差異沒有動到的程式碼 |
| 用一個形狀一致的 logo 物件取代 `isLocal` 分支 | 部分已經處理：改成 `symbol()` 之後，這個分支已經少了一處 |

**`/simplify` 不會執行它修改過的程式碼**，所以 Claude Code 另外確認了這三項修正沒有改變頁面上的任何東西。做法是拿六種連結（GitHub、根目錄相對路徑、舊主機、DevelopersIO、Zenn 和一個註腳）分別交給修改前後的外掛處理，輸出完全相同。

## 對 /simplify 處理過的程式碼執行 /code-review

對 `/simplify` 改過的 `rehype-link-icons.ts` 和 `site.ts` 執行 `/code-review` 之後，回報了十項審查意見。

**其中九項在那次 commit 正式上線時就已經存在**，這九項裡有三項可以直接重現：

| 輸入 | 外掛的行為 | 原因 |
| --- | --- | --- |
| `href="/\github.com/x"` | 畫出 GitHub 的 logo | 根目錄相對路徑的判斷排除了 `//`，卻沒有排除 `/\`，而解析 URL 時會把反斜線當成斜線 |
| `href="http://constructor/"` | 拋出 `TypeError: key.slice is not a function`，整個建置失敗 | logo 對照表是一般物件，所以這個主機名稱會查到 `Object.prototype.constructor` |
| DevelopersIO 的 `#cbd31e` 區塊 | 在淺色主題的白底上，對比度只有 1.63:1，低於 WCAG 要求的 3:1 | 自行繪製的 logo 不經過對比度檢查 |

負責抽象層級的 AI 代理其實也看過 `markFor` 裡判斷根目錄相對路徑的正規表示式，但它只指出這段判斷放錯了地方。**這個正規表示式會不會讓格式錯誤的 `href` 通過，屬於正確性的問題**，不在它負責的範圍內，所以反斜線的錯誤要到 `/code-review` 才被發現。

## /simplify 和 /code-review 該在什麼時候執行？

正確的做法是**先執行 `/simplify`，最後才執行 `/code-review`**。`/simplify` 會直接修改工作目錄裡的程式碼，而審查只看得到執行當下的程式碼；如果順序反過來，`/simplify` 做的修改就在沒有經過任何審查的情況下被 commit。

*Figure — Workflow: /simplify 會修改程式碼，所以要讓 /code-review 審查修改後的結果，而不是反過來。*

Batsov 在 [3 月那篇文章](https://batsov.com/articles/2026/03/11/essential-claude-code-skills-and-commands/)裡介紹的工作流程，順序正好相反：「先修改，用 `/review` 找出問題，把指出的問題都修好，最後才用 `/simplify` 整理」（中譯）。

## 總結

`/simplify` 會把差異交給四個 AI 代理，從重複使用、簡化、效率和抽象層級四個角度同時審查，再由主代理套用修正，但會略過改變行為或超出差異範圍的部分。**它完全不找錯誤，也不會執行它修改過的程式碼**。

**接著再對 `/simplify` 處理過的程式碼執行 `/code-review`**。如果想拿已經正式上線的 commit 試試這兩個 skill，可以用 `git cherry-pick -n` 把它重新套用到另一個工作樹，在那裡執行。

## 參考連結

- [Claude Code 指令參考文件（含 `/simplify` 與 `/code-review` 條目）](https://code.claude.com/docs/en/commands)
- [Review locally with /code-review（包含它和 /simplify 的關係）](https://code.claude.com/docs/en/code-review-local)
- [Claude Code 更新紀錄（/simplify 的沿革見 2.1.63 到 2.1.154）](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md)
- [Bozhidar Batsov: Essential Claude Code skills and commands](https://batsov.com/articles/2026/03/11/essential-claude-code-skills-and-commands/)
