跳轉到主要內容
Hooks 是使用者定義的 shell 命令,在 Claude Code 生命週期的特定時間點執行。它們提供對 Claude Code 行為的確定性控制,確保某些操作始終發生,而不是依賴 LLM 選擇執行它們。使用 hooks 來強制執行專案規則、自動化重複性任務,並將 Claude Code 與您現有的工具整合。 對於需要判斷而不是確定性規則的決策,您也可以使用基於提示的 hooks基於代理的 hooks,它們使用 Claude 模型來評估條件。 有關擴展 Claude Code 的其他方式,請參閱skills以提供 Claude 額外的指令和可執行命令、subagents以在隔離的上下文中執行任務,以及plugins以打包要在專案間共享的擴展。
本指南涵蓋常見用例和入門方式。有關完整的事件架構、JSON 輸入/輸出格式和非同步 hooks 和 MCP 工具 hooks 等進階功能,請參閱 Hooks 參考

設定您的第一個 hook

若要建立 hook,請將 hooks 區塊新增到設定檔。本逐步解說建立一個桌面通知 hook,因此每當 Claude 等待您的輸入而不是監視終端時,您都會收到警報。
1

將 hook 新增到您的設定

開啟 ~/.claude/settings.json 並新增 Notification hook。下面的範例使用 osascript 進行 macOS;有關 Linux 和 Windows 命令,請參閱當 Claude 需要輸入時收到通知
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
如果您的設定檔已經有 hooks 鍵,請將 Notification 作為現有事件鍵的同級項目新增,而不是替換整個物件。每個事件名稱是單個 hooks 物件內的鍵:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }]
      }
    ],
    "Notification": [
      {
        "matcher": "",
        "hooks": [{ "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" }]
      }
    ]
  }
}
您也可以透過在 CLI 中描述您想要的內容,要求 Claude 為您編寫 hook。
2

驗證配置

輸入 /hooks 以開啟 hooks 瀏覽器。您將看到所有可用 hook 事件的列表,每個配置了 hooks 的事件旁邊都有一個計數。選擇 Notification 以確認您的新 hook 出現在列表中。選擇 hook 會顯示其詳細資訊:事件、匹配器、類型、來源檔案和命令。
3

測試 hook

Esc 返回 CLI。要求 Claude 執行需要權限的操作,然後切換離開終端。您應該會收到桌面通知。
/hooks 選單是唯讀的。若要新增、修改或移除 hooks,請直接編輯您的設定 JSON 或要求 Claude 進行變更。

您可以自動化的內容

Hooks 讓您在 Claude Code 生命週期的關鍵點執行程式碼:編輯後格式化檔案、在執行前阻止命令、當 Claude 需要輸入時發送通知、在工作階段開始時注入上下文等。有關 hook 事件的完整列表,請參閱 Hooks 參考 每個範例都包含一個現成可用的配置區塊,您可以將其新增到設定檔。最常見的模式:

當 Claude 需要輸入時收到通知

每當 Claude 完成工作並需要您的輸入時收到桌面通知,這樣您可以切換到其他任務而無需檢查終端。 此 hook 使用 Notification 事件,當 Claude 等待輸入或權限時觸發。下面的每個標籤使用平台的原生通知命令。將此新增到 ~/.claude/settings.json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
osascript 透過內建的 Script Editor 應用程式路由通知。如果 Script Editor 沒有通知權限,命令會無聲地失敗,macOS 不會提示您授予它。在終端中執行一次以使 Script Editor 出現在您的通知設定中:
osascript -e 'display notification "test"'
目前不會出現任何內容。開啟系統設定 > 通知,在列表中找到 Script Editor,並開啟允許通知。再次執行命令以確認測試通知出現。

編輯後自動格式化程式碼

在 Claude 編輯的每個檔案上自動執行 Prettier,以便格式保持一致而無需手動干預。 此 hook 使用 PostToolUse 事件搭配 Edit|Write 匹配器,因此它只在檔案編輯工具之後執行。該命令使用 jq 提取編輯的檔案路徑並將其傳遞給 Prettier。將此新增到您的專案根目錄中的 .claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}
本頁上的 Bash 範例使用 jq 進行 JSON 解析。使用 brew install jq(macOS)、apt-get install jq(Debian/Ubuntu)安裝它,或參閱 jq 下載

