Skip to content

Claude Code Hooks 设计指南(参考文档)

基于 2026 年最新官方文档整理,涵盖 18 种 Hook 事件、4 种 Handler 类型


目录

  1. 概念概述
  2. Hook 事件类型(18 种)
  3. 配置格式与位置
  4. 匹配器规则(Matcher)
  5. Handler 类型(4 种)
  6. 环境变量
  7. 输入/输出 JSON 格式
  8. 响应决策控制
  9. 实用模式与示例
  10. 高级特性
  11. 故障排除

1. 概念概述

Hooks 是用户定义的自动化机制,在 Claude Code 生命周期的特定节点自动执行。类似 Git Hooks,但作用于 AI 辅助开发流程。

核心区别

机制作用执行保证
CLAUDE.md引导 Claude 的行为偏好建议性,Claude 可能不遵守
Hooks强制执行确定性规则确定性,100% 执行
Skills可复用的指令集按需触发
Subagents复杂委托任务隔离上下文

适用场景:文件保护、代码格式化、危险操作拦截、审计日志、桌面通知、上下文注入等。


2. Hook 事件类型

共 18 种事件,按生命周期分组:

会话生命周期

事件触发时机Matcher 匹配字段
SessionStart会话启动或恢复startup / resume / clear / compact
SessionEnd会话终止clear / logout / prompt_input_exit / bypass_permissions_disabled
PreCompact上下文压缩前manual / auto
ConfigChange配置文件外部修改user_settings / project_settings / local_settings / policy_settings / skills

用户交互

事件触发时机Matcher 匹配字段
UserPromptSubmit用户提交提示词后(处理前)无(始终触发)
NotificationClaude 需要用户注意permission_prompt / idle_prompt / auth_success / elicitation_dialog

工具执行

事件触发时机Matcher 匹配字段
PreToolUse工具执行前工具名:Bash / Edit / Write / Read / mcp__.*
PostToolUse工具执行成功后同上
PostToolUseFailure工具执行失败后同上
PermissionRequest权限确认弹窗时同上

Agent 与任务

事件触发时机Matcher 匹配字段
SubagentStart子代理启动Agent 类型:Bash / Explore / Plan / 自定义名
SubagentStop子代理完成同上
TeammateIdle团队成员空闲
TaskCompleted任务标记完成
StopClaude 完成回复

Worktree

事件触发时机Matcher 匹配字段
WorktreeCreate工作树创建
WorktreeRemove工作树移除

3. 配置格式与位置

配置结构

json
{
  "hooks": {
    "EventName": [
      {
        "matcher": "regex_pattern",
        "hooks": [
          {
            "type": "command",
            "command": "shell command here",
            "timeout": 30,
            "async": false
          }
        ]
      }
    ]
  },
  "disableAllHooks": false,
  "allowedHttpHookUrls": ["https://hooks.example.com/*"],
  "httpHookAllowedEnvVars": ["MY_TOKEN"]
}

配置位置与优先级

位置作用域可提交 Git优先级
~/.claude/settings.json全局(所有项目)最低 (5)
.claude/settings.json单项目中 (4)
.claude/settings.local.json单项目(本地)否(gitignore)高 (3)
托管策略设置组织级管理员控制最高 (1)
Plugin hooks/hooks.json插件启用时随插件N/A
Skill/Agent frontmatter组件活跃时随文件N/A

配置方式

  • 交互式:在 Claude Code 中输入 /hooks
  • 手动编辑:直接修改 settings.json
  • 插件:在 Plugin manifest 中包含 hooks/hooks.json

4. 匹配器规则

Matcher 是正则表达式,根据事件类型匹配不同字段。

匹配示例

json
// 精确匹配单个工具
"matcher": "Bash"

// 匹配多个工具(正则 OR)
"matcher": "Edit|Write"

// 匹配所有 MCP 工具
"matcher": "mcp__.*"

// 匹配特定 MCP 服务器的工具
"matcher": "mcp__github__.*"

// 空匹配器 = 始终触发
"matcher": ""

MCP 工具命名规范

mcp__<server_name>__<tool_name>

示例:
- mcp__github__search_repositories
- mcp__filesystem__read_file
- mcp__ace-tool__search_context

5. Handler 类型

四种 Handler

类型说明适用场景
command本地 Shell 命令最常用:验证、格式化、通知
httpPOST 到 HTTP 端点外部服务、团队审计
prompt单轮 LLM 评估是/否判断、模糊决策
agent多轮子代理(有工具访问权限)复杂验证、文件检查

command 类型

json
{
  "type": "command",
  "command": "bash .claude/hooks/validate.sh",
  "timeout": 30,
  "async": false
}

