Claude Code 的钩子系统允许你在 29 个预定义事件发生时自动执行脚本、HTTP 请求或 LLM 提示,从而拦截、验证或增强 Claude 的行为。系统提供 5 种钩子类型,通过简单的 JSON 配置即可构建从代码格式化到安全策略执行的完整自动化工作流。

Claude Code Hooks 系统深度指南:29 个事件、5 种钩子类型与自动化工作流

Claude Code 的钩子(Hooks)是事件驱动的自动化脚本,能够在 Claude Code 会话的特定关键时刻自动执行,用于验证输入、修改输出、执行安全策略或集成外部系统。本文将深入解析其配置、事件、类型和实战应用。

一、钩子配置与匹配模式

钩子配置在多个层级的 settings.json 文件中,遵循特定的 JSON 结构。

配置层级(从高到低):

  1. 托管策略:组织级设置,用户无法覆盖。
  2. 用户设置:~/.claude/settings.json,应用于所有项目。
  3. 项目设置:.claude/settings.json,可提交到版本库。
  4. 本地项目设置:.claude/settings.local.json,不提交。
  5. 插件钩子:插件目录下的 hooks/hooks.json。
  6. 组件钩子:定义在技能(SKILL.md)、代理(agent.md)的 frontmatter 中。

基本配置结构:

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

匹配模式(Matcher)用于筛选触发钩子的工具:

模式 描述 示例
精确字符串 匹配特定工具 "Write"
正则表达式 匹配多个工具 "Edit|Write"
通配符 匹配所有工具 "*" 或 ""
MCP 工具 匹配 MCP 服务器工具 "mcp__memory__.*"

InstructionsLoaded 事件的匹配器值:session_start、nested_traversal、path_glob_match。

二、五种钩子类型详解

Claude Code 支持五种钩子类型,各自适用于不同场景。

1. 命令钩子(Command Hooks)

默认类型,执行 Shell 命令。支持两种形式:

  • Shell 形式:通过 "command": "..." 执行。
  • Exec 形式(v2.1.139+):通过 "args": [...] 数组直接执行二进制文件,避免 Shell 注入。

两种形式互斥,只能使用其一。当需要使用管道、重定向或 && 链时用 Shell 形式;调用单个可执行文件时用 Exec 形式更安全。

2. HTTP 钩子(HTTP Hooks)

向远程 Webhook 端点发送 POST 请求,接收 JSON 响应。启用沙箱时会经过沙箱路由。出于安全考虑,URL 中使用环境变量需显式配置 allowedEnvVars 列表。

{
  "type": "http",
  "url": "https://my-webhook.example.com/hook"
}

3. 提示钩子(Prompt Hooks)

钩子内容是一段提示词,由 Claude LLM 评估。主要用于 Stop 和 SubagentStop 事件,进行智能的任务完成度检查。LLM 会返回一个包含 decision 和 reason 的结构化决策。

4. MCP 工具钩子(MCP Tool Hooks,v2.1.118+)

直接调用已配置的 MCP 服务器上的工具。输入数据(工具名、输入、会话上下文)作为 MCP 工具的参数传递。适合将验证逻辑封装在 MCP 服务中。

{
  "type": "mcp_tool",
  "server": "my-mcp-server",
  "tool": "validate_edit"
}

5. 代理钩子(Agent Hooks)

启动一个专用子代理(Subagent)来执行复杂的多步骤评估。与提示钩子的单轮 LLM 评估不同,代理钩子可以使用工具(如 Read、Grep、Bash)进行深入检查。

三、29 个钩子事件全表

Claude Code 提供了 29 个事件,覆盖从会话开始到结束的各个环节。以下是基于源文档的完整事件列表。

事件 触发时机 匹配器输入 可阻断 常见用途
SessionStart 会话开始、恢复、清理、压缩 startup/resume/clear/compact 否 环境设置
Setup 初始化环境(每会话一次) (无) 否 配置工具、安装依赖
InstructionsLoaded CLAUDE.md 或规则文件加载后 (无) 否 修改/过滤指令
UserPromptSubmit 用户提交提示时 (无) 是 验证用户提示
UserPromptExpansion 用户提示被扩展后 (无) 是 转换或检查扩展后的提示
PreToolUse 工具执行前 工具名称 是(允许/拒绝/询问) 验证、修改工具输入
PermissionRequest 权限对话框显示时 工具名称 是 自动批准/拒绝
PermissionDenied 用户拒绝权限提示时 工具名称 否 日志记录、策略执行
PostToolUse 工具执行成功后 工具名称 否 添加上下文、反馈
PostToolUseFailure 工具执行失败后 工具名称 否 错误处理、日志记录
PostToolBatch 一批工具使用完成后 (无) 否 聚合报告、批量验证
Notification 发送通知时 通知类型 否 自定义通知
SubagentStart 子代理启动时 代理类型名称 否 子代理初始化
SubagentStop 子代理完成时 代理类型名称 是 子代理验证
Stop Claude 完成响应时 (无) 是 任务完成检查
StopFailure API 错误结束轮次时 (无) 否 错误恢复、日志记录
TeammateIdle 团队代理空闲时 (无) 是 团队协调
TaskCompleted 任务标记为完成时 (无) 是 任务后操作
TaskCreated 通过 TaskCreate 创建任务时 (无) 否 任务跟踪、日志
ConfigChange 配置文件变更时 (无) 是(策略除外) 响应配置更新
CwdChanged 工作目录变更时 (无) 否 目录特定设置
FileChanged 监视的文件变更时 (无) 否 文件监视、重新构建
PreCompact 上下文压缩前 manual/auto 否 压缩前操作
PostCompact 压缩完成后 (无) 否 压缩后操作
WorktreeCreate 工作树创建时 (无) 是(返回路径) 工作树初始化
WorktreeRemove 工作树移除时 (无) 否 工作树清理
Elicitation MCP 服务器请求用户输入时 (无) 是 输入验证
ElicitationResult 用户响应诱导后 (无) 是 响应处理
SessionEnd 会话终止时 (无) 否 清理、最终日志