阻止編輯受保護的檔案

防止 Claude 修改敏感檔案,如 .envpackage-lock.json.git/ 中的任何內容。Claude 會收到解釋編輯被阻止原因的回饋,因此它可以調整其方法。 此範例使用 hook 呼叫的單獨指令檔。該指令檢查目標檔案路徑是否與受保護的模式列表相符,並以代碼 2 退出以阻止編輯。
1

建立 hook 指令

將此儲存到 .claude/hooks/protect-files.sh
#!/bin/bash
# protect-files.sh

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
    exit 2
  fi
done

exit 0
2

使指令可執行(macOS/Linux)

Hook 指令必須可執行,Claude Code 才能執行它們:
chmod +x .claude/hooks/protect-files.sh
3

註冊 hook

PreToolUse hook 新增到 .claude/settings.json,在任何 EditWrite 工具呼叫之前執行指令:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

壓縮後重新注入上下文

當 Claude 的上下文視窗填滿時,壓縮會總結對話以釋放空間。這可能會遺失重要細節。使用帶有 compact 匹配器的 SessionStart hook 在每次壓縮後重新注入關鍵上下文。 您的命令寫入 stdout 的任何文字都會新增到 Claude 的上下文中。此範例提醒 Claude 專案慣例和最近的工作。將此新增到您的專案根目錄中的 .claude/settings.json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Reminder: use Bun, not npm. Run bun test before committing. Current sprint: auth refactor.'"
          }
        ]
      }
    ]
  }
}
您可以將 echo 替換為任何產生動態輸出的命令,如 git log --oneline -5 以顯示最近的提交。有關在每個工作階段開始時注入上下文,請考慮改用 CLAUDE.md。有關環境變數,請參閱參考中的 CLAUDE_ENV_FILE

審計配置變更

追蹤工作階段期間設定或 skills 檔案何時變更。ConfigChange 事件在外部程序或編輯器修改配置檔案時觸發,因此您可以記錄變更以進行合規性檢查或阻止未授權的修改。 此範例將每個變更附加到審計日誌。將此新增到 ~/.claude/settings.json
{
  "hooks": {
    "ConfigChange": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
          }
        ]
      }
    ]
  }
}
匹配器按配置類型篩選:user_settingsproject_settingslocal_settingspolicy_settingsskills。要阻止變更生效,以代碼 2 退出或傳回 {"decision": "block"}。有關完整的輸入架構,請參閱 ConfigChange 參考

當目錄或檔案變更時重新載入環境

某些專案根據您所在的目錄設定不同的環境變數。direnv 之類的工具在您的 shell 中自動執行此操作,但 Claude 的 Bash 工具不會自行選取這些變更。 配對 SessionStart hook 與 CwdChanged hook 可以修復此問題。SessionStart 載入您啟動時所在目錄的變數,CwdChanged 在 Claude 每次變更目錄時重新載入它們。兩者都寫入 CLAUDE_ENV_FILE,Claude Code 在每個 Bash 命令之前執行為指令碼前置。將此新增到 ~/.claude/settings.json
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
          }
        ]
      }
    ],
    "CwdChanged": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
          }
        ]
      }
    ]
  }
}
在每個具有 .envrc 的目錄中執行一次 direnv allow,以便允許 direnv 載入它。如果您使用 devbox 或 nix 而不是 direnv,相同的模式適用於 devbox shellenvdevbox global shellenv 代替 direnv export bash 若要對特定檔案而不是每次目錄變更做出反應,請使用 FileChanged 搭配 matcher 列出要監視的檔案名稱(以 | 分隔)。若要建立監視清單,此值會分割為字面檔案名稱,而不是作為正規表達式進行評估。有關輸入架構、watchPaths 輸出和 CLAUDE_ENV_FILE 詳細資訊,請參閱 FileChanged。此範例監視工作目錄中 .envrc.env 的變更:
{
  "hooks": {
    "FileChanged": [
      {
        "matcher": ".envrc|.env",
        "hooks": [
          {
            "type": "command",
            "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
          }
        ]
      }
    ]
  }
}
有關輸入架構、watchPaths 輸出和 CLAUDE_ENV_FILE 詳細資訊,請參閱 CwdChangedFileChanged 參考項目。

