設定您的第一個 hook
若要建立 hook,請將hooks 區塊新增到設定檔。本逐步解說建立一個桌面通知 hook,因此每當 Claude 等待您的輸入而不是監視終端時,您都會收到警報。
將 hook 新增到您的設定
開啟 如果您的設定檔已經有 您也可以透過在 CLI 中描述您想要的內容,要求 Claude 為您編寫 hook。
~/.claude/settings.json 並新增 Notification hook。下面的範例使用 osascript 進行 macOS;有關 Linux 和 Windows 命令,請參閱當 Claude 需要輸入時收到通知。hooks 鍵,請將 Notification 作為現有事件鍵的同級項目新增,而不是替換整個物件。每個事件名稱是單個 hooks 物件內的鍵:驗證配置
輸入
/hooks 以開啟 hooks 瀏覽器。您將看到所有可用 hook 事件的列表,每個配置了 hooks 的事件旁邊都有一個計數。選擇 Notification 以確認您的新 hook 出現在列表中。選擇 hook 會顯示其詳細資訊:事件、匹配器、類型、來源檔案和命令。您可以自動化的內容
Hooks 讓您在 Claude Code 生命週期的關鍵點執行程式碼:編輯後格式化檔案、在執行前阻止命令、當 Claude 需要輸入時發送通知、在工作階段開始時注入上下文等。有關 hook 事件的完整列表,請參閱 Hooks 參考。 每個範例都包含一個現成可用的配置區塊,您可以將其新增到設定檔。最常見的模式:當 Claude 需要輸入時收到通知
每當 Claude 完成工作並需要您的輸入時收到桌面通知,這樣您可以切換到其他任務而無需檢查終端。 此 hook 使用Notification 事件,當 Claude 等待輸入或權限時觸發。下面的每個標籤使用平台的原生通知命令。將此新增到 ~/.claude/settings.json:
- macOS
- Linux
- Windows (PowerShell)
如果沒有出現通知
如果沒有出現通知
osascript 透過內建的 Script Editor 應用程式路由通知。如果 Script Editor 沒有通知權限,命令會無聲地失敗,macOS 不會提示您授予它。在終端中執行一次以使 Script Editor 出現在您的通知設定中:編輯後自動格式化程式碼
在 Claude 編輯的每個檔案上自動執行 Prettier,以便格式保持一致而無需手動干預。 此 hook 使用PostToolUse 事件搭配 Edit|Write 匹配器,因此它只在檔案編輯工具之後執行。該命令使用 jq 提取編輯的檔案路徑並將其傳遞給 Prettier。將此新增到您的專案根目錄中的 .claude/settings.json:
本頁上的 Bash 範例使用
jq 進行 JSON 解析。使用 brew install jq(macOS)、apt-get install jq(Debian/Ubuntu)安裝它,或參閱 jq 下載。阻止編輯受保護的檔案
防止 Claude 修改敏感檔案,如.env、package-lock.json 或 .git/ 中的任何內容。Claude 會收到解釋編輯被阻止原因的回饋,因此它可以調整其方法。
此範例使用 hook 呼叫的單獨指令檔。該指令檢查目標檔案路徑是否與受保護的模式列表相符,並以代碼 2 退出以阻止編輯。
壓縮後重新注入上下文
當 Claude 的上下文視窗填滿時,壓縮會總結對話以釋放空間。這可能會遺失重要細節。使用帶有compact 匹配器的 SessionStart hook 在每次壓縮後重新注入關鍵上下文。
您的命令寫入 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 參考。
當目錄或檔案變更時重新載入環境
某些專案根據您所在的目錄設定不同的環境變數。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 列出要監視的檔案名稱(以 | 分隔)。若要建立監視清單,此值會分割為字面檔案名稱,而不是作為正規表達式進行評估。有關輸入架構、watchPaths 輸出和 CLAUDE_ENV_FILE 詳細資訊,請參閱 FileChanged。此範例監視工作目錄中 .envrc 和 .env 的變更:
watchPaths 輸出和 CLAUDE_ENV_FILE 詳細資訊,請參閱 CwdChanged 和 FileChanged 參考項目。
自動批准特定權限提示
跳過您始終允許的工具呼叫的批准對話。此範例自動批准ExitPlanMode,這是 Claude 在完成呈現計畫並要求繼續時呼叫的工具,因此您不會在每次計畫準備好時被提示。
與上面的退出代碼範例不同,自動批准要求您的 hook 將 JSON 決策寫入 stdout。PermissionRequest hook 在 Claude Code 即將顯示權限對話時觸發,傳回 "behavior": "allow" 會代表您回答它。
匹配器將 hook 的範圍限制為僅 ExitPlanMode,因此不會影響其他提示。將此新增到 ~/.claude/settings.json:
setMode 項目的 updatedPermissions 陣列。mode 值是任何權限模式,如 default、acceptEdits 或 bypassPermissions,destination: "session" 僅將其應用於當前工作階段。
bypassPermissions 只有在工作階段已經啟用了繞過模式時才適用:--dangerously-skip-permissions、--permission-mode bypassPermissions、--allow-dangerously-skip-permissions 或設定中的 permissions.defaultMode: "bypassPermissions",且未被 permissions.disableBypassPermissionsMode 禁用。它永遠不會被持久化為 defaultMode。acceptEdits,您的 hook 會將此 JSON 寫入 stdout:
.* 上進行匹配或留空匹配器會自動批准每個權限提示,包括檔案寫入和 shell 命令。有關決策欄位的完整集合,請參閱 PermissionRequest 參考。
Hooks 如何工作
Hook 事件在 Claude Code 的特定生命週期點觸發。當事件觸發時,所有匹配的 hooks 並行執行,相同的 hook 命令會自動去重。下表顯示每個事件及其觸發時間:| Event | When it fires |
|---|---|
SessionStart | When a session begins or resumes |
UserPromptSubmit | When you submit a prompt, before Claude processes it |
UserPromptExpansion | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
PreToolUse | Before a tool call executes. Can block it |
PermissionRequest | When a permission dialog appears |
PermissionDenied | When a tool call is denied by the auto mode classifier. Return {retry: true} to tell the model it may retry the denied tool call |
PostToolUse | After a tool call succeeds |
PostToolUseFailure | After a tool call fails |
Notification | When Claude Code sends a notification |
SubagentStart | When a subagent is spawned |
SubagentStop | When a subagent finishes |
TaskCreated | When a task is being created via TaskCreate |
TaskCompleted | When a task is being marked as completed |
Stop | When Claude finishes responding |
StopFailure | When the turn ends due to an API error. Output and exit code are ignored |
TeammateIdle | When an agent team teammate is about to go idle |
InstructionsLoaded | When a CLAUDE.md or .claude/rules/*.md file is loaded into context. Fires at session start and when files are lazily loaded during a session |
ConfigChange | When a configuration file changes during a session |
CwdChanged | When the working directory changes, for example when Claude executes a cd command. Useful for reactive environment management with tools like direnv |
FileChanged | When a watched file changes on disk. The matcher field specifies which filenames to watch |
WorktreeCreate | When a worktree is being created via --worktree or isolation: "worktree". Replaces default git behavior |
WorktreeRemove | When a worktree is being removed, either at session exit or when a subagent finishes |
PreCompact | Before context compaction |
PostCompact | After context compaction completes |
Elicitation | When an MCP server requests user input during a tool call |
ElicitationResult | After a user responds to an MCP elicitation, before the response is sent back to the server |
SessionEnd | When a session terminates |
deny 的 PreToolUse hook 會取消工具呼叫,無論其他的傳回什麼。一個 hook 傳回 ask 會強制權限提示,即使其餘的傳回 allow。來自 additionalContext 的文字會從每個 hook 保留並一起傳遞給 Claude。
每個 hook 都有一個 type 來決定它如何執行。大多數 hooks 使用 "type": "command",它執行 shell 命令。還有三種其他類型可用:
"type": "http":POST 事件資料到 URL。請參閱 HTTP hooks。"type": "prompt":單輪 LLM 評估。請參閱基於提示的 hooks。"type": "agent":具有工具存取的多輪驗證。代理 hooks 是實驗性的,可能會改變。請參閱基於代理的 hooks。
讀取輸入並傳回輸出
Hooks 透過 stdin、stdout、stderr 和退出代碼與 Claude Code 通訊。當事件觸發時,Claude Code 將事件特定的資料作為 JSON 傳遞到您的指令的 stdin。您的指令讀取該資料、執行其工作,並透過退出代碼告訴 Claude Code 接下來要做什麼。Hook 輸入
每個事件都包含常見欄位,如session_id 和 cwd,但每個事件類型都新增不同的資料。例如,當 Claude 執行 Bash 命令時,PreToolUse hook 在 stdin 上接收類似以下內容:
UserPromptSubmit hooks 改為取得 prompt 文字,SessionStart hooks 取得 source(startup、resume、clear、compact),等等。有關共享欄位,請參閱參考中的常見輸入欄位,以及每個事件的部分以了解事件特定的架構。
Hook 輸出
您的指令透過寫入 stdout 或 stderr 並以特定代碼退出來告訴 Claude Code 接下來要做什麼。例如,想要阻止命令的PreToolUse hook:
- Exit 0:操作繼續。對於
UserPromptSubmit和SessionStarthooks,您寫入 stdout 的任何內容都會新增到 Claude 的上下文中。 - Exit 2:操作被阻止。寫入原因到 stderr,Claude 會收到它作為回饋,以便它可以調整。
- 任何其他退出代碼:操作繼續。文字記錄顯示
<hook name> hook error通知,後面跟著 stderr 的第一行;完整的 stderr 進入除錯日誌。
結構化 JSON 輸出
退出代碼給您兩個選項:允許或阻止。為了獲得更多控制,退出 0 並改為將 JSON 物件列印到 stdout。使用 exit 2 以 stderr 訊息阻止,或使用 exit 0 和 JSON 進行結構化控制。不要混合它們:Claude Code 在您退出 2 時忽略 JSON。
PreToolUse hook 可以拒絕工具呼叫並告訴 Claude 為什麼,或將其升級給使用者以獲得批准:
permissionDecision 並取消工具呼叫,然後將 permissionDecisionReason 回饋給 Claude。這些 permissionDecision 值特定於 PreToolUse:
"allow":跳過互動式權限提示。拒絕和詢問規則,包括企業受管拒絕清單,仍然適用"deny":取消工具呼叫並將原因傳送給 Claude"ask":照常向使用者顯示權限提示
"defer" 在非互動模式中使用 -p 旗標時可用。它以保留的工具呼叫退出程序,以便 Agent SDK 包裝器可以收集輸入並繼續。有關詳細資訊,請參閱參考中的延遲工具呼叫以供稍後使用。
傳回 "allow" 會跳過互動式提示,但不會覆蓋權限規則。如果拒絕規則與工具呼叫相符,即使您的 hook 傳回 "allow",呼叫也會被阻止。如果詢問規則相符,使用者仍會被提示。這意味著來自任何設定範圍(包括受管理的設定)的拒絕規則始終優先於 hook 批准。
其他事件使用不同的決策模式。例如,PostToolUse 和 Stop hooks 使用頂級 decision: "block" 欄位,而 PermissionRequest 使用 hookSpecificOutput.decision.behavior。有關按事件的完整分解,請參閱參考中的摘要表。
對於 UserPromptSubmit hooks,改用 additionalContext 將文字注入到 Claude 的上下文中。基於提示的 hooks(type: "prompt")以不同方式處理輸出:請參閱基於提示的 hooks。
使用匹配器篩選 hooks
沒有匹配器,hook 會在其事件的每次出現時觸發。匹配器讓您縮小範圍。例如,如果您只想在檔案編輯後執行格式化程式(而不是在每次工具呼叫後),請將匹配器新增到您的PostToolUse hook:
"Edit|Write" 匹配器只在 Claude 使用 Edit 或 Write 工具時觸發,而不是在它使用 Bash、Read 或任何其他工具時。請參閱匹配器模式以了解純名稱和正規表達式如何被評估。
每個事件類型都在特定欄位上進行匹配:
| 事件 | 匹配器篩選的內容 | 範例匹配器值 |
|---|---|---|
PreToolUse、PostToolUse、PostToolUseFailure、PermissionRequest、PermissionDenied | 工具名稱 | Bash、Edit|Write、mcp__.* |
SessionStart | 工作階段如何開始 | startup、resume、clear、compact |
SessionEnd | 工作階段為什麼結束 | clear、resume、logout、prompt_input_exit、bypass_permissions_disabled、other |
Notification | 通知類型 | permission_prompt、idle_prompt、auth_success、elicitation_dialog |
SubagentStart | 代理類型 | Bash、Explore、Plan 或自訂代理名稱 |
PreCompact、PostCompact | 什麼觸發了壓縮 | manual、auto |
SubagentStop | 代理類型 | 與 SubagentStart 相同的值 |
ConfigChange | 配置來源 | user_settings、project_settings、local_settings、policy_settings、skills |
StopFailure | 錯誤類型 | rate_limit、authentication_failed、billing_error、invalid_request、server_error、max_output_tokens、unknown |
InstructionsLoaded | 載入原因 | session_start、nested_traversal、path_glob_match、include、compact |
Elicitation | MCP 伺服器名稱 | 您配置的 MCP 伺服器名稱 |
ElicitationResult | MCP 伺服器名稱 | 與 Elicitation 相同的值 |
FileChanged | 字面檔案名稱以監視(請參閱 FileChanged) | .envrc|.env |
UserPromptSubmit、Stop、TeammateIdle、TaskCreated、TaskCompleted、WorktreeCreate、WorktreeRemove、CwdChanged | 不支援匹配器 | 始終在每次出現時觸發 |
- 記錄每個 Bash 命令
- 匹配 MCP 工具
- 在工作階段結束時清理
只匹配
Bash 工具呼叫並將每個命令記錄到檔案。PostToolUse 事件在命令完成後觸發,因此 tool_input.command 包含執行的內容。hook 在 stdin 上接收事件資料作為 JSON,jq -r '.tool_input.command' 只提取命令字串,>> 將其附加到日誌檔案:使用 if 欄位按工具名稱和引數篩選
if 欄位需要 Claude Code v2.1.85 或更新版本。較早的版本會忽略它並在每次匹配的呼叫上執行 hook。if 欄位使用權限規則語法按工具名稱和引數一起篩選 hooks,因此 hook 程序只在工具呼叫相符時生成,或當 Bash 命令太複雜而無法解析時。這超越了 matcher,它只在工具名稱級別篩選。
例如,若要只在 Claude 使用 git 命令而不是所有 Bash 命令時執行 hook:
git * 相符時生成,或當命令太複雜而無法解析為子命令時。對於複合命令(如 npm test && git push),Claude Code 評估每個子命令並觸發 hook,因為 git push 相符。if 欄位接受與權限規則相同的模式:"Bash(git *)"、"Edit(*.ts)" 等。若要匹配多個工具名稱,請使用每個都有自己的 if 值的單獨處理程式,或在 matcher 級別進行匹配,其中支援管道交替。
if 只適用於工具事件:PreToolUse、PostToolUse、PostToolUseFailure 和 PermissionRequest。將其新增到任何其他事件會防止 hook 執行。
配置 hook 位置
您新增 hook 的位置決定了其範圍:
在 Claude Code 中執行
/hooks 以瀏覽按事件分組的所有配置的 hooks。若要一次禁用所有 hooks,請在設定檔中設定 "disableAllHooks": true。
如果您在 Claude Code 執行時直接編輯設定檔,檔案監視程式通常會自動選取 hook 變更。
基於提示的 hooks
對於需要判斷而不是確定性規則的決策,使用type: "prompt" hooks。Claude Code 不執行 shell 命令,而是將您的提示和 hook 的輸入資料傳送到 Claude 模型(預設為 Haiku)以做出決策。如果您需要更多功能,可以使用 model 欄位指定不同的模型。
模型的唯一工作是傳回 yes/no 決策作為 JSON:
"ok": true:操作繼續"ok": false:操作被阻止。模型的"reason"被回饋給 Claude,以便它可以調整。
Stop hook 詢問模型是否所有請求的任務都已完成。如果模型傳回 "ok": false,Claude 會繼續工作並使用 reason 作為其下一個指令:
基於代理的 hooks
當驗證需要檢查檔案或執行命令時,使用type: "agent" hooks。與只進行單個 LLM 呼叫的提示 hooks 不同,代理 hooks 生成一個 subagent,可以讀取檔案、搜尋程式碼和使用其他工具在傳回決策之前驗證條件。
代理 hooks 使用與提示 hooks 相同的 "ok" / "reason" 回應格式,但預設超時時間更長(60 秒)且最多 50 個工具使用輪次。
此範例驗證在允許 Claude 停止之前測試通過:
HTTP hooks
使用type: "http" hooks 將事件資料 POST 到 HTTP 端點,而不是執行 shell 命令。端點接收命令 hook 在 stdin 上接收的相同 JSON,並使用相同的 JSON 格式透過 HTTP 回應主體傳回結果。
HTTP hooks 在您希望 Web 伺服器、雲端函數或外部服務處理 hook 邏輯時很有用:例如,一個共享的審計服務,在整個團隊中記錄工具使用事件。
此範例將每個工具使用 POST 到本機記錄服務:
hookSpecificOutput 欄位。HTTP 狀態代碼本身無法阻止操作。
標頭值支援使用 $VAR_NAME 或 ${VAR_NAME} 語法的環境變數插值。只有在 allowedEnvVars 陣列中列出的變數才會被解析;所有其他 $VAR 參考保持為空。
有關完整的配置選項和回應處理,請參閱參考中的 HTTP hooks。
限制和故障排除
限制
- 命令 hooks 只透過 stdout、stderr 和退出代碼通訊。它們無法觸發
/命令或工具呼叫。透過additionalContext傳回的文字會作為系統提醒注入,Claude 將其讀取為純文字。HTTP hooks 改為透過回應主體通訊。 - Hook 超時預設為 10 分鐘,可透過
timeout欄位(以秒為單位)按 hook 配置。 PostToolUsehooks 無法撤銷操作,因為工具已經執行。PermissionRequesthooks 在非互動模式(-p)中不觸發。對於自動化權限決策,使用PreToolUsehooks。Stophooks 在 Claude 完成回應時觸發,而不僅在任務完成時。它們在使用者中斷時不觸發。API 錯誤觸發 StopFailure 代替。- 當多個 PreToolUse hooks 傳回
updatedInput以重寫工具的引數時,最後完成的會獲勝。由於 hooks 並行執行,順序是非確定性的。避免有多個 hook 修改同一工具的輸入。
Hooks 和權限模式
PreToolUse hooks 在任何權限模式檢查之前觸發。傳回permissionDecision: "deny" 的 hook 會阻止工具,即使在 bypassPermissions 模式或使用 --dangerously-skip-permissions。這讓您強制執行使用者無法透過變更其權限模式來繞過的原則。
反面不成立:傳回 "allow" 的 hook 不會繞過來自設定的拒絕規則。Hooks 可以加強限制,但不能放寬超過權限規則允許的限制。
Hook 未觸發
Hook 已配置但從不執行。- 執行
/hooks並確認 hook 出現在正確的事件下 - 檢查匹配器模式是否與工具名稱完全相符(匹配器區分大小寫)
- 驗證您觸發的是正確的事件類型(例如,
PreToolUse在工具執行前觸發,PostToolUse在之後觸發) - 如果在非互動模式(
-p)中使用PermissionRequesthooks,改用PreToolUse
Hook 輸出中的錯誤
您在文字記錄中看到類似「PreToolUse hook error: …」的訊息。- 您的指令意外以非零代碼退出。透過管道傳輸範例 JSON 來手動測試它:
- 如果您看到「command not found」,使用絕對路徑或
$CLAUDE_PROJECT_DIR來參考指令 - 如果您看到「jq: command not found」,安裝
jq或使用 Python/Node.js 進行 JSON 解析 - 如果指令根本沒有執行,使其可執行:
chmod +x ./my-hook.sh
/hooks 顯示未配置任何 hooks
您編輯了設定檔但 hooks 未出現在選單中。
- 檔案編輯通常會自動選取。如果在幾秒鐘後仍未出現,檔案監視程式可能已錯過變更:重新啟動您的工作階段以強制重新載入。
- 驗證您的 JSON 有效(不允許尾隨逗號和註解)
- 確認設定檔在正確的位置:
.claude/settings.json用於專案 hooks,~/.claude/settings.json用於全域 hooks
Stop hook 永遠執行
Claude 在無限迴圈中繼續工作而不是停止。 您的 Stop hook 指令需要檢查它是否已經觸發了延續。從 JSON 輸入解析stop_hook_active 欄位,如果為 true 則提前退出:
JSON 驗證失敗
Claude Code 顯示 JSON 解析錯誤,即使您的 hook 指令輸出有效的 JSON。 當 Claude Code 執行 hook 時,它生成一個 shell,該 shell 來源您的設定檔(~/.zshrc 或 ~/.bashrc)。如果您的設定檔包含無條件的 echo 陳述式,該輸出會被前置到您的 hook 的 JSON:
$- 變數包含 shell 旗標,i 表示互動式。Hooks 在非互動式 shell 中執行,因此 echo 被跳過。
除錯技術
文字記錄檢視(使用Ctrl+O 切換)為每個觸發的 hook 顯示一行摘要:成功是無聲的,阻止錯誤顯示 stderr,非阻止錯誤顯示 <hook name> hook error 通知,後面跟著 stderr 的第一行。
有關完整的執行詳細資訊,包括哪些 hooks 相符、它們的退出代碼、stdout 和 stderr,請閱讀除錯日誌。使用 claude --debug-file /tmp/claude.log 啟動 Claude Code 以寫入已知路徑,然後在另一個終端中執行 tail -f /tmp/claude.log。如果您啟動時沒有該旗標,在工作階段中執行 /debug 以啟用記錄並找到日誌路徑。
深入瞭解
- Hooks 參考:完整的事件架構、JSON 輸出格式、非同步 hooks 和 MCP 工具 hooks
- 安全考量:在共享或生產環境中部署 hooks 之前進行檢查
- Bash 命令驗證器範例:完整的參考實現