設定您的第一個 hook
若要建立 hook,請將hooks 區塊新增到設定檔。本逐步解說建立一個桌面通知 hook,因此每當 Claude 等待您的輸入而不是監視終端時,您都會收到警報。
1
將 hook 新增到您的設定
開啟 如果您的設定檔已經有 您也可以透過在 CLI 中描述您想要的內容,要求 Claude 為您編寫 hook。
~/.claude/settings.json 並新增 Notification hook。如果檔案不存在,請建立它。下面的範例使用 osascript 進行 macOS;有關 Linux 和 Windows 命令,請參閱當 Claude 需要輸入時收到通知。hooks 鍵,請將 Notification 作為現有事件鍵的同級項目新增,而不是替換整個物件。每個事件名稱是單個 hooks 物件內的鍵:2
驗證設定
在 Claude Code 提示字元輸入
/hooks 以開啟 hooks 瀏覽器。您的新 hook 會出現在 Notification 下的列表中。3
測試 hook
按
Esc 返回 CLI。按 Shift+Tab 直到狀態列顯示 ⏸ manual mode on,要求 Claude 執行需要權限的操作,然後切換離開終端機。您應該會收到桌面通知。您可以自動化的內容
Hooks 讓您在 Claude Code 生命週期的關鍵點執行程式碼:編輯後格式化檔案、在執行前阻止命令、當 Claude 需要輸入時發送通知、在工作階段開始時注入上下文等。有關 hook 事件的完整列表,請參閱 Hooks 參考。 每個範例都包含一個現成可用的配置區塊,您可以將其新增到設定檔。 有關 hooks 執行單獨模型審查並將發現結果反饋到工作階段中的生產範例,請參閱security-guidance plugin 如何與 Claude Code 整合。
當 Claude 需要輸入時收到通知
每當 Claude 完成工作並需要您的輸入時收到桌面通知,這樣您可以切換到其他任務而無需檢查終端。 此 hook 使用Notification 事件,Claude Code 會在 Claude 等待輸入或權限時觸發此事件。請參閱每個通知類型何時觸發以了解確切的時機。
下面的每個標籤使用平台的原生通知命令。將此新增到 ~/.claude/settings.json:
- macOS
- Linux
- Windows (PowerShell)
如果沒有出現通知
如果沒有出現通知
osascript 透過內建的 Script Editor 應用程式路由通知。如果 Script Editor 沒有通知權限,命令會無聲地失敗,macOS 不會提示您授予它。在終端機中執行一次以使 Script Editor 出現在您的通知設定中:matcher 會在所有通知類型上觸發。若要僅在特定事件上觸發,請將其設定為以下其中一個值:
Claude Code 在終端和在 Claude Desktop、VS Code 擴充功能和其他透過 Agent SDK 回答權限請求的主機中以不同方式計時
permission_prompt。請參閱每個通知類型何時觸發以了解兩種計時。
quota_auto_resume_fired、quota_auto_resume_stale 和 quota_auto_resume_disabled 匹配器需要 Claude Code v2.1.234 或更新版本。
在終端工作階段中,沙箱命令的網路請求的 permission_prompt 需要 Claude Code v2.1.246 或更新版本。
隊友終端設定問題的 agent_needs_input 需要 Claude Code v2.1.248 或更新版本。
在 Claude Code 提示字元中輸入 /hooks,並確認 hook 出現在 Notification 之下。
編輯後自動格式化程式碼
在 Claude 編輯的每個檔案上自動執行 Prettier,以便格式保持一致而無需手動干預。 此 hook 使用PostToolUse 事件搭配 Edit|Write 匹配器,因此它只在檔案編輯工具之後執行。該命令使用 jq 提取編輯的檔案路徑並將其傳遞給 Prettier。將此新增到您的專案根目錄中的 .claude/settings.json:
Bash 命令重寫它時,請改用 FileChanged hook。
本頁上的 Bash 範例使用
jq 進行 JSON 解析。使用 brew install jq(macOS)、apt-get install jq(Debian 和 Ubuntu)安裝它,或參閱 jq 下載。阻止編輯受保護的檔案
防止 Claude 修改敏感檔案,如.env、package-lock.json 或 .git/ 中的任何內容。Claude 會收到解釋編輯被阻止原因的回饋,因此它可以調整其方法。
此範例使用 hook 呼叫的單獨指令檔。該指令檢查目標檔案路徑是否與受保護的模式列表相符,並以代碼 2 退出以阻止編輯。
1
建立 hook 指令
將此儲存到
.claude/hooks/protect-files.sh:2
在 macOS 和 Linux 上使指令可執行
Hook 指令必須可執行,Claude Code 才能執行它們:
3
註冊 hook
將
PreToolUse hook 新增到 .claude/settings.json,在任何 Edit 或 Write 工具呼叫之前執行指令:4
測試 hook
要求 Claude 將註解新增到您的
.env 檔案。Claude Code 在執行前阻止編輯,並將指令的 Blocked: 訊息作為回饋傳遞給 Claude。壓縮後重新注入上下文
當 Claude 的上下文視窗填滿時,壓縮會總結對話以釋放空間。這可能會遺失重要細節。使用帶有compact 匹配器的 SessionStart hook 在每次壓縮後重新注入關鍵上下文。
Claude Code 將您的命令寫入 stdout 的任何純文字新增到 Claude 的上下文中。此範例提醒 Claude 專案慣例和最近的工作。將此新增到您的專案根目錄中的 .claude/settings.json:
echo 替換為任何產生動態輸出的命令,如 git log --oneline -5 以顯示最近的提交。有關在每個工作階段開始時注入上下文,請考慮改用 CLAUDE.md。有關環境變數,請參閱參考中的 CLAUDE_ENV_FILE。
審計配置變更
追蹤工作階段期間設定或 skills 檔案何時變更。ConfigChange 事件在外部程序或編輯器修改配置檔案時觸發,因此您可以記錄變更以進行合規性檢查或阻止未授權的修改。
此範例將每個變更附加到審計日誌。將此新增到 ~/.claude/settings.json:
user_settings、project_settings、local_settings、policy_settings 或 skills。要阻止變更生效,以代碼 2 退出或傳回 {"decision": "block"}。有關完整的輸入架構,請參閱 ConfigChange 參考。
若要確認 hook 記錄變更,請在工作階段執行時在另一個編輯器中編輯設定檔,然後開啟 ~/claude-config-audit.log:hook 會為每個變更附加一行 JSON,包含時間戳記、來源和檔案路徑。
當目錄或檔案變更時重新載入環境
某些專案根據您所在的目錄設定不同的環境變數。direnv 之類的工具在您的 shell 中自動執行此操作,但 Claude 的 Bash 工具不會自行選取這些變更。 配對SessionStart hook 與 CwdChanged hook 可以修復此問題。SessionStart 載入您啟動時所在目錄的變數,CwdChanged 在 Claude 每次變更目錄時重新載入它們。兩者都寫入 CLAUDE_ENV_FILE,Claude Code 在每個 Bash 命令之前執行為指令碼前置。將此新增到 ~/.claude/settings.json:
.envrc 的目錄中執行一次 direnv allow,以便允許 direnv 載入它。如果您使用 devbox 或 nix 而不是 direnv,相同的模式適用於 devbox shellenv 或 devbox global shellenv 代替 direnv export bash。
若要對特定檔案而不是每次目錄變更做出反應,請使用 FileChanged 搭配 matcher 列出要監視的檔案名稱(以 | 分隔)。建立監視清單時,Claude Code 會將此值分割為字面檔案名稱,而不是作為正規表達式進行評估。有關輸入架構、watchPaths 輸出和 CLAUDE_ENV_FILE 詳細資訊,請參閱 FileChanged。此範例監視工作目錄中 .envrc 和 .env 的變更:
watchPaths 輸出和 CLAUDE_ENV_FILE 詳細資訊,請參閱 CwdChanged 和 FileChanged 參考項目。
自動批准特定權限提示
跳過您始終允許的工具呼叫的批准對話。此範例自動批准ExitPlanMode,這是 Claude 在完成呈現計畫並要求繼續時呼叫的工具,因此您不會在每次計畫準備好時被提示。
與上面的退出代碼範例不同,自動批准要求您的 hook 將 JSON 決策寫入 stdout。Claude Code 在即將要求您的權限時執行 PermissionRequest hooks,如果您的 hook 傳回 "behavior": "allow",Claude Code 會代表您回答請求。
匹配器將 hook 的範圍限制為僅 ExitPlanMode,因此不會影響其他提示。將此新增到 ~/.claude/settings.json:
setMode 項目的 updatedPermissions 陣列。mode 值是任何權限模式,如 default、acceptEdits 或 bypassPermissions,destination: "session" 僅將其應用於當前工作階段。
bypassPermissions 只有在您啟動工作階段時繞過模式已經可用的情況下才適用:--dangerously-skip-permissions、--permission-mode bypassPermissions、--allow-dangerously-skip-permissions 或使用者、--settings 或受管設定中的 permissions.defaultMode: "bypassPermissions"。如果繞過模式已被 permissions.disableBypassPermissionsMode 停用,或您是在受限模式中啟動工作階段,則它不適用。Claude Code 永遠不會將其儲存為 defaultMode。acceptEdits,您的 hook 會將此 JSON 寫入 stdout:
.* 上進行匹配或留空匹配器會自動批准每個工具權限提示,包括檔案寫入和 shell 命令。有關決策欄位的完整集合,請參閱 PermissionRequest 參考。
hooks 如何運作
Claude Code 在其生命週期的特定時間點觸發 hook 事件。當事件觸發時,Claude Code 會並行執行所有相符的 hooks;請參閱 Hook 處理程式欄位 以了解重複處理程式的處理方式。下表顯示每個事件及其觸發時機:
每個 hook 都有一個
type 決定其執行方式。大多數 hooks 使用 "type": "command",它執行 shell 命令。還有四種其他類型可用:
"type": "http":將事件資料 POST 到 URL。請參閱 HTTP hooks。"type": "mcp_tool":在已設定的 MCP 伺服器上呼叫工具。請參閱 MCP tool hooks。"type": "prompt":單輪 LLM 評估。請參閱 Prompt-based hooks。"type": "agent":具有工具存取的多輪驗證。Agent hooks 是實驗性的,可能會變更。請參閱 Agent-based hooks。
合併來自多個 hooks 的結果
當多個 hooks 相符同一事件時,每個 hook 的命令都會執行到完成,然後 Claude Code 才會合併結果。一個 hook 傳回deny 不會阻止同層 hooks 執行。不要依賴一個 hook 的 deny 來抑制另一個 hook 中的副作用。
所有相符的 hooks 完成後,Claude Code 會合併其輸出。對於 PreToolUse 權限決定,最嚴格的答案適用,順序為 deny、defer、ask、allow。來自 additionalContext 的文字會從每個 hook 保留並一起傳遞給 Claude。
下面的範例在 Bash 上註冊兩個 PreToolUse hooks。第一個將每個命令附加到日誌檔案並以 0 結束。第二個執行一個指令碼,當命令包含 rm -rf 時以 2 結束以拒絕:
rm -rf /tmp/build 時,兩個 hooks 並行執行。日誌 hook 將命令寫入 ~/.claude/bash.log 並以 0 結束,這表示沒有決定。護欄 hook 以 2 結束,這拒絕了工具呼叫。拒絕優先,所以 Claude Code 阻止命令並向 Claude 顯示護欄的 stderr。日誌項目仍然被寫入,因為日誌 hook 已經執行。
讀取輸入並傳回輸出
Hooks 通過 stdin、stdout、stderr 和結束代碼與 Claude Code 通訊。當事件觸發時,Claude Code 將事件特定資料作為 JSON 傳遞到您的指令碼的 stdin。您的指令碼讀取該資料,執行其工作,並通過結束代碼告訴 Claude Code 接下來要做什麼。Hook 輸入
每個事件都包含常見欄位,如session_id(會話的唯一 ID)和 cwd(事件觸發時的工作目錄),但每個事件類型都會新增不同的資料。當 Claude 執行 Bash 命令時,PreToolUse hook 在 stdin 上接收這些欄位:
hook_event_name:觸發 hook 的事件tool_name:Claude 即將使用的工具tool_input:Claude 傳遞給工具的引數。對於 Bash,其command欄位保存 shell 命令。
npm test 命令的 hook 輸入如下所示:
UserPromptSubmit hooks 改為取得 prompt 文字,SessionStart hooks 取得 startup、resume、clear、compact 或 fork 的 source,以此類推。請參閱參考中的 常見輸入欄位 以了解共享欄位,以及每個事件的部分以了解事件特定的結構描述。
Hook 輸出
您的指令碼通過寫入 stdout 或 stderr 並以特定代碼結束來告訴 Claude Code 接下來要做什麼。以下PreToolUse hook 阻止命令:
- 結束代碼 0:您的 hook 通過其結束代碼報告無異議。
- 結束代碼 2:Claude Code 阻止該動作。將原因寫入 stderr。它的位置取決於事件:某些事件將其提供給 Claude 作為回饋,以便它可以調整,其他事件將其顯示給使用者,還有一些(如
ConfigChange和Elicitation)不顯示任何訊息。某些事件無法被阻止:對於SessionStart和其他事件,結束代碼 2 向使用者顯示 stderr 並繼續執行。請參閱 每個事件的結束代碼 2 行為 以取得完整清單。 - 任何其他結束代碼:對於大多數事件,動作會以 非阻止性錯誤 繼續進行,除非該 hook 屬於 其失敗會阻止動作 的類型,或其 JSON 輸出通過驗證:
- 通過 schema 驗證的已解析物件:Claude Code 忽略結束代碼,JSON 單獨決定結果,hook 不會報告為錯誤。每個事件的例外情況(如
WorktreeCreate在任何非零結束代碼上失敗)列在參考的 結束代碼輸出 部分中。 - 未通過 schema 驗證的已解析物件,或 Claude Code 嘗試解析為 JSON 但不是有效 JSON 的 stdout:非阻止性錯誤;通知包含驗證或解析訊息。
- Claude Code 視為純文字 的 stdout,或空 stdout:動作以非阻止性錯誤進行。逐字稿顯示
<hook name> hook error通知,然後是 stderr 的第一行,前綴為Failed with non-blocking status code:。要擷取完整的 stderr,請使用claude --debug或在工作階段中執行/debug來啟用 偵錯日誌。
- 通過 schema 驗證的已解析物件:Claude Code 忽略結束代碼,JSON 單獨決定結果,hook 不會報告為錯誤。每個事件的例外情況(如
結構化 JSON 輸出
結束代碼只允許您阻止或保持沉默。為了獲得更多控制,結束代碼 0 並改為列印 JSON 物件到 stdout。使用結束代碼 2 以 stderr 訊息阻止,或使用結束代碼 0 和 JSON 進行結構化控制。每個 hook 選擇一種方法。有關混合它們時會發生什麼,請參閱 結束代碼輸出。
PreToolUse hook 可以拒絕工具呼叫並告訴 Claude 原因,或將其升級給使用者以供核准:
"deny",Claude Code 取消工具呼叫並將 permissionDecisionReason 回饋給 Claude。
在 PreToolUse 上,Claude Code 按如下方式處理每個 permissionDecision 值:
-
"allow":跳過互動式權限提示。拒絕和詢問規則(包括企業管理的拒絕清單)仍然適用,以下情況的提示也同樣適用:- 從 網路路徑 讀取
- 標記為
requiresUserInteraction的 MCP 工具 - 在該設定會傳達到 Claude Code 的工作階段中,您的組織設定為
ask的連接器工具
"allow"在 plan mode 中的作用,請參閱 plan mode 中的 hook 核准。 -
"deny":取消工具呼叫並將原因傳送給 Claude -
"ask":向使用者正常顯示權限提示
"defer" 在 非互動模式 中使用 -p 旗標時可用。它以保留的工具呼叫結束程序,以便 Agent SDK 包裝器可以收集輸入並繼續。請參閱參考中的 延遲工具呼叫以供稍後使用。
PreModelSwitch hook 傳回相同的 permissionDecision 欄位:"allow" 允許模型切換進行,"deny" 取消它。"ask" 在您在互動式會話中執行 /model 時要求您確認切換;在其他地方,Claude Code 將 "ask" 視為拒絕。請參閱 PreModelSwitch 決定控制。
其他事件使用不同的決定模式。例如,PostToolUse 和 Stop hooks 使用頂層 decision: "block" 欄位,而 PermissionRequest 使用 hookSpecificOutput.decision.behavior。請參閱參考中的 摘要表 以取得按事件的完整細目。
對於 UserPromptSubmit hooks,改為使用 hookSpecificOutput.additionalContext 將文字注入 Claude 的上下文。將 additionalContext 嵌套在 hookSpecificOutput 內;如果您將其放在 JSON 的頂層,Claude Code 會以無聲方式忽略它。例如,此輸出將目前分支狀態新增到每個提示:
type: "prompt" 的 Hooks 以不同方式處理輸出:請參閱 Prompt-based hooks。
使用匹配器篩選 hooks
沒有匹配器,hook 會在其事件的每次出現時觸發。匹配器可讓您縮小範圍。例如,如果您只想在檔案編輯後執行格式化程式,而不是在每次工具呼叫後,請將匹配器新增到您的PostToolUse hook:
"Edit|Write" 匹配器只在 Claude 使用 Edit 或 Write 工具時觸發,不在使用 Bash、Read 或任何其他工具時觸發。逗號以相同方式分隔替代項,所以 "Edit, Write" 是等效的。請參閱 匹配器模式 以了解純名稱和正規表達式的評估方式。
Claude 也可以通過執行 shell 命令來建立或修改檔案。如果您的 hook 必須看到每個檔案變更,例如用於合規性掃描或稽核日誌,請新增一個
Stop hook,每輪掃描一次工作樹。對於每次呼叫的覆蓋範圍,也請匹配 Bash|PowerShell 並讓您的指令碼使用 git status --porcelain 列出修改和未追蹤的檔案。PowerShell hook 輸入部分 說明了為什麼僅匹配 Bash 是不夠的。要在特定檔案在磁碟上變更時執行 hook,無論是什麼寫入它,請使用 FileChanged hook。
下面的標籤顯示不同事件類型上的一些其他匹配器。
- 記錄每個 Bash 命令
- 匹配 MCP 工具
- 在會話結束時清理
僅匹配
Bash 工具呼叫並將每個命令記錄到檔案。PostToolUse 事件在命令完成後觸發,所以 tool_input.command 包含執行的內容。hook 在 stdin 上接收事件資料作為 JSON,jq -r '.tool_input.command' 僅提取命令字串,>> 將其附加到日誌檔案:使用 if 欄位按工具名稱和引數篩選
if 欄位使用 權限規則語法 按工具名稱和引數一起篩選 hooks,因此 hook 程序只在工具呼叫相符時生成。這超越了 matcher,它只在工具名稱級別按工具名稱篩選。
例如,此設定只在 Claude 使用 git 命令而不是所有 Bash 命令時執行 hook:
if 模式的形狀和 Claude 正在呼叫的 Bash 命令:
當 Claude Code 無法確定 Bash 輸入執行哪些命令時,無論模式如何,它都會執行您的 hook。Bash 匹配表 涵蓋 Claude Code 可以和不能按子命令縮小的命令形狀。因為篩選是盡力而為,請使用 權限系統 而不是 hook 來強制執行硬允許或拒絕。
if 欄位接受與權限規則相同的模式:"Bash(git *)"、"Edit(*.ts)" 等。要匹配多個工具名稱,請使用各自具有自己 if 值的單獨處理程式,或在支援管道替代的 matcher 級別進行匹配。
if 只適用於工具事件:PreToolUse、PostToolUse、PostToolUseFailure、PermissionRequest 和 PermissionDenied。將其新增到任何其他事件會防止 hook 執行。
設定 hook 位置
您新增 hook 的位置決定其範圍:
在 Claude Code 中執行
/hooks 以瀏覽按事件分組的所有已設定 hooks。
要停用 hooks,請在您的設定檔案中設定 "disableAllHooks": true。Claude Code 讀取 設定優先順序 適用後剩下的值,因此專案的設定檔案可以覆蓋您的。在受管理的設定中設定的 Hooks 仍然執行,除非 disableAllHooks 也在那裡設定。對於每個級別的完整範圍,請參閱 disableAllHooks。
如果您在 Claude Code 執行時直接編輯設定檔案,檔案監視程式通常會自動選取 hook 變更。
基於提示的 hooks
對於需要判斷而不是確定性規則的決策,使用type: "prompt" hooks。Claude Code 不執行 shell 命令,而是將您的提示和 hook 的輸入資料傳送到 Claude 模型以做出決策。如果您需要更多功能,可以使用 model 欄位指定不同的模型。
模型的唯一工作是傳回其決策作為 JSON:
"ok": true:操作繼續"ok": false:發生的情況取決於事件:Stop和SubagentStop:reason被回饋給 Claude,以便它繼續工作,除非回應也設定"impossible": true以標記該條件為永遠無法滿足的條件,在這種情況下 Claude Code 允許停止並結束回合PreToolUse:工具呼叫被拒絕;預設情況下回合結束,拒絕reason在聊天中顯示為警告行。在 hook 上設定continueOnBlock: true以改為將reason傳回給 Claude 作為工具錯誤,以便它可以調整並繼續。在 v2.1.210 之前,拒絕reason被傳回給 Claude 作為工具錯誤,回合繼續PostToolUse:預設情況下回合結束,reason在聊天中顯示為警告行。設定continueOnBlock: true以將reason回饋給 Claude 並改為繼續回合PostToolBatch、UserPromptSubmit和UserPromptExpansion:回合結束,reason在聊天中顯示為警告行
Stop hook 詢問模型是否所有請求的任務都已完成。如果模型傳回 "ok": false 因為條件尚未滿足,Claude 會繼續工作並使用 reason 作為其下一個指令:
基於代理的 hooks
當驗證需要檢查檔案或執行命令時,使用type: "agent" hooks。與只進行單個 LLM 呼叫的提示 hooks 不同,代理 hooks 生成一個 subagent,可以讀取檔案、搜尋程式碼和使用其他工具在傳回決策之前驗證條件。
代理 hooks 使用 "ok" / "reason" 回應格式,預設超時時間更長(60 秒),最多 50 個工具使用輪次。它們不支援提示 hook 的 impossible 欄位。當 ok: false 時,Claude Code 處理代理 hook 的方式與處理在同一事件上設定 continueOnBlock: true 的提示 hook 相同,因此在 PreToolUse 和 PostToolUse 上輪次會繼續;代理 hooks 沒有 continueOnBlock 欄位。請參閱代理 hook 配置以了解欄位,包括 Claude Code 用 hook 的 JSON 輸入替換的 $ARGUMENTS 預留位置。
此範例驗證在允許 Claude 停止之前測試通過:
HTTP hooks
使用type: "http" hooks 將事件資料 POST 到 HTTP 端點,而不是執行 shell 命令。端點接收命令 hook 在 stdin 上接收的相同 JSON,並使用相同的 JSON 格式透過 HTTP 回應主體傳回結果。
HTTP hooks 在您希望 Web 伺服器、雲端函數或外部服務處理 hook 邏輯時很有用:例如,一個共享的審計服務,在整個團隊中記錄工具使用事件。
此範例將每個工具使用 POST 到本機記錄服務:
- 2xx 狀態:若要阻止工具呼叫,請在主體中傳回適當的
hookSpecificOutput欄位。 - 任何其他狀態,或請求失敗:Claude Code 會回報非阻斷性錯誤並讓該動作繼續進行。若要讓失敗的端點阻止該動作,請在 hook 上設定
onFailure: "block"。
$VAR_NAME 或 ${VAR_NAME} 語法的環境變數插值。只有在 allowedEnvVars 陣列中列出的變數才會被解析;所有其他 $VAR 參考保持為空。
有關完整的配置選項和回應處理,請參閱參考中的 HTTP hooks。
限制和故障排除
限制
設計 hooks 時請記住這些限制:- 命令 hooks 只透過 stdout、stderr 和退出代碼通訊。它們無法觸發
/命令或工具呼叫。透過additionalContext傳回的文字會作為系統提醒注入,Claude 將其讀取為純文字。HTTP hooks 改為透過回應主體通訊。 - Hook 超時因類型而異。透過
timeout欄位(以秒為單位)按 hook 覆寫。command、http、mcp_tool:10 分鐘。Claude Code 將UserPromptSubmit、PreModelSwitch和PostModelSwitchhooks 的預設值降低至 30 秒,將MessageDisplay的預設值降低至 10 秒。prompt:30 秒。agent:60 秒。SessionEndhooks 的任何類型共享 1.5 秒的預算。如果您的設定為 hook 設定了更長的timeout,Claude Code 會將預算提高以匹配,最多 60 秒。
PostToolUsehooks 無法撤銷操作,因為工具已經執行。PermissionRequesthook 在 Claude Code 即將要求您授予權限時觸發,或在它原本會自動拒絕無法顯示提示的呼叫時觸發。在使用-p旗標的非互動模式中,它們在dontAsk模式以外仍會執行,而沒有任何 hook 做出決策、也沒有其他機制能回應的呼叫會被拒絕。Stophooks 在 Claude 完成回應時觸發,而不僅在任務完成時。它們在使用者中斷時不觸發。API 錯誤觸發 StopFailure 代替。- 當多個
PreToolUsehooks 傳回updatedInput以重寫工具的引數時,最後完成的會獲勝。由於 hooks 並行執行,順序是非確定性的。避免有多個 hook 修改同一工具的輸入。
Hooks 和權限模式
PreToolUse hooks 在任何權限模式檢查之前觸發,在每個權限模式中,包括 dontAsk。傳回 permissionDecision: "deny" 的 hook 會阻止工具,即使在 bypassPermissions 模式或使用 --dangerously-skip-permissions。這讓您強制執行使用者無法透過變更其權限模式來繞過的原則。
反之則不成立:設定檔和外掛 hooks/hooks.json 中的 hook 可以加強限制,但不能放寬超過權限規則允許的範圍。傳回 "allow" 的 hook 不會繞過來自設定的拒絕規則,也無法抑制以下情況的提示:
- 從網路路徑讀取
- 標記為
requiresUserInteraction的 MCP 工具 - 在該設定會傳達到 Claude Code 的工作階段中,您的組織設定為
ask的連接器工具
PreToolUse hook 對檔案編輯傳回 "allow",您會得到與沒有 hook 時該編輯相同的提示、阻止或核准。若要解除 hook 核准的這項限制,請核准計畫或切換到其他權限模式。
您安裝的 mod 如果處理 tool.check,可以核准您的 PreToolUse hook 阻止的呼叫,除非該 hook 在受管設定中。在 plan mode 中,當此類呼叫為唯讀時,mod 可以核准它,但不能核准檔案編輯或其他非唯讀的呼叫。使用 hook 擴展權限列出哪些規則優先於 mod。
Hook 未觸發
Hook 已配置但從不執行。- 執行
/hooks並確認 hook 出現在正確的事件下 - 檢查匹配器模式是否與工具名稱完全相符。匹配器區分大小寫
- 驗證您觸發的是正確的事件類型:
PreToolUse在工具執行前觸發,PostToolUse在之後觸發。PermissionRequesthook 在 Claude Code 即將要求您的權限時觸發;請參閱限制以了解非互動模式的情況
Hook 輸出中的錯誤
您在文字記錄中看到類似「PreToolUse hook error: …」的訊息。-
您的指令意外以非零代碼退出。透過管道傳輸範例 JSON 來手動測試它:
-
如果您看到「command not found」,使用絕對路徑或
${CLAUDE_PROJECT_DIR}來參考指令。為了完全避免 shell 引用,添加"args": []以切換到 exec 形式,它直接生成指令而不使用 shell -
如果您看到「jq: command not found」,安裝
jq或使用 Python/Node.js 進行 JSON 解析 -
如果訊息包含
blocking because Git Bash wasn't found,表示您在 Windows 上、Claude Code 找不到 Git Bash,且失敗或逾時的 hook 阻止了工具呼叫。請參閱在沒有 Git Bash 的 Windows 上失敗的 hook 以了解修正方法 -
如果通知顯示 JSON 驗證訊息,您的 hook 的 stdout 解析為 JSON 但未通過架構驗證。如果顯示 JSON 解析訊息,stdout 看起來像 JSON 物件但不是有效的 JSON。即使在退出 0 時也會發生這兩種情況。
要修復解析失敗,使用 JSON 編碼器(例如
jq)而不是字串連接來建立有效負載,以便值內的引號和反斜線被轉義。參考的退出代碼輸出部分涵蓋了退出代碼和 JSON 組合 -
如果指令根本沒有執行,使其可執行:
chmod +x ./my-hook.sh
/hooks 顯示未配置任何 hooks
您編輯了設定檔但 hooks 未出現在選單中。
- 檔案編輯通常會自動選取。如果在幾秒鐘後仍未出現,檔案監視程式可能已錯過變更:重新啟動您的工作階段以強制重新載入。
- 驗證您的 JSON 有效:不允許尾隨逗號和註解
- 確認設定檔在正確的位置:
.claude/settings.json用於專案 hooks,~/.claude/settings.json用於全域 hooks - 如果選單顯示
Only hooks from managed settings run here,表示您的組織已設定allowManagedHooksOnly。您的使用者、專案和本機設定檔中的 hook 不會執行,也不會列出
Stop hook 觸發區塊上限
Claude 繼續工作而不是停止,然後以警告結束回合,表示 Stop hook 連續阻止了太多次。 當 Stop hook 連續阻止八次、且期間 Claude 沒有任何工具呼叫時,Claude Code 會覆寫它。您的 hook 指令碼需要檢查它是否已經觸發了延續。從 JSON 輸入解析stop_hook_active 欄位,如果為 true 則提前退出:
CLAUDE_CODE_STOP_HOOK_BLOCK_CAP 提高上限。
Hook JSON 沒有效果
您的 hook 列印有效的 JSON,但決策沒有生效,文字記錄中也沒有出現錯誤。檢查哪個原因適用:- JSON 前的額外輸出:其他東西首先寫入 stdout,通常是您 shell 設定檔中的無條件
echo,所以輸出不再以{開頭。請參閱JSON 前的 shell 設定檔輸出。 - 欄位位置錯誤:將每個欄位的位置與 JSON 輸出格式進行比較。例如,
permissionDecision應該在hookSpecificOutput內,而不是在頂層。請參閱位於錯誤層級的欄位。
JSON 前的 shell 設定檔輸出
Hook 在非互動式 shell 中執行,但 Git Bash 和某些設定(例如BASH_ENV 指向 ~/.bashrc)仍然會載入您的設定檔,而設定檔列印的任何內容都會在您 hook 的 JSON 之前到達 stdout:
{ 開頭的輸出讀取為純文字,因此您的 JSON 會被忽略。由於 hook 以 0 退出,逐字稿中也不會顯示任何錯誤。要檢查是否為此原因,請使用 claude --debug 啟動 Claude Code,觸發 hook,然後在除錯日誌中搜尋 Hook output does not start with {。要修復此問題,請在您的設定檔中包裝 echo 陳述式,使其只在互動式 shell 中執行:
$- 變數包含 shell 旗標,i 表示互動式。Hooks 在非互動式 shell 中執行,因此 echo 被跳過。
位於錯誤層級的欄位
當您的 hook 在頂層而不是在hookSpecificOutput 內傳回 permissionDecision 或 additionalContext 時,JSON 仍然會解析,Claude Code 會忽略放置錯誤的欄位而不報告錯誤。要查看它忽略了哪些欄位,使用 claude --debug 啟動 Claude Code 並在除錯日誌中搜尋 Hook JSON output had unrecognized keys。
檢查 hook 做了什麼
按Ctrl+O 開啟逐字稿檢視,並尋找 hook 的結果:
- 成功:您看不到任何內容,除非 hook 的 JSON 顯示某些內容,例如
systemMessage或 Stop hook 回饋。- 要確認 hook 已執行,請檢查其效果,例如重新格式化的檔案
- 阻止錯誤:在大多數事件上,您會看到隨阻止一起傳回的訊息,例如
Blocked: rm commands are not allowed。在少數事件上,例如ConfigChange和Elicitation,您不會看到任何訊息。退出碼 2 說明訊息的來源。 - 非阻止錯誤:您會看到
<hook name> hook error通知,其中包含簡短說明,例如Failed with non-blocking status code:之後的 stderr 第一行,或 JSON 驗證或解析訊息。操作仍會繼續進行。
claude --debug-file /tmp/claude.log 啟動 Claude Code 以寫入已知路徑,然後在另一個終端機中執行 tail -f /tmp/claude.log。如果您啟動時沒有該旗標,請在工作階段中執行 /debug 以啟用日誌並找到日誌路徑。
深入瞭解
- Hooks 參考:完整的事件架構、JSON 輸出格式、非同步 hooks 和 MCP 工具 hooks
- 安全考量:在共享或生產環境中部署 hooks 之前進行檢查
- Bash 命令驗證器範例:完整的參考實現