自動批准特定權限提示

跳過您始終允許的工具呼叫的批准對話。此範例自動批准 ExitPlanMode,這是 Claude 在完成呈現計畫並要求繼續時呼叫的工具,因此您不會在每次計畫準備好時被提示。 與上面的退出代碼範例不同,自動批准要求您的 hook 將 JSON 決策寫入 stdout。PermissionRequest hook 在 Claude Code 即將顯示權限對話時觸發,傳回 "behavior": "allow" 會代表您回答它。 匹配器將 hook 的範圍限制為僅 ExitPlanMode,因此不會影響其他提示。將此新增到 ~/.claude/settings.json
{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "ExitPlanMode",
        "hooks": [
          {
            "type": "command",
            "command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
          }
        ]
      }
    ]
  }
}
當 hook 批准時,Claude Code 退出計畫模式並恢復進入計畫模式之前處於活動狀態的任何權限模式。文字記錄顯示「由 PermissionRequest hook 允許」,其中對話會出現。hook 路徑始終保持當前對話:它無法清除上下文並以對話可以執行的方式啟動新的實現工作階段。 若要改為設定特定的權限模式,您的 hook 的輸出可以包含帶有 setMode 項目的 updatedPermissions 陣列。mode 值是任何權限模式,如 defaultacceptEditsbypassPermissionsdestination: "session" 僅將其應用於當前工作階段。
bypassPermissions 只有在工作階段已經啟用了繞過模式時才適用:--dangerously-skip-permissions--permission-mode bypassPermissions--allow-dangerously-skip-permissions 或設定中的 permissions.defaultMode: "bypassPermissions",且未被 permissions.disableBypassPermissionsMode 禁用。它永遠不會被持久化為 defaultMode
若要將工作階段切換到 acceptEdits,您的 hook 會將此 JSON 寫入 stdout:
{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "updatedPermissions": [
        { "type": "setMode", "mode": "acceptEdits", "destination": "session" }
      ]
    }
  }
}
保持匹配器盡可能狹窄。在 .* 上進行匹配或留空匹配器會自動批准每個權限提示,包括檔案寫入和 shell 命令。有關決策欄位的完整集合,請參閱 PermissionRequest 參考

Hooks 如何工作

Hook 事件在 Claude Code 的特定生命週期點觸發。當事件觸發時,所有匹配的 hooks 並行執行,相同的 hook 命令會自動去重。下表顯示每個事件及其觸發時間:
EventWhen it fires
SessionStartWhen a session begins or resumes
UserPromptSubmitWhen you submit a prompt, before Claude processes it
UserPromptExpansionWhen a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion
PreToolUseBefore a tool call executes. Can block it
PermissionRequestWhen a permission dialog appears
PermissionDeniedWhen a tool call is denied by the auto mode classifier. Return {retry: true} to tell the model it may retry the denied tool call
PostToolUseAfter a tool call succeeds
PostToolUseFailureAfter a tool call fails
NotificationWhen Claude Code sends a notification
SubagentStartWhen a subagent is spawned
SubagentStopWhen a subagent finishes
TaskCreatedWhen a task is being created via TaskCreate
TaskCompletedWhen a task is being marked as completed
StopWhen Claude finishes responding
StopFailureWhen the turn ends due to an API error. Output and exit code are ignored
TeammateIdleWhen an agent team teammate is about to go idle
InstructionsLoadedWhen 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
ConfigChangeWhen a configuration file changes during a session
CwdChangedWhen the working directory changes, for example when Claude executes a cd command. Useful for reactive environment management with tools like direnv
FileChangedWhen a watched file changes on disk. The matcher field specifies which filenames to watch
WorktreeCreateWhen a worktree is being created via --worktree or isolation: "worktree". Replaces default git behavior
WorktreeRemoveWhen a worktree is being removed, either at session exit or when a subagent finishes
PreCompactBefore context compaction
PostCompactAfter context compaction completes
ElicitationWhen an MCP server requests user input during a tool call
ElicitationResultAfter a user responds to an MCP elicitation, before the response is sent back to the server
SessionEndWhen a session terminates
當多個 hooks 相符時,每個都傳回自己的結果。對於決策,Claude Code 選擇最具限制性的答案。傳回 denyPreToolUse 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_idcwd,但每個事件類型都新增不同的資料。例如,當 Claude 執行 Bash 命令時,PreToolUse hook 在 stdin 上接收類似以下內容:
{
  "session_id": "abc123",          // 此工作階段的唯一 ID
  "cwd": "/Users/sarah/myproject", // 事件觸發時的工作目錄
  "hook_event_name": "PreToolUse", // 哪個事件觸發了此 hook
  "tool_name": "Bash",             // Claude 即將使用的工具
  "tool_input": {                  // Claude 傳遞給工具的引數
    "command": "npm test"          // 對於 Bash,這是 shell 命令
  }
}
您的指令可以解析該 JSON 並對任何這些欄位採取行動。UserPromptSubmit hooks 改為取得 prompt 文字,SessionStart hooks 取得 source(startup、resume、clear、compact),等等。有關共享欄位,請參閱參考中的常見輸入欄位,以及每個事件的部分以了解事件特定的架構。