关键版本特性:

  • PostToolUse duration_ms(v2.1.119+):PostToolUse 和 PostToolUseFailure 输入新增 duration_ms 字段,记录工具执行时间(毫秒)。
  • Stop 钩子连续阻断上限(v2.1.143+):如果 Stop 钩子连续 8 次返回阻断决策,会话将自动终止并发出警告,防止无限循环。可通过环境变量 CLAUDE_CODE_STOP_HOOK_BLOCK_CAP 调整阈值(设为 0 禁用)。
  • updatedToolOutput 重写所有工具输出(v2.1.121+):PostToolUse 钩子的 hookSpecificOutput.updatedToolOutput 字段现在可用于重写所有工具(如 Bash, Edit, Read)的输出,而不仅仅是 MCP 工具。

四、钩子输入输出与高级用法

输入 JSON 字段表(通过 stdin)

所有钩子都通过 stdin 接收 JSON 输入。关键字段包括 session_id、transcript_path、cwd、hook_event_name、tool_name、tool_input、agent_id、agent_type、worktree 和 effort.level(v2.1.133+)。

退出码与行为

退出码 含义 行为
0 成功 继续,并解析 stdout 中的 JSON
2 阻断错误 阻断操作,stderr 显示为错误信息
其他 非阻断错误 继续,stderr 在详细模式下显示

输出 JSON 格式(stdout,退出码 0)

输出 JSON 可以控制钩子行为。例如,hookSpecificOutput 字段可用于:

  • PreToolUse:设置 permissionDecision(allow/deny/ask)和 updatedInput 修改工具输入。
  • PostToolUse:设置 additionalContext 为 Claude 添加额外信息,或通过 updatedToolOutput 重写工具输出。
  • Stop/SubagentStop:设置 continue: false 来阻断并要求 Claude 继续工作。

可恢复的阻断(continueOnBlock,v2.1.139+)

默认情况下,PostToolUse 钩子返回 "decision": "block" 会中止当前轮次。在钩子配置中设置 "continueOnBlock": true,可以将拒绝信息作为 tool_result 返回给 Claude,让模型读取反馈后重试或调整。

终端序列输出(terminalSequence,v2.1.141+)

输出 JSON 可包含 terminalSequence 字段,向宿主终端发送原始的 OSC 转义序列(如 OSC 9 桌面通知),用于提醒或窗口标题更新。

组件级钩子

钩子可以定义在技能、代理的 frontmatter 中,与其绑定。子代理(Subagent) frontmatter 中定义的 Stop 钩子会自动转换为 SubagentStop 钩子,确保仅在该特定子代理完成时触发。

五、实战示例:从验证到自动化

以下示例展示了如何组合使用钩子。所有脚本均可在 Claude HowTo 教程指南 中找到。

  1. 安全扫描(PostToolUse):在 Write 或 Edit 工具执行后,自动扫描代码中的硬编码密码或 API 密钥,并将警告作为上下文反馈给 Claude。
  2. 自动格式化(PostToolUse):在文件保存后,根据扩展名自动调用 Prettier、Black 或 gofmt 进行代码格式化。
  3. 提示验证(UserPromptSubmit):在 Claude 处理用户输入前,验证提示内容,阻断包含“删除数据库”等危险命令的请求。
  4. 智能停止检查(Prompt-Based Stop Hook):使用提示钩子让 LLM 评估 Claude 是否完成了所有请求的任务,确保任务闭环。
  5. 上下文用量跟踪(Hook 配对):结合 UserPromptSubmit(记录起始 token 数)和 Stop(计算增量)钩子,精确跟踪每次请求的 token 消耗。
  6. 会话结束日志(SessionEnd):在会话结束时提示用户记录学习模块进度,并保存到外部文件。

六、安全注意事项

钩子执行任意 Shell 命令,使用时需自行承担风险。关键安全实践包括:

  • 沙箱与信任:HTTP 钩子在启用沙箱时经过沙箱路由;statusLine 等输出需要工作区信任。
  • 环境变量管理:HTTP 钩子 URL 中使用环境变量需显式配置 allowedEnvVars。
  • 策略控制:组织可通过托管策略的 disableAllHooks 设置全局禁用钩子,用户无法覆盖。
  • 命令注入防护:优先使用 args 数组形式(exec form)执行命令,避免 Shell 解析带来的注入风险。
  • 测试:务必在安全环境中测试钩子脚本。

FAQ

Q: 如何防止 Stop 钩子导致会话死循环? A: 从 v2.1.143 版本起,如果同一个 Stop 钩子连续 8 次返回阻断决策("decision": "block" 或 continue: false),Claude Code 会自动终止会话并发出警告。你可以通过设置环境变量 CLAUDE_CODE_STOP_HOOK_BLOCK_CAP 来调整这个上限(例如设为 5),或者设为 0 来禁用此安全限制。

Q: 在钩子脚本中如何获取当前项目目录的路径? A: 所有钩子脚本都可以通过环境变量 $CLAUDE_PROJECT_DIR 获取项目根目录的绝对路径。在配置钩子命令时,应使用此变量而不是硬编码路径,例如 "$CLAUDE_PROJECT_DIR/.claude/hooks/your-script.sh",这样能确保脚本在不同机器上正确执行。