不讓 Claude 收工的 Stop hook:拆解 everything-claude-code 的 delivery-gate
多數人裝 Claude Code 的 hook,是拿來自動跑 lint、格式化、擋危險指令。affaan-m(帳號名 Affaan)的開源專案 everything-claude-code(簡稱 ECC)在 6/30 加了一個反過來的東西:一個不讓 Claude 停下來的 Stop hook。它叫 delivery-gate——交件關卡。Claude 想結束這一輪、把控制權交還給你之前,得先過三道機械檢查;沒過,就被踢回去繼續做。
這個設計有趣的地方在於:它完全不靠「AI 判斷 AI 做得好不好」。它只查三件可以用程式驗證的事實——你有沒有講逃避的話、該記的學習筆記今天有沒有更新、磁碟還剩幾 GB。這篇拆解它的運作原理,並給你可以照抄的 settings.json 與 prompt 習慣。
本文大綱
先搞懂 ECC 與 Stop hook 是什麼
everything-claude-code 是 affaan-m 維護的一套 Claude Code「增強包」,也相容 Cursor、Codex、Copilot 等 harness。它把 agents、skills、rules、hooks 打包成一個 plugin,倉庫裡放了 60 多個 subagent、200 多個 skill。這次要談的,是 6/30 由貢獻者 YuhaoLin2005 提交的 commit 51bced9:「Stop hook: verify thinking quality at session end」。它新增了 skills/delivery-gate/,裡面一個 126 行的 SKILL.md 加一個 220 行的 hooks/quality-gate.py。
要看懂它,先要知道 Claude Code 的 Stop hook 是什麼。Claude Code 有一組生命週期事件(PreToolUse、PostToolUse、Stop…),其中 Stop 在「Claude 回完最後一段、準備結束這一輪」時觸發——注意,不是每次呼叫工具,而是整輪要停的那一刻。官方文件講得很直白:Stop hook「可以阻止 Claude 停下來,強迫它繼續對話」。這正是 delivery-gate 的著力點。
運作原理:三道檢查,全是查事實

流程如上圖。當 Stop 事件觸發,Claude Code 會把一段 JSON 從 stdin 餵給 quality-gate.py,裡面有兩個關鍵欄位:transcript_path(本輪對話逐字稿的檔案路徑)和 stop_hook_active(這一輪是否已經被 Stop hook 擋過一次)。腳本讀進逐字稿後,跑三道檢查。
第一道:合理化語句偵測。 用 4 條正規表達式掃逐字稿,抓那種「先跳過測試」「這是既有的 bug、不是我造成的」的逃避話術。核心 pattern 大致長這樣:
RATIONALIZATIONS = [
r'(?:this|that)\s+is\s+a\s+pre[- ]existing\s+(?:issue|bug)',
r'skipping\s+(?:tests?|lint|coverage|type[- ]check)\s+for\s+now',
r'(?:tests?|coverage)\s+(?:are|is)\s+(?:failing|broken)\s+but',
r"(?:not\s+addressing|won't\s+fix|leaving)\s+the\s+(?:failing|broken)",
]
抓到只在 stderr 印警告,永遠不擋。作者的定位很清楚:這只是提醒,真正的品質判斷交給會思考的 reviewer,regex 不越權。
第二道:學習庫時效。 這是 ECC 的哲學核心。它用檔案的修改時間(mtime)檢查 5 個「學習庫」有沒有在今天被更新:
LIBS = {
'ratings-tracker': 'ratings-tracker.md',
'decisions-log': 'decisions/log.md',
'growth-log': 'growth-log/',
'output-index': 'output-index.md',
'tooling-capabilities': 'tooling_capabilities.md',
}
規則是:如果這一輪是複雜任務(腳本用 COMPLEX_THRESHOLD = 3,也就是 ≥3 次 Edit/Write 就算複雜),卻有 3 個以上學習庫沒更新、或 growth-log 今天完全沒動過,就 exit 2 擋下。白話說:你剛做完一件不簡單的事,卻沒留下任何可複用的筆記,門就不讓你出。
它怎麼知道這一輪「動了幾次」?靠的就是前面那個 transcript_path。Claude Code 會把整輪對話寫成一份 JSONL 逐字稿,每一次工具呼叫都是一行;腳本把檔案讀進來、數裡面 Edit 與 Write 出現的次數,超過門檻就判定為複雜任務。這也是為什麼三道檢查全都不需要呼叫 LLM——它要的資訊,Claude Code 早就以檔案的形式攤在磁碟上了,腳本只是去讀、去數、去比對時間戳。這種「用現成的檔案系統事實當判準」的思路,是整個 delivery-gate 值得學的地方,比它本身擋了什麼更重要。
第三道:磁碟空間。 三階門檻,防止 agent 邊跑邊把硬碟寫爆:低於 50GB 印提醒、低於 30GB 印警告、低於 15GB 硬擋(程式裡是 DISK_CRIT_GB = 15)。對長時間掛著 agent、狂產 log 與快照的人,這條救命。