Hook 輸出

您的指令透過寫入 stdout 或 stderr 並以特定代碼退出來告訴 Claude Code 接下來要做什麼。例如,想要阻止命令的 PreToolUse hook:
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

if echo "$COMMAND" | grep -q "drop table"; then
  echo "Blocked: dropping tables is not allowed" >&2  # stderr 變成 Claude 的回饋
  exit 2 # exit 2 = 阻止操作
fi

exit 0  # exit 0 = 讓它繼續
退出代碼決定接下來會發生什麼:
  • Exit 0:操作繼續。對於 UserPromptSubmitSessionStart hooks,您寫入 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 為什麼,或將其升級給使用者以獲得批准:
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Use rg instead of grep for better performance"
  }
}
Claude Code 讀取 permissionDecision 並取消工具呼叫,然後將 permissionDecisionReason 回饋給 Claude。這些 permissionDecision 值特定於 PreToolUse
  • "allow":跳過互動式權限提示。拒絕和詢問規則,包括企業受管拒絕清單,仍然適用
  • "deny":取消工具呼叫並將原因傳送給 Claude
  • "ask":照常向使用者顯示權限提示
第四個值 "defer"非互動模式中使用 -p 旗標時可用。它以保留的工具呼叫退出程序,以便 Agent SDK 包裝器可以收集輸入並繼續。有關詳細資訊,請參閱參考中的延遲工具呼叫以供稍後使用 傳回 "allow" 會跳過互動式提示,但不會覆蓋權限規則。如果拒絕規則與工具呼叫相符,即使您的 hook 傳回 "allow",呼叫也會被阻止。如果詢問規則相符,使用者仍會被提示。這意味著來自任何設定範圍(包括受管理的設定)的拒絕規則始終優先於 hook 批准。 其他事件使用不同的決策模式。例如,PostToolUseStop hooks 使用頂級 decision: "block" 欄位,而 PermissionRequest 使用 hookSpecificOutput.decision.behavior。有關按事件的完整分解,請參閱參考中的摘要表 對於 UserPromptSubmit hooks,改用 additionalContext 將文字注入到 Claude 的上下文中。基於提示的 hooks(type: "prompt")以不同方式處理輸出:請參閱基於提示的 hooks

使用匹配器篩選 hooks

