Anthropic 的 Hooks 文件說明,Hook 命令會透過標準輸入接收 JSON 資料;因此看不到效果時,先確認事件有沒有觸發、腳本有沒有啟動,再查回傳內容,而不是先重裝 Claude Code。(官方 Hooks 文件)
症狀:格式檢查、命令攔截或測試檢查沒有反應。
最快解法:先核對實際載入的設定檔與事件、matcher,再檢查遠端執行帳戶、腳本環境和輸出格式。
這篇適合在遠端 Mac 上使用 Claude Code、但 Hook 效果不如預期的開發者。
如果你維護 CI 或共用節點,也能用以下流程區分設定問題、執行失敗與驗收責任。
先定位 Claude Code Hooks 的故障層
不要一開始就刪除設定或重裝。先用一個可重複的最小動作,例如對指定檔案執行一次預期會觸發檢查的修改,並觀察會話紀錄和 Hook 的診斷輸出。
將現象分成幾層,能避免把不同問題混在一起:
- 事件未觸發:操作沒有走到你設定的事件。例如,你期待工具開始前執行檢查,實際設定卻是工作階段結束時才觸發。
- matcher 未匹配:事件已發生,但設定篩選的工具名稱或條件不符合實際呼叫。
- 腳本未啟動:Hook 已被選中,但檔案路徑、可執行權限或解譯器有問題。
- 腳本已執行、效果未生效:輸出格式、退出狀態或決策欄位不符合該事件的契約。
- Hook 通過、後續失敗:Hook 有執行,但後續工具、建置或 CI 步驟失敗。這不是「Hook 沒觸發」。
記下測試動作、啟動 Claude Code 的方式、工作目錄,以及看到的紀錄。診斷資料不要包含 Token、簽署憑據或其他機密。
核對遠端 Mac 實際讀取的設定來源
Hooks 的設定可能放在不同範圍。先比對正在執行 Claude Code 的帳戶與工作目錄,再確認該環境實際可讀取的設定檔。不要只檢查你登入桌面時使用的帳戶。
Claude Code 設定文件列出使用者、專案、本機專案與受管理設定的用途。可先用下表整理檢查範圍:
| 設定來源 | 常見用途 | 排查時確認 |
|---|---|---|
| 使用者設定 | 該使用者的個人偏好 | SSH、互動式終端或服務程序是否以同一帳戶執行 |
| 專案設定 | 隨專案共用的設定 | 工作目錄是否位於預期專案,設定檔是否存在且可讀 |
| 專案本機設定 | 只供本機工作目錄使用的設定 | CI 或其他帳戶是否根本看不到這份本機檔案 |
| 受管理設定 | 組織管理的政策 | 是否有受管規則影響可用設定或執行行為 |
在遠端 Mac 開發環境中,桌面終端、SSH 工作階段和 Runner 服務程序可能使用不同帳戶、工作目錄或啟動環境。逐一在實際執行 Claude Code 的環境核對設定,不要假設本機設定會同步到另一個帳戶。
如果你要把這套檢查放進正式流程,先確認團隊使用的遠端 Mac 方案與使用方式,再以實際執行帳戶做驗收。
對齊事件、matcher 與實際工具呼叫
依照操作發生的時間點選事件。工具呼叫前的檢查、工具執行後的檢查,以及工作階段結束時的處理,不是可互換的設定。Anthropic 的Hooks 事件與 matcher 說明可用來比對事件名稱、篩選條件與傳入資料。
實際排查時,先把設定縮到單一事件與單一工具呼叫。若要確認工具呼叫前的攔截,就觀察對應的前置事件;不要用結束事件來推斷前置事件是否生效。接著查看 matcher 是否針對實際工具名稱,而不是你以為 Claude Code 會呼叫的工具。
保留一份「預期動作 → 預期事件 → 實際工具 → Hook 紀錄」的對照。若事件有紀錄但沒有腳本輸出,問題可能在啟動;若腳本有輸出但未阻止操作,則應轉查回傳契約。這比一次加入多個 matcher 更容易定位。
比對 SSH 與 Runner 的腳本環境
Hook 腳本能啟動,不代表它擁有你互動式終端中的環境。尤其要比較 SSH 登入 Shell 與 Runner 服務帳戶的 PATH、工作目錄、解譯器路徑、依賴程式和檔案寫入權限。
可在腳本開頭加入短期診斷輸出,只記錄必要的非敏感資訊,例如目前帳戶、工作目錄、PATH,以及必要命令是否可找到。不要列印整份環境變數;其中可能包含憑據。也不要把「本機 Shell 找得到命令」當成服務程序也能找到的證明。
若找不到命令,先使用明確的解譯器或工具路徑,再確認服務帳戶具備讀取專案、執行腳本與寫入預期輸出位置的權限。若腳本依賴登入 Shell 才載入的環境,應明確設定所需路徑,而不是期待非互動程序沿用登入設定。
核對回傳契約與阻斷效果
Hook 有執行結果,不表示 Claude Code 一定會依你預期採取動作。先查事件文件對標準輸入、JSON 輸出、退出狀態與決策欄位的要求,再分別測試一般完成與明確阻斷。不同事件支援的控制方式可能不同,不能只靠「程式有印字」判斷成功。
Claude Code 的權限文件也要一併檢查:Hook 的控制結果和權限政策是不同層次。把它們分開驗證,才能知道是 Hook 回傳錯誤、設定沒有匹配,還是權限規則在起作用。
| 觀察到的結果 | 優先核對 | 下一步 |
|---|---|---|
| 沒有 Hook 紀錄 | 設定來源、事件是否觸發、matcher 條件 | 縮小成單一工具呼叫重測 |
| 有啟動紀錄、沒有預期輸出 | 解譯器、依賴、標準輸入解析與權限 | 在目標帳戶下單獨執行腳本 |
| 有輸出但未阻斷 | 事件支援的決策欄位、JSON 格式、退出狀態 | 依官方契約測試允許與阻斷兩種結果 |
| Hook 顯示完成、CI 仍失敗 | 後續命令與 CI 判定 | 查看建置、測試工作本身的結果 |
文件對 Hook 退出狀態有明確區分:0 表示命令成功;2 用於阻斷錯誤,其他非零狀態的處理則需依 Hook 類型查看文件。不要把任意非零狀態都當成阻斷成功。(官方 Hooks 輸出與退出狀態說明)
分開驗收 Xcode、CI 與主機安全
Stop Hook 可用於工作階段結束時的檢查,但它不能單獨證明 Xcode 測試通過。把檔案修改後的格式檢查、工作階段結束時的檢查,以及 CI 中正式執行的建置與測試分開記錄。
Apple 的執行測試與解讀結果文件說明了測試結果的檢視方式;需要命令列驗收時,另核對 Xcode 命令列工具參考。測試命令、結果資料和 CI 對成功或失敗的判定應能互相追溯。Apple 亦提供透過 SSH 自動化 Xcode 測試的歸檔指南,可作為遠端執行流程的補充參考。
| 需求 | Hook 可負責的部分 | 不應交給 Hook 單獨承擔的部分 |
|---|---|---|
| 修改後快速檢查 | 觸發格式或靜態檢查 | 保證完整建置與測試通過 |
| 工具呼叫控制 | 依事件契約回傳允許、詢問或阻斷結果 | 隔離主機、帳戶或檔案系統權限 |
| Xcode 自動化測試 | 提醒、啟動或輔助檢查流程 | 取代 CI 保存測試結果與判定工作狀態 |
| 敏感操作保護 | 配合權限設定做額外檢查 | 取代人工審批、作業系統權限或簽署憑據保護 |
修復後,以預期通過和預期失敗的動作分別驗收,並確認節點重新啟動後仍能由目標帳戶執行。若要判斷失敗,需分清 Hook 錯誤、Hook 未匹配、腳本執行失敗與 CI 後續步驟失敗;這些情況應留下不同證據。
若你目前靠本機終端或共用 Linux 伺服器排查,常見代價是環境與帳戶不一致、無法直接完成 macOS 專屬的 Xcode 驗收,以及長期購置設備卻未必持續使用。需要真實 macOS 環境做短期重現或驗證時,可了解 MACCOME 遠端 Mac 使用方案;但若工作長期穩定佔用節點,或必須連接實體設備,自購 Mac 可能更合適。
常見問題
Claude Code Hooks 為什麼在遠端 Mac 上沒有反應?
先確認實際讀取的設定檔與執行帳戶,再比對事件和 matcher。只有確認 Hook 已被選中後,才查腳本路徑、依賴與輸出。
PreToolUse matcher 沒有命中,如何縮小問題?
只保留一個前置事件和一種工具呼叫,核對 matcher 的工具名稱及輸入條件,再查看會話與 Hook 紀錄。
SSH 環境找不到腳本命令,應先檢查什麼?
比對服務帳戶與互動式 Shell 的 PATH、工作目錄、解譯器和依賴;不要假設登入 Shell 的設定會套用到 Runner。
Stop Hook 能驗收 Xcode 自動化測試嗎?
它能協助執行結束時的檢查,但不能取代 Xcode 測試結果及 CI 的正式成功判定。
Hook 可以取代作業系統權限或人工審批嗎?
不可以。Hook 是流程控制的一環,不是主機隔離或憑據保護機制;敏感操作仍須由權限政策、人工審批與受控 CI 負責。