生活分享

Claude Code|建立可停止的品質檢查 Hook

讓完成檢查能指出失敗並有清楚的退出機制。測試沒有通過時,Claude 應知道工作還有問題;但如果 Hook 每次都阻止結束,又可能陷入不停重試。本篇建立有次數邊界的 Stop 檢查,第一次失敗回報原因,重複觸發時停止遞迴,並把尚未完成的結果清楚交回讀者。

閱讀時間約 6 分鐘

建立可停止的品質檢查 Hook:文件、螢幕與完成記號的幾何插圖
圖片:Mokaair (© Mokaair)
本篇目錄
  1. 先定義這個檢查能保證什麼
  2. 看懂停止事件的回應
  3. 先以正常事件重播
  4. 注入一個確定會失敗的測試
  5. 使用 stop_hook_active 避免遞迴
  6. 安裝到 Claude 並做真實觸發
  7. 測試失敗訊息要能導向下一步
  8. 常見失敗與停止方式

測試沒有通過時,Claude 應知道工作還有問題;但如果 Hook 每次都阻止結束,又可能陷入不停重試。本篇建立有次數邊界的 Stop 檢查,第一次失敗回報原因,重複觸發時停止遞迴,並把尚未完成的結果清楚交回讀者。

先讀、及。下載第 75 篇材料,在 starter 操作。需要 Node.js 22 以上,真實事件另需 Claude 登入。閱讀約 20 分鐘,實作約 45 分鐘。

先定義這個檢查能保證什麼

先定義這個檢查能保證什麼 → 看懂停止事件的回應 → 先以正常事件重播
先定義這個檢查能保證什麼 → 看懂停止事件的回應 → 先以正常事件重播 · 圖片:Mokaair (© Mokaair)
閱讀完整文字說明

建立可停止的品質檢查 Hook,以流程和文件圖形呈現教學重點。

本課在 Stop 事件執行固定的模型測試命令,只檢查這四個測試是否通過。它不是不可繞過的 CI,也不表示網站已通過瀏覽器、手機或部署驗證。把一個小 Hook 說成完整品質保證,會讓讀者誤以為未覆蓋的部分也已檢查。

材料的 hooks/quality.mjs 使用 Node 啟動另一個 Node 程序,傳入陣列,不從事件拼接命令。工作目錄取自事件 cwd,執行上限十五秒。固定命令能讓結果可比較,也避免一次 Stop 自動安裝依賴、啟動外部服務或跑一整套沒有時間上限的工作。

先手動執行 node --test tests/model.test.mjs,確認四個正常。若本機 Node 不存在,Hook 自然也不會成功;先處理環境,再談品質判斷。執行失敗、測試斷言失敗和超時都應保留原因,不能全部換成「已檢查」。

看懂停止事件的回應

PreToolUse 使用的拒絕欄位不適用所有事件。Stop 若需要要求繼續處理,可依官方事件格式輸出 decision:block 與 reason;不需要阻止時則正常結束。每個事件的 JSON 契約不同,應先用離線資料確認,再安裝到真實工作階段。

範例輸出:Stop 檢查失敗時的決定 · json
{
  "decision": "block",
  "reason": "模型測試未通過。請查看實際測試輸出,修正原因或明確回報受阻;不要宣稱完成。"
}

reason 應包含下一個可執行動作,而不只是「失敗」。本課指向固定的核心測試,讓讀者可以在終端機重跑取得完整結果。若你擴充成多套測試,須記錄是哪一套失敗及執行範圍,不要讓模型在沒有依據的情況下重寫程式。

輸出 JSON 不代表 shell 退出碼一定非零。Hook 決定與程序是否正常產生回應是兩層訊號,需要分別檢查。反過來,腳本本身拋錯,也不等於它產生了一個有效的 Stop 阻擋決定,不能把兩者混成同一種失敗。

先以正常事件重播

材料中的 fixtures/stop.json 是手工事件,包含 hook_event_name 和 stop_hook_active。先在正確專案重播,預期核心測試通過,沒有輸出阻擋決定。接著記錄重播命令退出狀態,確認工具沒有一直留在執行中。

專案終端機:正常基準 · text
node hooks/replay.mjs quality fixtures/stop.json
node --test tests/model.test.mjs

這一輪證明腳本能接受事件並執行測試,不代表 Claude 真正送出過 Stop。把「離線重播」「Claude 事件」「手動測試」分成三種來源,後續報告就不會把同一份假資料重播誤當成完整產品整合驗證。

對於沒有測試需求的簡短對話,無條件在每次 Stop 跑測試可能只是增加等待。本篇先展示固定檢查的機制,真實專案可再加入有根據的變更判斷,例如只在相關檔案改動後執行。不要以猜測模型正在寫程式作為唯一觸發條件。

注入一個確定會失敗的測試

保存 model.js,將 toggleTodo 的相等比較刻意改成不相等,再手動執行模型測試。預期與識別碼相關的案例失敗。這個故障影響小、可重現,適合用來驗證 Hook;不要以破壞套件安裝或刪除大量檔案製造混亂的失敗。

再次重播 Stop,預期得到 block 決定。記錄 reason,再手動重跑測試查看原始斷言。確認是因為功能錯誤被阻擋,而不是命令寫錯或工作目錄不正確。兩種狀況都可能導致非零結果,但需要不同修正。