沒有匹配器,hook 會在其事件的每次出現時觸發。匹配器讓您縮小範圍。例如,如果您只想在檔案編輯後執行格式化程式(而不是在每次工具呼叫後),請將匹配器新增到您的 PostToolUse hook:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "prettier --write ..." }
        ]
      }
    ]
  }
}
"Edit|Write" 匹配器只在 Claude 使用 EditWrite 工具時觸發,而不是在它使用 BashRead 或任何其他工具時。請參閱匹配器模式以了解純名稱和正規表達式如何被評估。 每個事件類型都在特定欄位上進行匹配:
事件匹配器篩選的內容範例匹配器值
PreToolUsePostToolUsePostToolUseFailurePermissionRequestPermissionDenied工具名稱BashEdit|Writemcp__.*
SessionStart工作階段如何開始startupresumeclearcompact
SessionEnd工作階段為什麼結束clearresumelogoutprompt_input_exitbypass_permissions_disabledother
Notification通知類型permission_promptidle_promptauth_successelicitation_dialog
SubagentStart代理類型BashExplorePlan 或自訂代理名稱
PreCompactPostCompact什麼觸發了壓縮manualauto
SubagentStop代理類型SubagentStart 相同的值
ConfigChange配置來源user_settingsproject_settingslocal_settingspolicy_settingsskills
StopFailure錯誤類型rate_limitauthentication_failedbilling_errorinvalid_requestserver_errormax_output_tokensunknown
InstructionsLoaded載入原因session_startnested_traversalpath_glob_matchincludecompact
ElicitationMCP 伺服器名稱您配置的 MCP 伺服器名稱
ElicitationResultMCP 伺服器名稱Elicitation 相同的值
FileChanged字面檔案名稱以監視(請參閱 FileChanged.envrc|.env
UserPromptSubmitStopTeammateIdleTaskCreatedTaskCompletedWorktreeCreateWorktreeRemoveCwdChanged不支援匹配器始終在每次出現時觸發
顯示不同事件類型上匹配器的更多範例:
只匹配 Bash 工具呼叫並將每個命令記錄到檔案。PostToolUse 事件在命令完成後觸發,因此 tool_input.command 包含執行的內容。hook 在 stdin 上接收事件資料作為 JSON,jq -r '.tool_input.command' 只提取命令字串,>> 將其附加到日誌檔案:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
          }
        ]
      }
    ]
  }
}
有關完整的匹配器語法,請參閱 Hooks 參考

使用 if 欄位按工具名稱和引數篩選

if 欄位需要 Claude Code v2.1.85 或更新版本。較早的版本會忽略它並在每次匹配的呼叫上執行 hook。
if 欄位使用權限規則語法按工具名稱和引數一起篩選 hooks,因此 hook 程序只在工具呼叫相符時生成,或當 Bash 命令太複雜而無法解析時。這超越了 matcher,它只在工具名稱級別篩選。 例如,若要只在 Claude 使用 git 命令而不是所有 Bash 命令時執行 hook:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(git *)",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh"
          }
        ]
      }
    ]
  }
}
hook 程序只在 Bash 命令的子命令與 git * 相符時生成,或當命令太複雜而無法解析為子命令時。對於複合命令(如 npm test && git push),Claude Code 評估每個子命令並觸發 hook,因為 git push 相符。if 欄位接受與權限規則相同的模式:"Bash(git *)""Edit(*.ts)" 等。若要匹配多個工具名稱,請使用每個都有自己的 if 值的單獨處理程式,或在 matcher 級別進行匹配,其中支援管道交替。 if 只適用於工具事件:PreToolUsePostToolUsePostToolUseFailurePermissionRequest。將其新增到任何其他事件會防止 hook 執行。

配置 hook 位置

您新增 hook 的位置決定了其範圍:
位置範圍可共享
~/.claude/settings.json您的所有專案否,本機到您的機器
.claude/settings.json單個專案是,可以提交到儲存庫
.claude/settings.local.json單個專案否,gitignored
受管理的原則設定組織範圍是,由管理員控制
Plugin hooks/hooks.json啟用外掛時是,與外掛捆綁
Skill代理 frontmatter當 skill 或代理處於活動狀態時是,在元件檔案中定義
在 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": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains to be done\"}."
          }
        ]
      }
    ]
  }
}
有關完整的配置選項,請參閱參考中的基於提示的 hooks

基於代理的 hooks

