看累了听个音乐吧
8.2 Hook 事件类型详解

四个时间点,四种控制方式
Claude Code 提供四个 Hook 事件,覆盖了会话的关键时间点:
会话开始
↓
[SessionStart Hook]
↓
Claude 决定调用某个工具
↓
[PreToolUse Hook] ← 可以在这里阻止
↓
工具执行
↓
[PostToolUse Hook] ← 可以在这里处理结果
↓
Claude 等待你输入
↓
[Notification Hook] ← 可以在这里发通知PreToolUse — 工具调用前拦截
触发时机: Claude Code 准备调用一个工具,但还没调用
最强大的事件,因为你可以在这里:
- 检查工具参数,决定是否允许执行
- 修改传入的参数(通过 stdout 输出新参数)
- 直接阻止这次工具调用(exit code 2)
Hook 收到的 JSON 输入(通过 stdin):
json
{
"tool_name": "Edit",
"tool_input": {
"file_path": "/path/to/file.ts",
"old_string": "...",
"new_string": "..."
}
}常见用途:
- 阻止修改
.env、package-lock.json等敏感文件 - 阻止运行危险命令(
rm -rf、git push --force) - 记录每次文件修改的审计日志
PostToolUse — 工具调用后处理
触发时机: 工具执行完毕之后
收到的 JSON 输入:
json
{
"tool_name": "Edit",
"tool_input": {
"file_path": "/path/to/file.ts"
},
"tool_response": {
"success": true
}
}常见用途:
- 文件修改后自动格式化(Prettier、gofmt、black)
- 文件修改后自动运行相关测试
- 记录操作日志
Notification — 等待输入时触发
触发时机: Claude Code 完成了一段工作,正在等待你的输入或确认
常见用途:
- 发桌面通知(你离开了屏幕,它做完了叫你回来看)
- 发 Slack 消息
- 播放提示音
这个 Hook 没有 JSON 输入,不需要解析参数,只是一个"叫你回来"的信号。
SessionStart — 会话开始时触发
触发时机: 两种情况
- 新会话启动时
- 上下文压缩(compaction)完成后恢复时
重要: 上下文压缩会丢失对话历史,但 SessionStart Hook 可以在压缩后自动重新注入关键信息。
常见用途:
- 压缩后重新注入关键上下文("这是一个 TypeScript 项目,不要用 any")
- 会话开始时打印项目状态摘要
- 检查环境变量是否设置正确
Hook 配置格式
所有 Hook 配置都写在 settings.json 里:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "你的脚本命令"
}
]
}
],
"PostToolUse": [...],
"Notification": [...],
"SessionStart": [...]
}
}matcher 字段: 用正则或工具名过滤,只对匹配的工具触发
"Edit|Write":只对文件编辑/写入触发"Bash":只对命令执行触发""(空字符串):对所有工具触发
Exit Code 的含义
Hook 脚本的退出码决定了 Claude Code 的行为:
| Exit Code | 含义 | 适用事件 |
|---|---|---|
0 | 成功,继续执行 | 所有事件 |
2 | 阻止这次操作 | 只有 PreToolUse |
| 其他非零值 | 报告错误,但继续执行 | 所有事件 |
Exit code 2 是最关键的——它让你的 Hook 有能力说"不"。
用 stderr 给 Claude 解释原因:
bash
echo "Blocked: .env files cannot be modified" >&2
exit 2Claude Code 会把 stderr 的内容告诉 AI,让它知道为什么被阻止,从而调整方案。
下一节,动手写几个真实可用的 Hook。