执行特点:

  • 输入:JSON 通过 stdin 传入
  • 输出:exit code + stdout/stderr
  • 工作目录:会话的当前目录
  • 去重:相同命令只执行一次
  • 并行:同一事件的多个 Hook 并行运行
  • 超时:默认 10 分钟

http 类型

json
{
  "type": "http",
  "url": "https://hooks.company.com/claude-events",
  "headers": {
    "Authorization": "Bearer $HOOK_TOKEN"
  },
  "allowedEnvVars": ["HOOK_TOKEN"],
  "timeout": 15
}
  • allowedEnvVars 中的变量会被解析
  • 需在 allowedHttpHookUrls 中预先授权 URL

prompt 类型

json
{
  "type": "prompt",
  "prompt": "检查此操作是否安全。返回 {\"ok\": true} 或 {\"ok\": false, \"reason\": \"...\"}",
  "model": "haiku"
}

agent 类型

json
{
  "type": "agent",
  "prompt": "验证所有单元测试通过: $ARGUMENTS",
  "timeout": 120,
  "model": "opus"
}

6. 环境变量

Hook 脚本可用变量

变量说明示例
CLAUDE_PROJECT_DIR项目根目录绝对路径/Users/user/myproject
CLAUDE_CODE_REMOTE是否远程模式true / false
CLAUDE_ENV_FILE设置会话环境变量的文件路径/tmp/claude-env-xyz
CLAUDE_SESSION_ID当前会话唯一 IDabc123def456
CLAUDE_FILE_PATHS文件相关 Hook 的文件路径/path/to/file.ts

在 SessionStart 中设置环境变量

bash
#!/bin/bash
# 追加到 CLAUDE_ENV_FILE 为会话设置变量
echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
echo 'export DEBUG=1' >> "$CLAUDE_ENV_FILE"

Shell Profile 注意事项

Hooks 在非交互式 Shell 中运行,但会 source ~/.zshrc~/.bashrc。若 Profile 中有无条件 echo,会污染 JSON 输出:

bash
# 修复方式:包裹在交互式检测中
if [[ $- == *i* ]]; then
  echo "Shell ready"  # 仅交互式 Shell 执行
fi

7. 输入/输出 JSON 格式

通用输入字段(所有事件)

json
{
  "session_id": "abc123",
  "cwd": "/Users/sarah/myproject",
  "hook_event_name": "PreToolUse",
  "timestamp": "2026-02-27T14:30:00Z"
}

各事件输入示例

PreToolUse(Bash):

json
{
  "session_id": "abc123",
  "cwd": "/Users/sarah/myproject",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}

PreToolUse(Edit):

json
{
  "hook_event_name": "PreToolUse",
  "tool_name": "Edit",
  "tool_input": {
    "file_path": "/project/src/app.ts",
    "old_string": "const x = 1;",
    "new_string": "const x = 2;"
  }
}

UserPromptSubmit:

json
{
  "hook_event_name": "UserPromptSubmit",
  "prompt": "Fix the authentication bug"
}

PostToolUse:

json
{
  "hook_event_name": "PostToolUse",
  "tool_name": "Edit",
  "tool_input": { "file_path": "src/app.ts" },
  "tool_response": "File edited successfully"
}

SessionStart:

json
{
  "hook_event_name": "SessionStart",
  "source": "resume",
  "cwd": "/path/to/project"
}

SessionEnd:

json
{
  "hook_event_name": "SessionEnd",
  "exit_reason": "clear",
  "duration_seconds": 1234
}

Notification:

json
{
  "hook_event_name": "Notification",
  "notification_type": "permission_prompt",
  "message": "Claude Code needs your attention"
}

8. 响应决策控制

Exit Code 含义

Code含义行为
0成功操作继续。stdout 解析为 JSON 决策
2阻止操作被阻止。stderr 作为反馈发送给 Claude
其他部分失败操作继续。stderr 仅在 verbose 模式记录

PreToolUse 决策

json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "命令安全,自动放行",
    "updatedInput": {
      "command": "rg pattern ."
    }
  }
}
决策值效果
"allow"绕过权限系统,直接执行
"deny"阻止工具,将原因反馈给 Claude
"ask"向用户显示权限确认弹窗

updatedInput 可选字段:可修改工具的输入参数(如将 grep 替换为 rg)。

PostToolUse / Stop 决策

json
{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "decision": "block",
    "reason": "代码需要审查后才能继续"
  }
}

PermissionRequest 决策

json
{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "approve"
    }
  }
}

TaskCompleted 决策