Agent hooks 是實驗性的。行為和配置可能在未來版本中改變。對於生產工作流程,優先使用命令 hooks
當驗證需要檢查檔案或執行命令時,使用 type: "agent" hooks。與只進行單個 LLM 呼叫的提示 hooks 不同,代理 hooks 生成一個 subagent,可以讀取檔案、搜尋程式碼和使用其他工具在傳回決策之前驗證條件。 代理 hooks 使用與提示 hooks 相同的 "ok" / "reason" 回應格式,但預設超時時間更長(60 秒)且最多 50 個工具使用輪次。 此範例驗證在允許 Claude 停止之前測試通過:
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS",
            "timeout": 120
          }
        ]
      }
    ]
  }
}
當 hook 輸入資料本身足以做出決策時,使用提示 hooks。當您需要根據程式碼庫的實際狀態驗證某些內容時,使用代理 hooks。 有關完整的配置選項,請參閱參考中的基於代理的 hooks

HTTP hooks

使用 type: "http" hooks 將事件資料 POST 到 HTTP 端點,而不是執行 shell 命令。端點接收命令 hook 在 stdin 上接收的相同 JSON,並使用相同的 JSON 格式透過 HTTP 回應主體傳回結果。 HTTP hooks 在您希望 Web 伺服器、雲端函數或外部服務處理 hook 邏輯時很有用:例如,一個共享的審計服務,在整個團隊中記錄工具使用事件。 此範例將每個工具使用 POST 到本機記錄服務:
{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "http",
            "url": "http://localhost:8080/hooks/tool-use",
            "headers": {
              "Authorization": "Bearer $MY_TOKEN"
            },
            "allowedEnvVars": ["MY_TOKEN"]
          }
        ]
      }
    ]
  }
}
端點應使用與命令 hooks 相同的輸出格式傳回 JSON 回應主體。要阻止工具呼叫,傳回 2xx 回應並包含適當的 hookSpecificOutput 欄位。HTTP 狀態代碼本身無法阻止操作。 標頭值支援使用 $VAR_NAME${VAR_NAME} 語法的環境變數插值。只有在 allowedEnvVars 陣列中列出的變數才會被解析;所有其他 $VAR 參考保持為空。 有關完整的配置選項和回應處理,請參閱參考中的 HTTP hooks

限制和故障排除

限制

  • 命令 hooks 只透過 stdout、stderr 和退出代碼通訊。它們無法觸發 / 命令或工具呼叫。透過 additionalContext 傳回的文字會作為系統提醒注入,Claude 將其讀取為純文字。HTTP hooks 改為透過回應主體通訊。
  • Hook 超時預設為 10 分鐘,可透過 timeout 欄位(以秒為單位)按 hook 配置。
  • PostToolUse hooks 無法撤銷操作,因為工具已經執行。
  • PermissionRequest hooks 在非互動模式-p)中不觸發。對於自動化權限決策,使用 PreToolUse hooks。
  • Stop hooks 在 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)中使用 PermissionRequest hooks,改用 PreToolUse

Hook 輸出中的錯誤

您在文字記錄中看到類似「PreToolUse hook error: …」的訊息。
  • 您的指令意外以非零代碼退出。透過管道傳輸範例 JSON 來手動測試它:
    echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh
    echo $?  # 檢查退出代碼
    
  • 如果您看到「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 則提前退出:
#!/bin/bash
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0  # 允許 Claude 停止
fi
# ... 您的 hook 邏輯的其餘部分

JSON 驗證失敗

Claude Code 顯示 JSON 解析錯誤,即使您的 hook 指令輸出有效的 JSON。 當 Claude Code 執行 hook 時,它生成一個 shell,該 shell 來源您的設定檔(~/.zshrc~/.bashrc)。如果您的設定檔包含無條件的 echo 陳述式,該輸出會被前置到您的 hook 的 JSON:
Shell ready on arm64
{"decision": "block", "reason": "Not allowed"}
Claude Code 嘗試將其解析為 JSON 並失敗。要修復此問題,在您的 shell 設定檔中包裝 echo 陳述式,使其只在互動式 shell 中執行:
# 在 ~/.zshrc 或 ~/.bashrc 中
if [[ $- == *i* ]]; then
  echo "Shell ready"
fi
$- 變數包含 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 以啟用記錄並找到日誌路徑。

深入瞭解