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

本頁目錄
引言
/simplify 是 Claude Code 內建的 skill。這個 skill 我已經用了好幾個星期,卻不知道它到底在做什麼。我只知道它還有個雙胞胎 skill 叫 /code-review,很多人建議把兩者搭配使用。這兩個 skill 看起來很像,但它們各自怎麼分工,我卻說不上來。
/simplify 是只做程式碼整理的審查。四個 AI 代理會同時運行,讀取差異,各自負責一個角度:重複使用、簡化、效率,以及抽象層級,也就是判斷各項變更是否放在正確的分層。它們的修正會直接寫進工作目錄,不會先列出來讓使用者挑選要套用哪些。
/simplify 不會去挑程式碼的錯誤,所以 /code-review 要在它之後執行,檢查它處理過的程式碼。我用這個部落格的一個真實的 commit 把兩者都執行了一次,看看各自能抓到什麼。
/simplify 的運作方式
/simplify 是 Claude Code 內建(bundled)的 skill。內建 skill 是一段寫在 Claude Code 裡的提示詞,告訴模型怎麼用自己的工具完成審查和修正。指令參考文件對它的說明如下(中譯):
審查變更過的程式碼,找出可以整理的地方並套用修正。四個審查用的 AI 代理會並行執行,涵蓋既有輔助函式的重複使用、簡化、效率,以及變更是否位於正確的抽象層級。這項審查不找正確性方面的錯誤,要找錯誤請使用
/code-review。
/simplify 載入的提示詞分成三個階段:
- 收集差異。以 upstream 分支為基準執行
git diff,再加上尚未 commit 的變更;如果以參數傳入路徑或 pull request,就改以那個目標為準。 - 審查。四個 AI 代理同時啟動,並被交付上個步驟收集的差異以及應該以哪個角度進行審查。
- 套用。針對同一行的審查意見會先合併成一項,再逐項直接套用到工作目錄。
每個 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、分支或路徑 |
2026 年 3 月那篇文章出自 Ruby 程式碼分析與格式化工具 RuboCop 的作者 Bozhidar Batsov。他說 /simplify 是「我最常用的 skill」,會在「完成較大規模的重構之後,或一次接受一批 AI 產生的程式碼之後」馬上執行它(引文為中譯)。
拿真實的 commit 來測試 /simplify
我挑的是一個已經正式上線的 commit。這個部落格有一個 rehype 外掛(在建置時加工 HTML 的外掛)rehype-link-icons.ts,會在連結旁邊畫出品牌的 logo;這個 commit 替它加了四個新的 logo:Qiita、Zenn、DevelopersIO,以及在這個部落格上其他文章的連結加上的印章。
我在另一個工作樹裡,把過去的 commit 重新套用成還沒 commit 的變更,這樣就能放手讓 /simplify 去修改,也不會影響到真正的程式碼以及正在進行的工作:
git worktree add --detach ../simplify-trial <commit>^git -C ../simplify-trial cherry-pick -n <commit>接著在 ../simplify-trial 工作樹裡,用 Claude Code 2.1.310 執行:
/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>)的程式碼,一拿到回傳值就立刻把它拆開:
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 型別也就不需要了:
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。
Batsov 在 3 月那篇文章裡介紹的工作流程,順序正好相反:「先修改,用 /review 找出問題,把指出的問題都修好,最後才用 /simplify 整理」(中譯)。
總結
/simplify 會把差異交給四個 AI 代理,從重複使用、簡化、效率和抽象層級四個角度同時審查,再由主代理套用修正,但會略過改變行為或超出差異範圍的部分。它完全不找錯誤,也不會執行它修改過的程式碼。
接著再對 /simplify 處理過的程式碼執行 /code-review。如果想拿已經正式上線的 commit 試試這兩個 skill,可以用 git cherry-pick -n 把它重新套用到另一個工作樹,在那裡執行。

