Claude Code 的钩子系统允许你在 29 个预定义事件发生时自动执行脚本、HTTP 请求或 LLM 提示,从而拦截、验证或增强 Claude 的行为。系统提供 5 种钩子类型,通过简单的 JSON 配置即可构建从代码格式化到安全策略执行的完整自动化工作流。
Claude Code Hooks 系统深度指南:29 个事件、5 种钩子类型与自动化工作流
Claude Code 的钩子(Hooks)是事件驱动的自动化脚本,能够在 Claude Code 会话的特定关键时刻自动执行,用于验证输入、修改输出、执行安全策略或集成外部系统。本文将深入解析其配置、事件、类型和实战应用。
一、钩子配置与匹配模式
钩子配置在多个层级的 settings.json 文件中,遵循特定的 JSON 结构。
配置层级(从高到低):
- 托管策略:组织级设置,用户无法覆盖。
- 用户设置:
~/.claude/settings.json,应用于所有项目。 - 项目设置:
.claude/settings.json,可提交到版本库。 - 本地项目设置:
.claude/settings.local.json,不提交。 - 插件钩子:插件目录下的
hooks/hooks.json。 - 组件钩子:定义在技能(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 教程指南 中找到。
- 安全扫描(PostToolUse):在
Write或Edit工具执行后,自动扫描代码中的硬编码密码或 API 密钥,并将警告作为上下文反馈给 Claude。 - 自动格式化(PostToolUse):在文件保存后,根据扩展名自动调用 Prettier、Black 或 gofmt 进行代码格式化。
- 提示验证(UserPromptSubmit):在 Claude 处理用户输入前,验证提示内容,阻断包含“删除数据库”等危险命令的请求。
- 智能停止检查(Prompt-Based Stop Hook):使用提示钩子让 LLM 评估 Claude 是否完成了所有请求的任务,确保任务闭环。
- 上下文用量跟踪(Hook 配对):结合
UserPromptSubmit(记录起始 token 数)和Stop(计算增量)钩子,精确跟踪每次请求的 token 消耗。 - 会话结束日志(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",这样能确保脚本在不同机器上正确执行。