Hooks 系统
完整掌握 Claude Code Hooks — 17 种生命周期事件、3 种处理器类型、10+ 实战 Recipe 与企业级配置
Hooks 系统¶
Hooks 允许你在 Claude Code 的关键生命周期节点插入自定义逻辑 — 自动格式化代码、拦截危险命令、发送通知、审计日志等。Hooks 是 Claude Code 最强大的扩展机制之一。
一、核心概念¶
每个 Hook 由三部分组成:
事件(When) → 匹配器(Which) → 处理器(What)
PreToolUse matcher: "Bash" command: "check_safety.sh"
- 事件:触发时机(如
PreToolUse— 工具执行前) - 匹配器:可选的工具名过滤(如只匹配
Bash或Write) - 处理器:Shell 命令、提示词注入 或 子代理
二、完整事件列表¶
核心事件¶
| 事件 | 触发时机 | 可阻断 | 典型用例 |
|---|---|---|---|
| PreToolUse | 工具执行前 | 是(exit 2) | 安全拦截、参数校验 |
| PostToolUse | 工具执行后 | 否 | 自动格式化、日志记录 |
| Notification | Claude 发送通知 | 否 | Slack/飞书/钉钉告警 |
| Stop | Claude 完成响应 | 否 | 质检、自动提交 |
| UserPromptSubmit | 用户提交提示 | 是 | 上下文注入、策略检查 |
| SessionStart | 会话启动 | 否 | 环境初始化、欢迎信息 |
扩展事件(2026 新增)¶
| 事件 | 触发时机 | 可阻断 | 典型用例 |
|---|---|---|---|
| SubagentStop | 子代理完成 | 否 | 收集子代理结果 |
| SubagentToolUse | 子代理使用工具 | 是 | 限制子代理权限 |
| FileChanged | 文件被修改 | 否 | 自动 lint、触发构建 |
| CwdChanged | 工作目录变更 | 否 | 加载目录特定配置 |
| ModelChange | 模型切换 | 否 | 记录模型使用统计 |
| CompactComplete | /compact 完成 | 否 | 上下文压缩后处理 |
| ToolError | 工具执行出错 | 否 | 错误收集、自动重试逻辑 |
三、Hook 处理器类型¶
类型 1:Command(Shell 命令)¶
最常用的类型,执行 Shell 命令:
{
"type": "command",
"command": "npx prettier --write $FILEPATH"
}
环境变量:
| 变量 | 说明 | 可用事件 |
|------|------|---------|
| $FILEPATH | 操作的文件路径 | PreToolUse/PostToolUse |
| $TOOL_INPUT | 工具输入 JSON | PreToolUse |
| $TOOL_NAME | 工具名称 | PreToolUse/PostToolUse |
| $SESSION_ID | 会话 ID | 所有 |
| $NOTIFICATION_MESSAGE | 通知内容 | Notification |
退出码:
0:允许继续2:阻断操作(仅 PreToolUse/UserPromptSubmit)- 其他:视为错误但不阻断
类型 2:Prompt(提示注入)¶
将文本注入 Claude 的上下文:
{
"type": "prompt",
"prompt": "记住:所有数据库操作必须使用事务"
}
适用场景:在 SessionStart 时注入额外的项目规则。
类型 3:Subagent(子代理)¶
生成子代理处理事件:
{
"type": "subagent",
"prompt": "审查刚刚修改的代码,检查是否有安全漏洞"
}
适用场景:PostToolUse 后自动审查代码质量。
四、配置方式¶
在 .claude/settings.json(项目级)或 ~/.claude/settings.json(用户级)中配置:
{
"hooks": {
"事件名": [
{
"matcher": "工具名(可选,支持 | 分隔多个)",
"hooks": [
{
"type": "command|prompt|subagent",
"command": "..."
}
]
}
]
}
}
五、实战 Recipe¶
Recipe 1:文件保存后自动格式化¶
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $FILEPATH 2>/dev/null || true"
}
]
}
]
}
}
Recipe 2:拦截危险的 Shell 命令¶
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo $TOOL_INPUT | grep -qE 'rm -rf /|sudo rm|git push --force|DROP TABLE|DROP DATABASE' && echo '危险命令已拦截' && exit 2 || exit 0"
}
]
}
]
}
}
Recipe 3:保护敏感文件¶
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Write|Edit",
"hooks": [
{
"type": "command",
"command": "echo $TOOL_INPUT | grep -qE '\\.env|\\.env\\.|credentials|secrets?\\.ya?ml|private.key' && echo '敏感文件访问已拦截' && exit 2 || exit 0"
}
]
}
]
}
}
Recipe 4:任务完成后系统通知¶
macOS:
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"$NOTIFICATION_MESSAGE\" with title \"Claude Code\"'"
}
]
}
]
}
}
Linux:
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' \"$NOTIFICATION_MESSAGE\""
}
]
}
]
}
}
Recipe 5:Slack 通知¶
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "curl -s -X POST https://hooks.slack.com/services/xxx/yyy/zzz -H 'Content-Type: application/json' -d '{\"text\": \"Claude Code 任务完成\"}'"
}
]
}
]
}
}
Recipe 6:ESLint 自动修复¶
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx eslint --fix $FILEPATH 2>/dev/null; npx prettier --write $FILEPATH 2>/dev/null; exit 0"
}
]
}
]
}
}
Recipe 7:审计日志¶
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) | session=$SESSION_ID | tool=$TOOL_NAME | file=$FILEPATH\" >> ~/.claude/audit.log"
}
]
}
]
}
}
Recipe 8:自动运行测试¶
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "echo $FILEPATH | grep -qE '\\.(ts|tsx|js|jsx)$' && echo $FILEPATH | grep -qvE '\\.test\\.|\\.spec\\.' && npx vitest related $FILEPATH --run 2>/dev/null || exit 0"
}
]
}
]
}
}
Recipe 9:保护迁移文件¶
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "echo $FILEPATH | grep -qE 'migrations/|alembic/versions/' && echo '禁止修改已有迁移文件,请创建新迁移' && exit 2 || exit 0"
}
]
}
]
}
}
Recipe 10:会话启动时注入上下文¶
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "prompt",
"prompt": "重要提醒:本项目正在进行 v3.0 大版本重构,所有新代码必须使用 React Server Components,不再支持 pages/ 目录。"
}
]
}
]
}
}
六、企业级 Hooks¶
managed-settings.d/ 配置¶
企业管理员可通过 managed-settings.d/ 目录强制全组织的安全策略:
# 在企业管理目录中创建策略文件
mkdir -p /etc/claude-code/managed-settings.d/
// /etc/claude-code/managed-settings.d/security.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/opt/claude-policy/check_command.sh"
}
]
}
],
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "/opt/claude-policy/audit_log.sh"
}
]
}
]
}
}
企业策略无法被用户或项目级配置覆盖。
七、调试与排错¶
Verbose 模式¶
按 Ctrl+O 开启 verbose 模式,可以看到:
- Hook 被触发的时机
- Hook 脚本的 stdout/stderr 输出
- Hook 的退出码
常见问题¶
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Hook 不触发 | matcher 拼写错误 | 检查工具名大小写:Bash、Write、Edit、Read |
| Hook 阻断了正常操作 | exit code 逻辑错误 | 确保正常情况 exit 0,只在需要拦截时 exit 2 |
| Hook 执行很慢 | 脚本耗时过长 | Hook 应在 1-2 秒内完成,长任务用后台执行 |
| 环境变量为空 | 事件不提供该变量 | 检查上方环境变量表,确认变量在该事件中可用 |
测试 Hook 脚本¶
在终端中手动测试,再放入配置:
# 模拟 PreToolUse 的环境变量
FILEPATH="src/main.ts" TOOL_INPUT="rm -rf /" bash -c 'echo $TOOL_INPUT | grep -qE "rm -rf" && echo "blocked" && exit 2 || exit 0'
八、与 Codex Hooks 对比¶
| 维度 | Claude Code Hooks | Codex Hooks |
|---|---|---|
| 事件数量 | 17 种 | 较少 |
| 配置方式 | settings.json | config.toml |
| 处理器类型 | command/prompt/subagent | command |
| 企业管理 | managed-settings.d/ | 无 |
| 阻断能力 | exit code 2 | 有限 |
下一步¶
- Skills 技巧 — 更高级的扩展方式
- MCP 服务器 — 连接外部工具
- 自动化与 CI/CD — 无头模式使用
- CLI 技巧 — 命令行使用技巧