json
{
  "hookSpecificOutput": {
    "hookEventName": "TaskCompleted",
    "decision": "block",
    "reason": "任务缺少必要的测试"
  }
}

SessionStart / UserPromptSubmit 输出

bash
#!/bin/bash
# stdout 内容会注入到 Claude 的上下文中
echo "提醒:使用 Bun 而非 npm。当前冲刺:auth 重构。"
exit 0

9. 实用模式与示例

模式 1:阻止危险操作

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/validate-bash.sh"
          }
        ]
      }
    ]
  }
}

validate-bash.sh:

bash
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command')

# 阻止危险命令
DANGEROUS_PATTERNS=("rm -rf" "git push --force" "git reset --hard" "DROP TABLE" "mkfs")
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
  if [[ "$CMD" == *"$pattern"* ]]; then
    echo "Blocked: 检测到危险命令 '$pattern'" >&2
    exit 2
  fi
done
exit 0

模式 2:编辑后自动格式化

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

模式 3:桌面通知

macOS:

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude 需要你的注意\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

Windows(PowerShell):

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "powershell -Command \"[System.Windows.Forms.MessageBox]::Show('Claude needs attention')\""
          }
        ]
      }
    ]
  }
}

模式 4:保护文件不被修改

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

protect-files.sh:

bash
#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

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

for pattern in "${PROTECTED[@]}"; do
  if [[ "$FILE" == *"$pattern"* ]]; then
    echo "Blocked: $FILE 匹配保护规则 '$pattern'" >&2
    exit 2
  fi
done
exit 0

模式 5:审计日志

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "http",
            "url": "https://audit.company.com/claude-events",
            "headers": {
              "Authorization": "Bearer $AUDIT_TOKEN"
            },
            "allowedEnvVars": ["AUDIT_TOKEN"],
            "async": true
          }
        ]
      }
    ]
  }
}

模式 6:压缩后重新注入上下文

json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "cat .claude/context-reminder.txt"
          }
        ]
      }
    ]
  }
}

模式 7:自动放行安全命令

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/auto-approve-safe.sh"
          }
        ]
      }
    ]
  }
}

auto-approve-safe.sh:

bash
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command')

SAFE_PREFIXES=("npm test" "npm run lint" "npx prettier" "git status" "git log" "git diff" "ls " "cat ")
for prefix in "${SAFE_PREFIXES[@]}"; do
  if [[ "$CMD" == "$prefix"* ]]; then
    echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"Safe command auto-approved"}}'
    exit 0
  fi
done
exit 0  # 非安全命令走正常权限流程

模式 8:工具输入修改(grep → rg)

bash
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command')

if [[ "$CMD" == grep* ]]; then
  MODIFIED=$(echo "$CMD" | sed 's/^grep/rg/')
  echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\",\"updatedInput\":{\"command\":\"$MODIFIED\"}}}"
  exit 0
fi
exit 0

10. 高级特性

异步 Hook

json
{
  "type": "command",
  "command": "node background-task.js",
  "async": true,
  "timeout": 30
}
  • 异步执行,不阻塞 Claude
  • 完成后若返回包含 systemMessageadditionalContext 的 JSON,会在下一轮传递给 Claude

HTTP Hook 安全配置

json
{
  "allowedHttpHookUrls": ["https://hooks.example.com/*"],
  "httpHookAllowedEnvVars": ["HOOK_TOKEN", "HOOK_SECRET"],
  "allowManagedHooksOnly": false
}

Stop Hook 防循环

json
{
  "hook_event_name": "Stop",
  "stop_hook_active": true  // 此字段为 true 时表示当前在 Stop Hook 链中
}

Hook 脚本应检查此字段避免无限循环:

bash
#!/bin/bash
INPUT=$(cat)
ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false')
if [[ "$ACTIVE" == "true" ]]; then
  exit 0  # 已在 Stop Hook 链中,不再触发
fi
# ... 正常逻辑

11. 故障排除

问题解决方案
Hook 未触发检查 /hooks 菜单;验证 matcher 正则(区分大小写);确认事件类型正确
"command not found"使用绝对路径或 $CLAUDE_PROJECT_DIR
JSON 校验失败修复 Shell Profile(无条件 echo);包裹在 if [[ $- == *i* ]]
Hook 超时增加 timeout 字段(秒);优化脚本性能
Hook 错误显示手动测试:echo '{"tool_name":"Bash"}' | ./hook.sh
Stop Hook 死循环检查 stop_hook_active 字段;为 true 时提前退出
异步输出丢失确保 Hook 退出时输出包含 additionalContext 的有效 JSON
权限不足确保脚本有执行权限:chmod +x .claude/hooks/*.sh

参考来源

Released under the MIT License.