擋下之後會發生什麼? 這是 Stop hook 最漂亮的一環。腳本 exit 2 時,Claude Code 的規則是:忽略 stdout,把 stderr 的文字當成錯誤訊息回餵給 Claude,然後 Claude 不能停、要繼續。所以你在 stderr 寫「你改了 code 卻沒更新 growth-log,請補上再收工」,Claude 讀到就會去補、再次觸發 Stop——這次通過,才真的結束。整條路徑不需要任何一次額外的 LLM 判斷。
別踩的坑:無限迴圈與門檻假設
這裡有個必須誠實講的風險。Stop hook 一旦 exit 2 擋人,Claude 補做後會再次觸發 Stop;如果條件還沒滿足,就會無限來回。Claude Code 給的解法是 payload 裡那個 stop_hook_active——當它是 true,代表這一輪已經被擋過一次,你的 hook 這時就該直接放行、別再擋。官方範例第一行就是檢查它。
從我讀 quality-gate.py 內容看,磁碟那條特別要小心:如果真的低於 15GB 就硬擋,而 Claude 一輪之內清不出空間,就可能卡死在來回之間。所以要自己部署的話,強烈建議在腳本開頭補一段 stop_hook_active 判斷(若為 true 直接 exit 0),這是官方最佳實踐,成本只有三行。這點我沒實際跑壓力測試,是從程式邏輯與官方文件推的,值得你自己驗一次。
另外幾個數字要標清楚適用前提:COMPLEX_THRESHOLD = 3、磁碟的 50/30/15GB、5 個學習庫路徑,全是 SKILL.md 裡標明「可設定」的變數,預設值不見得適合你——SSD 只剩 40GB 是常態的人,先把 50GB 提醒改掉,才不會每輪被吵。
搭配 growth-log:不然關卡只會逼出空筆記
delivery-gate 只管「你今天有沒有動 growth-log」,管不了你寫的東西有沒有價值。所以同一天 YuhaoLin2005 還提交了 growth-log skill,把方法論補上。它的主張很銳利:大多數學習日誌記的是事件(「修好了 X 的 bug」),但真正會累積的是模式。它給的模板長這樣:
## [標題:寫模式,不是寫事件]
### Context 我當時想做什麼?哪裡出錯/哪裡意外順利?
### Root Cause 底層機制,不是表面症狀
### The Pattern 下次遇到 X,我會做 Y;辨識訊號是 Z
### Related [交叉連結的其他條目]
三條規則值得抄進你自己的工作流:失敗比成功值得記(bug 教的比順利實作多);寫之前先搜舊筆記、把同根因的合併成一條而不是各記一份;每條都要能回答「下次遇到類似狀況,我會怎麼做不一樣」——寫不出這句,就代表模式還沒抽出來,那只是日記。作者的原話是:「If you can't write that sentence, you haven't extracted the pattern yet.」
這兩者是配套的:光有關卡沒方法論 → 逼出一堆空筆記;光有方法論沒關卡 → 忙起來就忘了記。ECC 把兩者綁在一起,才是重點。
同一週還進了哪些新 skill 與 hook 修補
delivery-gate 和 growth-log 不是孤例。6/29–6/30 這幾天,ECC 一口氣併進好幾個由不同貢獻者提交的東西,順著看能感覺到這個 repo 的節奏:
loop-design-check(貢獻者 Seekers2001):一個「設計並審查目標導向 agent 迴圈」的 skill。當你在寫那種「跑到滿足條件才停」的 agent loop 時,用它先檢查迴圈的終止條件、狀態推進與退場機制是否設計正確——這跟 Stop hook 的無限迴圈風險其實是同一類問題的一體兩面。react-native-patterns(貢獻者 yerros):一組 React Native / Expo 的 rules pack 加 patterns skill,把行動端該遵守的慣例打包給 agent 參考。mailtrap-email-integration(貢獻者 dieudonneAwa)與ecc-recipes(貢獻者 KyawZinLatt):前者是接 Mailtrap 寄信的整合手冊,後者是把常見任務串成「食譜」的組合包。
同時還有兩個不起眼但很有代表性的 hook 修補:貢獻者 sshworld 把 doc-file-warning 這個 hook 的 stdin listener 用 require.main 包起來,避免它被當模組載入時亂吃輸入;phobicdotno 則修了「在 Windows 上用 shell 探測 .cmd 型 MCP server 時,參數沒加引號」的坑。這兩個 PR 提醒一件事:hook 是跑在你真實 shell 裡的腳本,跨平台(尤其 Windows 的 .cmd)與 stdin 行為都是實打實的地雷,自己寫 hook 時要當回事。
值得實測的點是:這些 skill 大多是 Markdown 說明加少量腳本,clone 下來單抽一兩個來讀、改成自己的版本,成本很低。
什麼時候該用、什麼時候別用
適合:個人或小團隊,想把「收工前一定做某件事」變成肌肉記憶——不管是更新 changelog、跑完整測試、還是留學習筆記。機械檢查的好處是幾乎零 token 成本、零誤判:它不會像 LLM reviewer 那樣有時判對有時判錯,df 就是 df。
不適合硬套:CI/團隊共用環境別直接塞會 exit 2 的 Stop hook,容易在別人機器上莫名卡住;學習庫那套是 ECC 作者的個人生產力哲學,你的團隊如果沒有「每天寫 growth-log」的文化,第二道檢查只會變成噪音,建議先關掉或改成只警告。它也不是安全或正確性保證——它查的是習慣,不是你的 code 對不對。
給工程團隊:照這樣接上
想試最小版本,三步:
- 把
quality-gate.py放到~/.claude/scripts/(或只抽你要的檢查、自己寫一支)。 - 在
~/.claude/settings.json加上 Stop hook:
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/scripts/quality-gate.py",
"timeout": 5000
}]
}]
}
}
- 開頭補
stop_hook_active保險,門檻改成你機器的實際值,先只留「磁碟硬擋」這條驗證跑得動,再逐步加上學習庫檢查。
更務實的心法:把 delivery-gate 當成一個模式範本,而不是照單全收。你真正該問的是——「我的團隊每次交件前,有哪件事總是被跳過?」把那件事寫成一條能用檔案時間戳或 exit code 驗證的檢查,掛上 Stop hook。這比再多一句「請記得…」的 CLAUDE.md 指示有效得多,因為它是 harness 幫你強制執行,不是靠模型自律。
想更省事,可以讓 Claude Code 自己幫你生這支 hook。給它一段像這樣的 prompt:
幫我寫一支 Python Stop hook,放在
~/.claude/scripts/。它要:從 stdin 讀 JSON,先檢查stop_hook_active,若為 true 就exit 0;接著跑git status --porcelain,如果有未 commit 的檔案、但這一輪對話逐字稿(transcript_path)裡沒有出現pytest或npm test的字樣,就把提醒寫到 stderr 並exit 2。其餘情況exit 0。
這其實就是把 delivery-gate 的三道檢查換成「你自己團隊的那一道」——精神一樣:只驗可機械查證的事實,把 exit 2 留給真正該擋的情況,並且一定先看 stop_hook_active。寫完讓它順手把 settings.json 的 Stop 區塊也一起補上,你只要驗一次跑得動即可。
來源
- affaan-m / everything-claude-code(ECC):https://github.com/affaan-m/everything-claude-code — 維護者 affaan-m(Affaan)
- Stop hook commit
51bced9(by YuhaoLin2005, 2026-06-30):skills/delivery-gate/{SKILL.md, hooks/quality-gate.py} - growth-log skill commit
b5806b3(by YuhaoLin2005, 2026-06-30) - Claude Code Hooks 官方文件:https://code.claude.com/docs/en/hooks
整理:DataAgent · Coding Agent 實戰教學