故障檔案修好後,重新執行測試與 Stop 重播。完成證據應包含失敗前、故障時、修正後三個結果。只把 Hook 停用,測試仍失敗,不能算功能已修復;停用是控制自動化行為,修正程式是另一個工作。

使用 stop_hook_active 避免遞迴

當 Stop Hook 已經促使 Claude 繼續處理,再次收到停止事件時,不能無限重複相同阻擋。材料檢查 stop_hook_active;重複事件只回報仍需明確說明測試狀態,不再輸出 block。這是一個刻意有限的策略,讓失敗能交回讀者。

寫入 fixtures/stop-repeated.json:模擬已在停止檢查中 · json
{
  "hook_event_name": "Stop",
  "session_id": "lab-75",
  "stop_hook_active": true
}
專案終端機:故障仍存在時測試重複事件 · text
node hooks/replay.mjs quality fixtures/stop-repeated.json

預期不再阻擋,也不再啟動同一套遞迴測試。這不代表測試變成通過,最後回報仍應指出未完成。將「可以結束對話」與「品質已達標」分開,才能避免為了防止遞迴而把錯誤隱藏起來。

若你需要更多重試,可以另外保存有上限的狀態,但必須處理工作階段識別、清理及異常中斷。單靠一句「最多再試一次」的自然語言不等於程式計數器。本篇先採事件旗標與一次阻擋,便於讀者理解和驗證。

安裝到 Claude 並做真實觸發

先備份現有設定,再將 Stop 項目合併到 .claude/settings.json。Hook 外層 timeout 應留足腳本自己的十五秒測試時間;本課設二十秒。外層與內層上限不同,是為了讓腳本有機會整理結果,而不是先被外層直接終止。

寫入 .claude/settings.json 的 Stop 範例 · json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [{"type": "command", "command": "node hooks/quality.mjs", "timeout": 20}]
      }
    ]
  }
}

建立新工作階段,先用正常專案完成一個唯讀任務,再用故障版本完成同樣任務,觀察 Stop 行為。不要在提示詞直接貼預期的 Hook JSON 答案。保存事件紀錄和實際測試結果,才足以確認真實整合。

測試失敗訊息要能導向下一步

品質檢查阻擋結束時,訊息應指出要執行的命令及失敗類型。只有一句「請修正」會讓下一輪再次猜測原因。若完整輸出太長,可保存到本機檔案並在摘要列出檔案位置,讓讀者能看到原始錯誤而不必依賴模型轉述。

反覆失敗時停止自動循環,回到終端機直接執行相同測試。先確認測試本身可運作,再決定是否繼續修正。重新觸發 Stop 並不會自然解決環境缺少工具或測試命令寫錯的問題。

常見失敗與停止方式

症狀檢查重點下一步
每次都繼續無法結束重複事件旗標確認 stop_hook_active 分支
沒有測試就被阻擋cwd、命令、Node手動重跑同一命令
超時後仍說成功子程序狀態與錯誤分支非完成結果保留為失敗
Hook 停用後測試仍壞程式故障尚未修復恢復 model.js 並重測

若工作階段無法正常結束,先中止本次練習,再恢復自己備份的 Stop 設定,建立新階段確認不再觸發。不要刪除所有 Hook 或終止整台電腦的 Node 程序。只處理本次啟動的程序及設定,保留故障紀錄供排查。

完成判準包含通過、故障、修正、重複停止四種案例;每次都能指出測試結果及是否產生 block。小練習是讓固定測試超過內層時間上限,確認最後仍回報未完成,再恢復正常測試。若要處理更複雜的逾時與跨平台行為,接著閱讀。

回總目錄

  • 生活分享

    Claude Code|建立第一個 mod:在 Claude Code 行程內數工具呼叫

    寫一個三檔案的 mod,用驗證器與測試確認它掛上的事件。文件把 mod 定義成多了入口檔的 plugin:入口檔叫 hooks module,Claude Code 在事件發生時呼叫裡面的函式,函式可以觀察、改寫或接手事件。

  • 生活分享

    Claude Code|Git Worktree 平行工作

    隔離多個任務的檔案與分支。Git Worktree 讓同一儲存庫擁有多個工作目錄,各自使用分支與檔案。本篇會把待辦篩選與文件整理分開,確認兩個 session 不會直接改到彼此的檔案,再把其中一個成果整合回主分支。你也會知道何時可以安全清理工作目錄。

  • 生活分享

    Claude Code|雙 Worktree 實作與衝突整合

    隔離兩項功能,最後完成整合與回歸。兩個 Claude 工作階段同時編輯專案,最容易出現的問題是互相改到同一份檔案,或各自測試通過、整合後卻失敗。本篇用兩個 Worktree 分別處理篩選預設值與介面文字,故意製造一次小衝突,再完成整合、驗證與清理。你不需要先啟用 Agent Teams。

  • 生活分享

    Claude Code|比較流程品質、用量與執行時間

    以同一資料集比較兩種工作方法。比較兩種 Claude 工作方法時,不能只挑成功那一次,也不能只看第一個答案有多快。本篇用固定案例、原始紀錄和一致判準,比較品質、重試、等待與人工整合時間,最後寫出有樣本數與限制的報告,而不是保證某個方法一定省錢。

最新旅遊情報攻略

資料來源

生活分享