第二章写 CLAUDE.md 的时候留了一个尾巴:CLAUDE.md 只是「建议」,Agent 大概率会遵守,但不是 100%。你写了「禁止自动 push」,它还是有小概率给你 push 了。
还有一类事情也是这样:改完文件要格式化、改完要检查一下有没有写错、收尾前要扫一遍有没有遗留的 console.log。这些动作靠你记、靠 Agent 自觉,迟早会漏。
Hooks 要做的,就是把「发生了 X,就一定做 Y」从「靠记性」变成「靠系统」:不经过模型判断,到点就执行。
一、Hooks 是什么

回想一下 Agent Loop 的四步:感知上下文 → 模型决策 → 调用工具 → 观察结果。
Loop 在转,但在两步之间,有一些事情你希望自动发生:工具调用之前,先检查一下这条命令能不能跑;工具调用完,顺手格式化一下改动的文件;Agent 准备停下来时,扫一遍有没有遗留的 console.log。
Hooks 就是挂在这些「缝隙」里的脚本。它不是 Agent 在用的工具,是你给整个 Loop 装的触发器。
和 CLAUDE.md 最大的区别是:CLAUDE.md 是讲给模型听的,模型可能不听;Hook 是程序,到点一定执行。
Claude Code 的 Hook 事件有三十多种,覆盖会话开始、用户提交消息、子代理启动、上下文压缩等各个时间点。入门先掌握最常用的三个:
| 事件 | 触发时机 | 典型用途 |
|---|---|---|
PreToolUse |
Agent 准备调用某个工具,但还没执行 | 拦截危险操作 |
PostToolUse |
某个工具调用成功之后 | 自动格式化、检查改动 |
Stop |
Agent 回复完、准备停下来时 | 收尾检查 |
在 Claude Code 里输入 /hooks,可以看到当前配置了哪些 Hook。
二、一个最小的例子
先看一个实际有用的:每次 Agent 改完文件,自动用 Prettier 格式化。
在项目的 .claude/settings.json 里加入:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
这段配置的逻辑是:每次 Edit 或 Write 工具调用成功之后,执行 command 里的命令。
这里有一个关键点:Hook 拿到的信息,是从标准输入(stdin)传进来的一段 JSON,里面有这次调用的工具名、参数等。jq -r '.tool_input.file_path' 就是从这段 JSON 里取出被修改的文件路径,再交给 Prettier。