Claude Code hooks 在您的 設定檔 中配置:
~/.claude/settings.json - 使用者設定
.claude/settings.json - 專案設定
.claude/settings.local.json - 本機專案設定(未提交)
- 企業管理的政策設定
Hooks 按匹配器組織,每個匹配器可以有多個 hooks:
{
"hooks": {
"EventName": [
{
"matcher": "ToolPattern",
"hooks": [
{
"type": "command",
"command": "your-command-here"
}
]
}
]
}
}
- matcher:用於匹配工具名稱的模式,區分大小寫(僅適用於
PreToolUse 和 PostToolUse)
- 簡單字串完全匹配:
Write 僅匹配 Write 工具
- 支援正規表達式:
Edit|Write 或 Notebook.*
- 使用
* 匹配所有工具。您也可以使用空字串 ("") 或留空 matcher。
- hooks:當模式匹配時執行的 hooks 陣列
type:Hook 執行類型 - "command" 用於 bash 命令或 "prompt" 用於基於 LLM 的評估
command:(用於 type: "command")要執行的 bash 命令(可使用 $CLAUDE_PROJECT_DIR 環境變數)
prompt:(用於 type: "prompt")要發送給 LLM 進行評估的提示
timeout:(可選)Hook 應執行的時間長度(以秒為單位),超時後取消該特定 hook
對於不使用匹配器的事件,如 UserPromptSubmit、Notification、Stop 和 SubagentStop,您可以省略 matcher 欄位:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/prompt-validator.py"
}
]
}
]
}
}
專案特定的 Hook 指令碼
您可以使用環境變數 CLAUDE_PROJECT_DIR(僅在 Claude Code 生成 hook 命令時可用)來參考儲存在您專案中的指令碼,確保無論 Claude 的目前目錄如何,它們都能正常工作:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
}
]
}
]
}
}
外掛程式 hooks
外掛程式 可以提供與您的使用者和專案 hooks 無縫整合的 hooks。當外掛程式啟用時,外掛程式 hooks 會自動與您的配置合併。
外掛程式 hooks 的工作原理:
- 外掛程式 hooks 在外掛程式的
hooks/hooks.json 檔案或由 hooks 欄位的自訂路徑指定的檔案中定義。
- 當外掛程式啟用時,其 hooks 會與使用者和專案 hooks 合併
- 來自不同來源的多個 hooks 可以回應同一事件
- 外掛程式 hooks 使用
${CLAUDE_PLUGIN_ROOT} 環境變數來參考外掛程式檔案
外掛程式 hook 配置範例:
{
"description": "Automatic code formatting",
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
"timeout": 30
}
]
}
]
}
}
外掛程式 hooks 使用與常規 hooks 相同的格式,並有一個可選的 description 欄位來說明 hook 的用途。
外掛程式 hooks 與您的自訂 hooks 並行執行。如果多個 hooks 匹配一個事件,它們都會並行執行。
外掛程式的環境變數:
${CLAUDE_PLUGIN_ROOT}:外掛程式目錄的絕對路徑
${CLAUDE_PROJECT_DIR}:專案根目錄(與專案 hooks 相同)
- 所有標準環境變數都可用
有關建立外掛程式 hooks 的詳細資訊,請參閱 外掛程式元件參考。
基於提示的 Hooks
除了 bash 命令 hooks(type: "command"),Claude Code 還支援基於提示的 hooks(type: "prompt"),它們使用 LLM 來評估是否允許或阻止操作。基於提示的 hooks 目前僅支援 Stop 和 SubagentStop hooks,其中它們啟用智慧、上下文感知的決策。
基於提示的 hooks 如何工作
基於提示的 hooks 不執行 bash 命令,而是:
- 將 hook 輸入和您的提示發送給快速 LLM (Haiku)
- LLM 使用包含決策的結構化 JSON 進行回應
- Claude Code 自動處理決策
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete."
}
]
}
]
}
}
欄位:
type:必須是 "prompt"
prompt:要發送給 LLM 的提示文字
- 使用
$ARGUMENTS 作為 hook 輸入 JSON 的佔位符
- 如果
$ARGUMENTS 不存在,輸入 JSON 會附加到提示
timeout:(可選)超時時間(以秒為單位)(預設:30 秒)
回應架構
LLM 必須使用包含以下內容的 JSON 進行回應:
{
"decision": "approve" | "block",
"reason": "Explanation for the decision",
"continue": false, // Optional: stops Claude entirely
"stopReason": "Message shown to user", // Optional: custom stop message
"systemMessage": "Warning or context" // Optional: shown to user
}
回應欄位:
decision:"approve" 允許操作,"block" 防止操作
reason:當決策為 "block" 時顯示給 Claude 的說明
continue:(可選)如果為 false,完全停止 Claude 的執行
stopReason:(可選)當 continue 為 false 時顯示的訊息
systemMessage:(可選)顯示給使用者的其他訊息
支援的 hook 事件
基於提示的 hooks 適用於任何 hook 事件,但最適用於:
- Stop:智慧決定 Claude 是否應繼續工作
- SubagentStop:評估子代理是否已完成其任務
- UserPromptSubmit:使用 LLM 協助驗證使用者提示
- PreToolUse:做出上下文感知的權限決策
範例:智慧 Stop hook
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "You are evaluating whether Claude should stop working. Context: $ARGUMENTS\n\nAnalyze the conversation and determine if:\n1. All user-requested tasks are complete\n2. Any errors need to be addressed\n3. Follow-up work is needed\n\nRespond with JSON: {\"decision\": \"approve\" or \"block\", \"reason\": \"your explanation\"}",
"timeout": 30
}
]
}
]
}
}
範例:SubagentStop 與自訂邏輯
{
"hooks": {
"SubagentStop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Evaluate if this subagent should stop. Input: $ARGUMENTS\n\nCheck if:\n- The subagent completed its assigned task\n- Any errors occurred that need fixing\n- Additional context gathering is needed\n\nReturn: {\"decision\": \"approve\" or \"block\", \"reason\": \"explanation\"}"
}
]
}
]
}
}
與 bash 命令 hooks 的比較
| 功能 | Bash 命令 Hooks | 基於提示的 Hooks |
| 執行 | 執行 bash 指令碼 | 查詢 LLM |
| 決策邏輯 | 您在程式碼中實現 | LLM 評估上下文 |
| 設定複雜性 | 需要指令碼檔案 | 只需配置提示 |
| 上下文感知 | 受限於指令碼邏輯 | 自然語言理解 |
| 效能 | 快速(本機執行) | 較慢(API 呼叫) |
| 使用案例 | 確定性規則 | 上下文感知決策 |
最佳實踐
- 在提示中具體說明:清楚說明您希望 LLM 評估的內容
- 包含決策標準:列出 LLM 應考慮的因素
- 測試您的提示:驗證 LLM 對您的使用案例做出正確決策
- 設定適當的超時:預設為 30 秒,如需要可調整
- 用於複雜決策:Bash hooks 更適合簡單、確定性規則
有關建立外掛程式 hooks 的詳細資訊,請參閱 外掛程式元件參考。
Hook 事件
在 Claude 建立工具參數之後和處理工具呼叫之前執行。
常見匹配器:
Task - 子代理任務(請參閱 子代理文檔)
Bash - Shell 命令
Glob - 檔案模式匹配
Grep - 內容搜尋
Read - 檔案讀取
Edit - 檔案編輯
Write - 檔案寫入
WebFetch、WebSearch - 網路操作
PostToolUse
在工具成功完成後立即執行。
識別與 PreToolUse 相同的匹配器值。
Notification
在 Claude Code 發送通知時執行。通知在以下情況下發送:
- Claude 需要您的許可才能使用工具。範例:“Claude needs your permission to use Bash”
- 提示輸入已閒置至少 60 秒。“Claude is waiting for your input”
UserPromptSubmit
在使用者提交提示時執行,在 Claude 處理之前。這允許您根據提示/對話添加其他上下文、驗證提示或阻止某些類型的提示。
Stop
在主 Claude Code 代理完成回應時執行。如果停止是由於使用者中斷而發生的,則不執行。
SubagentStop
在 Claude Code 子代理(Task 工具呼叫)完成回應時執行。
PreCompact
在 Claude Code 即將執行壓縮操作之前執行。
匹配器:
manual - 從 /compact 呼叫
auto - 從自動壓縮呼叫(由於上下文視窗已滿)
SessionStart
在 Claude Code 啟動新工作階段或繼續現有工作階段時執行(目前在幕後啟動新工作階段)。適用於載入開發上下文,如現有問題或程式碼庫的最近變更、安裝依賴項或設定環境變數。
匹配器:
startup - 從啟動呼叫
resume - 從 --resume、--continue 或 /resume 呼叫
clear - 從 /clear 呼叫
compact - 從自動或手動壓縮呼叫。
保留環境變數
SessionStart hooks 可以存取 CLAUDE_ENV_FILE 環境變數,該變數提供一個檔案路徑,您可以在其中保留環境變數供後續 bash 命令使用。
範例:設定個別環境變數
#!/bin/bash
if [ -n "$CLAUDE_ENV_FILE" ]; then
echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
echo 'export API_KEY=your-api-key' >> "$CLAUDE_ENV_FILE"
echo 'export PATH="$PATH:./node_modules/.bin"' >> "$CLAUDE_ENV_FILE"
fi
exit 0
範例:保留 hook 中的所有環境變更
當您的設定修改環境時(例如 nvm use),通過比較環境來捕獲並保留所有變更:
#!/bin/bash
ENV_BEFORE=$(export -p | sort)
# Run your setup commands that modify the environment
source ~/.nvm/nvm.sh
nvm use 20
if [ -n "$CLAUDE_ENV_FILE" ]; then
ENV_AFTER=$(export -p | sort)
comm -13 <(echo "$ENV_BEFORE") <(echo "$ENV_AFTER") >> "$CLAUDE_ENV_FILE"
fi
exit 0
寫入此檔案的任何變數都將在工作階段期間 Claude Code 執行的所有後續 bash 命令中可用。
CLAUDE_ENV_FILE 僅適用於 SessionStart hooks。其他 hook 類型無法存取此變數。
SessionEnd
在 Claude Code 工作階段結束時執行。適用於清理任務、記錄工作階段統計資訊或儲存工作階段狀態。
hook 輸入中的 reason 欄位將是以下之一:
clear - 使用 /clear 命令清除工作階段
logout - 使用者登出
prompt_input_exit - 使用者在提示輸入可見時退出
other - 其他退出原因
Hook 輸入
Hooks 通過 stdin 接收包含工作階段資訊和事件特定資料的 JSON 資料:
{
// Common fields
session_id: string
transcript_path: string // Path to conversation JSON
cwd: string // The current working directory when the hook is invoked
permission_mode: string // Current permission mode: "default", "plan", "acceptEdits", or "bypassPermissions"
// Event-specific fields
hook_event_name: string
...
}
tool_input 的確切架構取決於工具。
{
"session_id": "abc123",
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"cwd": "/Users/...",
"permission_mode": "default",
"hook_event_name": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "/path/to/file.txt",
"content": "file content"
}
}
PostToolUse 輸入
tool_input 和 tool_response 的確切架構取決於工具。
{
"session_id": "abc123",
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"cwd": "/Users/...",
"permission_mode": "default",
"hook_event_name": "PostToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "/path/to/file.txt",
"content": "file content"
},
"tool_response": {
"filePath": "/path/to/file.txt",
"success": true
}
}
Notification 輸入
{
"session_id": "abc123",
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"cwd": "/Users/...",
"permission_mode": "default",
"hook_event_name": "Notification",
"message": "Task completed successfully"
}
UserPromptSubmit 輸入
{
"session_id": "abc123",
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"cwd": "/Users/...",
"permission_mode": "default",
"hook_event_name": "UserPromptSubmit",
"prompt": "Write a function to calculate the factorial of a number"
}
Stop 和 SubagentStop 輸入
當 Claude Code 已經因為 stop hook 而繼續時,stop_hook_active 為 true。檢查此值或處理文字記錄以防止 Claude Code 無限執行。
{
"session_id": "abc123",
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"permission_mode": "default",
"hook_event_name": "Stop",
"stop_hook_active": true
}
PreCompact 輸入
對於 manual,custom_instructions 來自使用者傳入 /compact 的內容。對於 auto,custom_instructions 為空。
{
"session_id": "abc123",
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"permission_mode": "default",
"hook_event_name": "PreCompact",
"trigger": "manual",
"custom_instructions": ""
}
SessionStart 輸入
{
"session_id": "abc123",
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"permission_mode": "default",
"hook_event_name": "SessionStart",
"source": "startup"
}
SessionEnd 輸入
{
"session_id": "abc123",
"transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"cwd": "/Users/...",
"permission_mode": "default",
"hook_event_name": "SessionEnd",
"reason": "exit"
}
Hook 輸出
有兩種方式讓 hooks 將輸出返回給 Claude Code。輸出傳達是否阻止以及應顯示給 Claude 和使用者的任何反饋。
簡單:退出代碼
Hooks 通過退出代碼、stdout 和 stderr 傳達狀態:
- 退出代碼 0:成功。
stdout 在文字記錄模式 (CTRL-R) 中顯示給使用者,除了 UserPromptSubmit 和 SessionStart,其中 stdout 被添加到上下文中。
- 退出代碼 2:阻止錯誤。
stderr 被反饋給 Claude 自動處理。請參閱下面的每個 hook 事件行為。
- 其他退出代碼:非阻止錯誤。
stderr 顯示給使用者,執行繼續。
提醒:如果退出代碼為 0,Claude Code 看不到 stdout,除了 UserPromptSubmit hook,其中 stdout 被注入為上下文。
退出代碼 2 行為
| Hook 事件 | 行為 |
PreToolUse | 阻止工具呼叫,向 Claude 顯示 stderr |
PostToolUse | 向 Claude 顯示 stderr(工具已執行) |
Notification | 不適用,僅向使用者顯示 stderr |
UserPromptSubmit | 阻止提示處理,清除提示,僅向使用者顯示 stderr |
Stop | 阻止停止,向 Claude 顯示 stderr |
SubagentStop | 阻止停止,向 Claude 子代理顯示 stderr |
PreCompact | 不適用,僅向使用者顯示 stderr |
SessionStart | 不適用,僅向使用者顯示 stderr |
SessionEnd | 不適用,僅向使用者顯示 stderr |
進階:JSON 輸出
Hooks 可以在 stdout 中返回結構化 JSON 以進行更複雜的控制:
常見 JSON 欄位
所有 hook 類型都可以包含這些可選欄位:
{
"continue": true, // Whether Claude should continue after hook execution (default: true)
"stopReason": "string", // Message shown when continue is false
"suppressOutput": true, // Hide stdout from transcript mode (default: false)
"systemMessage": "string" // Optional warning message shown to the user
}
如果 continue 為 false,Claude 在 hooks 執行後停止處理。
- 對於
PreToolUse,這與 "permissionDecision": "deny" 不同,後者只阻止特定工具呼叫並向 Claude 提供自動反饋。
- 對於
PostToolUse,這與 "decision": "block" 不同,後者向 Claude 提供自動反饋。
- 對於
UserPromptSubmit,這防止提示被處理。
- 對於
Stop 和 SubagentStop,這優先於任何 "decision": "block" 輸出。
- 在所有情況下,
"continue" = false 優先於任何 "decision": "block" 輸出。
stopReason 伴隨 continue 提供顯示給使用者的原因,不顯示給 Claude。
PreToolUse hooks 可以控制工具呼叫是否進行。
"allow" 繞過權限系統。permissionDecisionReason 顯示給使用者但不顯示給 Claude。
"deny" 防止工具呼叫執行。permissionDecisionReason 顯示給 Claude。
"ask" 要求使用者在 UI 中確認工具呼叫。permissionDecisionReason 顯示給使用者但不顯示給 Claude。
此外,hooks 可以在執行前使用 updatedInput 修改工具輸入:
updatedInput 允許您在工具執行前修改工具的輸入參數。這是一個 Record<string, unknown> 物件,包含您想要變更或添加的欄位。
- 這在
"permissionDecision": "allow" 時最有用,可以修改和批准工具呼叫。
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow"
"permissionDecisionReason": "My reason here",
"updatedInput": {
"field_to_modify": "new value"
}
}
}
decision 和 reason 欄位已棄用於 PreToolUse hooks。
改用 hookSpecificOutput.permissionDecision 和
hookSpecificOutput.permissionDecisionReason。已棄用的欄位
"approve" 和 "block" 分別對應 "allow" 和 "deny"。
PostToolUse 決策控制
PostToolUse hooks 可以在工具執行後向 Claude 提供反饋。
"block" 自動提示 Claude 使用 reason。
undefined 不執行任何操作。reason 被忽略。
"hookSpecificOutput.additionalContext" 為 Claude 添加要考慮的上下文。
{
"decision": "block" | undefined,
"reason": "Explanation for decision",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "Additional information for Claude"
}
}
UserPromptSubmit 決策控制
UserPromptSubmit hooks 可以控制使用者提示是否被處理。
"block" 防止提示被處理。提交的提示從上下文中清除。"reason" 顯示給使用者但不添加到上下文中。
undefined 允許提示正常進行。"reason" 被忽略。
"hookSpecificOutput.additionalContext" 如果未被阻止,將字串添加到上下文中。
{
"decision": "block" | undefined,
"reason": "Explanation for decision",
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "My additional context here"
}
}
Stop/SubagentStop 決策控制
Stop 和 SubagentStop hooks 可以控制 Claude 是否必須繼續。
"block" 防止 Claude 停止。您必須填入 reason 以便 Claude 知道如何進行。
undefined 允許 Claude 停止。reason 被忽略。
{
"decision": "block" | undefined,
"reason": "Must be provided when Claude is blocked from stopping"
}
SessionStart 決策控制
SessionStart hooks 允許您在工作階段開始時載入上下文。
"hookSpecificOutput.additionalContext" 將字串添加到上下文中。
- 多個 hooks 的
additionalContext 值被連接。
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "My additional context here"
}
}
SessionEnd 決策控制
SessionEnd hooks 在工作階段結束時執行。它們無法阻止工作階段終止,但可以執行清理任務。
退出代碼範例:Bash 命令驗證
#!/usr/bin/env python3
import json
import re
import sys
# Define validation rules as a list of (regex pattern, message) tuples
VALIDATION_RULES = [
(
r"\bgrep\b(?!.*\|)",
"Use 'rg' (ripgrep) instead of 'grep' for better performance and features",
),
(
r"\bfind\s+\S+\s+-name\b",
"Use 'rg --files | rg pattern' or 'rg --files -g pattern' instead of 'find -name' for better performance",
),
]
def validate_command(command: str) -> list[str]:
issues = []
for pattern, message in VALIDATION_RULES:
if re.search(pattern, command):
issues.append(message)
return issues
try:
input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
sys.exit(1)
tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
command = tool_input.get("command", "")
if tool_name != "Bash" or not command:
sys.exit(1)
# Validate the command
issues = validate_command(command)
if issues:
for message in issues:
print(f"• {message}", file=sys.stderr)
# Exit code 2 blocks tool call and shows stderr to Claude
sys.exit(2)
JSON 輸出範例:UserPromptSubmit 以添加上下文和驗證
對於 UserPromptSubmit hooks,您可以使用任一方法注入上下文:
- 退出代碼 0 與 stdout:Claude 看到上下文(
UserPromptSubmit 的特殊情況)
- JSON 輸出:提供對行為的更多控制
#!/usr/bin/env python3
import json
import sys
import re
import datetime
# Load input from stdin
try:
input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
sys.exit(1)
prompt = input_data.get("prompt", "")
# Check for sensitive patterns
sensitive_patterns = [
(r"(?i)\b(password|secret|key|token)\s*[:=]", "Prompt contains potential secrets"),
]
for pattern, message in sensitive_patterns:
if re.search(pattern, prompt):
# Use JSON output to block with a specific reason
output = {
"decision": "block",
"reason": f"Security policy violation: {message}. Please rephrase your request without sensitive information."
}
print(json.dumps(output))
sys.exit(0)
# Add current time to context
context = f"Current time: {datetime.datetime.now()}"
print(context)
"""
The following is also equivalent:
print(json.dumps({
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": context,
},
}))
"""
# Allow the prompt to proceed with the additional context
sys.exit(0)
#!/usr/bin/env python3
import json
import sys
# Load input from stdin
try:
input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
sys.exit(1)
tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
# Example: Auto-approve file reads for documentation files
if tool_name == "Read":
file_path = tool_input.get("file_path", "")
if file_path.endswith((".md", ".mdx", ".txt", ".json")):
# Use JSON output to auto-approve the tool call
output = {
"decision": "approve",
"reason": "Documentation file auto-approved",
"suppressOutput": True # Don't show in transcript mode
}
print(json.dumps(output))
sys.exit(0)
# For other cases, let the normal permission flow proceed
sys.exit(0)
使用 MCP 工具
Claude Code hooks 與 Model Context Protocol (MCP) 工具 無縫協作。當 MCP 伺服器提供工具時,它們會以特殊命名模式出現,您可以在 hooks 中匹配。
MCP 工具命名
MCP 工具遵循 mcp__<server>__<tool> 模式,例如:
mcp__memory__create_entities - Memory 伺服器的建立實體工具
mcp__filesystem__read_file - Filesystem 伺服器的讀取檔案工具
mcp__github__search_repositories - GitHub 伺服器的搜尋工具
為 MCP 工具配置 Hooks
您可以針對特定 MCP 工具或整個 MCP 伺服器:
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__memory__.*",
"hooks": [
{
"type": "command",
"command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"
}
]
},
{
"matcher": "mcp__.*__write.*",
"hooks": [
{
"type": "command",
"command": "/home/user/scripts/validate-mcp-write.py"
}
]
}
]
}
}
如需實用範例,包括程式碼格式化、通知和檔案保護,請參閱快速入門指南中的 更多範例。
安全考量
免責聲明
自行承擔風險使用:Claude Code hooks 自動在您的系統上執行任意 shell 命令。通過使用 hooks,您確認:
- 您對配置的命令負全責
- Hooks 可以修改、刪除或存取您的使用者帳戶可以存取的任何檔案
- 惡意或編寫不當的 hooks 可能導致資料遺失或系統損壞
- Anthropic 不提供任何保證,對因 hook 使用而導致的任何損害不承擔任何責任
- 您應在生產使用前在安全環境中徹底測試 hooks
在將任何 hook 命令添加到配置之前,請始終檢查並理解它們。
安全最佳實踐
以下是編寫更安全 hooks 的一些關鍵實踐:
- 驗證和清理輸入 - 永遠不要盲目信任輸入資料
- 始終引用 shell 變數 - 使用
"$VAR" 而不是 $VAR
- 阻止路徑遍歷 - 檢查檔案路徑中的
..
- 使用絕對路徑 - 為指令碼指定完整路徑(使用
"$CLAUDE_PROJECT_DIR" 表示專案路徑)
- 跳過敏感檔案 - 避免
.env、.git/、金鑰等
配置安全
直接編輯設定檔中的 hooks 不會立即生效。Claude Code:
- 在啟動時捕獲 hooks 的快照
- 在整個工作階段中使用此快照
- 如果 hooks 被外部修改,發出警告
- 需要在
/hooks 選單中檢查變更才能應用
這防止惡意 hook 修改影響您的目前工作階段。
Hook 執行詳細資訊
- 超時:預設 60 秒執行限制,每個命令可配置。
- 並行化:所有匹配的 hooks 並行執行
- 去重:多個相同的 hook 命令自動去重
- 環境:在目前目錄中以 Claude Code 的環境執行
CLAUDE_PROJECT_DIR 環境變數可用,包含專案根目錄的絕對路徑(Claude Code 啟動的位置)
CLAUDE_CODE_REMOTE 環境變數指示 hook 是在遠端(網路)環境中執行("true")還是本機 CLI 環境中執行(未設定或空)。使用此變數根據執行上下文執行不同的邏輯。
- 輸入:通過 stdin 的 JSON
- 輸出:
- PreToolUse/PostToolUse/Stop/SubagentStop:進度顯示在文字記錄中 (Ctrl-R)
- Notification/SessionEnd:記錄到偵錯只有 (
--debug)
- UserPromptSubmit/SessionStart:stdout 添加為 Claude 的上下文
基本故障排除
如果您的 hooks 不工作:
- 檢查配置 - 執行
/hooks 查看您的 hook 是否已註冊
- 驗證語法 - 確保您的 JSON 設定有效
- 測試命令 - 首先手動執行 hook 命令
- 檢查權限 - 確保指令碼可執行
- 檢查日誌 - 使用
claude --debug 查看 hook 執行詳細資訊
常見問題:
- 引號未轉義 - 在 JSON 字串中使用
\"
- 錯誤的匹配器 - 檢查工具名稱完全匹配(區分大小寫)
- 找不到命令 - 為指令碼使用完整路徑
進階偵錯
對於複雜的 hook 問題:
- 檢查 hook 執行 - 使用
claude --debug 查看詳細的 hook 執行
- 驗證 JSON 架構 - 使用外部工具測試 hook 輸入/輸出
- 檢查環境變數 - 驗證 Claude Code 的環境是否正確
- 測試邊界情況 - 嘗試使用不尋常的檔案路徑或輸入的 hooks
- 監控系統資源 - 檢查 hook 執行期間是否有資源耗盡
- 使用結構化日誌 - 在 hook 指令碼中實現日誌記錄
偵錯輸出範例
使用 claude --debug 查看 hook 執行詳細資訊:
[DEBUG] Executing hooks for PostToolUse:Write
[DEBUG] Getting matching hook commands for PostToolUse with query: Write
[DEBUG] Found 1 hook matchers in settings
[DEBUG] Matched 1 hooks for query "Write"
[DEBUG] Found 1 hook commands to execute
[DEBUG] Executing hook command: <Your command> with timeout 60000ms
[DEBUG] Hook command completed with status 0: <Your stdout>
進度訊息出現在文字記錄模式 (Ctrl-R) 中,顯示:
- 哪個 hook 正在執行
- 正在執行的命令
- 成功/失敗狀態
- 輸出或錯誤訊息