外观
第9章 Hooks自动化
约 2062 字大约 7 分钟
2026-06-07
这一章来聊聊怎么给 Claude 立几条"规矩",让它在干活的时候自动检查、自动把关,不用你每次都盯着。
9.1 Hooks 是什么玩意儿?
还是打个比方
假设你开了一家餐厅,雇了个厨师(就是 Claude)。你希望:
- 做菜之前必须洗手 → 干活之前自动检查
- 菜做好了必须先尝一口 → 干完之后自动检查
- 下班前必须关灯锁门 → 结束之前自动执行
Hooks 就是这些"自动执行的规矩"。 它们会在 Claude 干活的特定时间点自动触发,不需要你手动去管。
Hooks 跟技能有什么不一样?
| 对比项 | 技能(Skills) | Hooks |
|---|---|---|
| 怎么触发 | 你主动说关键词 | 自动触发,你不用管 |
| 干什么用 | 执行一整套流程 | 在关键时刻插一手,做检查或记录 |
| 打个比方 | 快捷按钮 | 自动报警器 |
9.2 Hooks 在什么时候会触发?
Claude Code 提供了这几个"监控点":
| Hook 类型 | 什么时候触发 | 能干什么 |
|---|---|---|
| SessionStart | 刚开始对话时 | 做些初始化工作 |
| UserPromptSubmit | 你发完消息后 | 检查你说的话合不合规 |
| PreToolUse | Claude 要用工具前 | 拦住危险操作 |
| PostToolUse | Claude 用完工具后 | 自动整理格式、记录日志 |
| Stop | 对话快结束时 | 保存状态、发通知 |
9.3 怎么配置 Hooks?
Hooks 写在 .claude/settings.json 文件里。
基本长这样
{
// 整个配置的最外层,就像一栋楼的整体结构图
"hooks": {
// Hook类型:SessionStart / PreToolUse / PostToolUse / Stop
"Hook类型": [
{
// matcher 用来匹配工具名称,决定这个 hook 管谁
"matcher": "匹配的工具名称",
"hooks": [
{
// 目前只有 command 这一种类型,就是跑一段 shell 命令
"type": "command",
// 这里写你要执行的 shell 命令
"command": "要执行的shell命令"
}
]
}
]
}
}几个关键字段的意思:
| 字段 | 意思 | 举个例子 |
|---|---|---|
matcher | 匹配哪些工具 | "Bash"、"Edit"、"Write" |
type | Hook 的类型 | "command"(执行一条命令) |
command | 具体要执行的命令 | 一段命令行 |
9.4 来看几个实际例子
例子1:改完文件自动整理格式(PostToolUse)
想干什么: 每次 Claude 修改完文件后,自动用 Prettier 把格式整理好。
{
"hooks": {
// PostToolUse = 工具用完之后触发,就像菜做完之后的质检
"PostToolUse": [
{
// 匹配 Edit 和 Write 两种工具,都是改文件的操作
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
// 用 npx 调用 prettier 自动格式化,--write 是直接改原文件
// $FILE_PATH 会自动替换成 Claude 改的那个文件路径
"command": "npx prettier --write '$FILE_PATH'"
}
]
}
]
}
}来解释一下:
matcher: "Edit|Write"→ 当 Claude 用 Edit 或 Write 工具改文件时触发command: "npx prettier --write '$FILE_PATH'"→ 对改过的文件执行 Prettier 格式化$FILE_PATH是个变量,会自动替换成被修改的那个文件路径
效果: Claude 改完文件 → 自动整理格式 → 文件始终保持干干净净。
例子2:拦住危险操作(PreToolUse)
想干什么: 不让 Claude 执行 rm -rf 和 DROP TABLE 这种危险命令。
{
"hooks": {
// PreToolUse = 工具执行之前拦截,就像门卫检查身份证
"PreToolUse": [
{
// 只监控 Bash 工具,因为只有执行命令才有 rm -rf 这种风险
"matcher": "Bash",
"hooks": [
{
"type": "command",
// 这条命令的意思:把 Claude 要执行的命令提取出来,
// 检查里面有没有 rm -rf、drop table、truncate 这些危险词
// 有就 exit 2(拦住),没有就 exit 0(放行)
"command": "echo '$ARGUMENTS' | jq -r '.tool_input.command' | grep -iqE 'rm -rf|drop table|truncate' && exit 2 || exit 0"
}
]
}
]
}
}来解释一下:
matcher: "Bash"→ 当 Claude 要执行命令时触发- 这条命令会检查 Claude 要做的事里有没有危险关键词
exit 2表示拦住,不让执行exit 0表示放行
效果: Claude 想执行 rm -rf /tmp/test → Hook 检测到危险 → 自动拦住。
例子3:自动记录 Claude 干了什么(PostToolUse)
想干什么: 自动记下 Claude 每次改了什么文件。
{
"hooks": {
"PostToolUse": [
{
// Edit|Write = Claude 改文件或新建文件的时候
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
// 把时间和文件名追加到日志文件里
// >> 是追加写入,不会覆盖之前的记录
"command": "echo \"[$(date '+%Y-%m-%d %H:%M:%S')] Claude 修改了: $FILE_PATH\" >> ~/.claude/changelog.log"
}
]
}
]
}
}效果: Claude 每次改文件,都会在 ~/.claude/changelog.log 里记下时间和改了哪个文件。
例子4:一启动就自动看看情况(SessionStart)
想干什么: 每次启动 Claude Code 时,自动看看当前项目的状态。
{
"hooks": {
// SessionStart = 刚启动就触发,就像上班先打卡
"SessionStart": [
{
// matcher 留空表示不管啥工具都触发(SessionStart 本来就跟工具无关)
"matcher": "",
"hooks": [
{
"type": "command",
// 先显示哪些文件改了,再显示最近5条提交记录
// 这样一启动就能知道项目当前的状态
"command": "echo '=== Git Status ===' && git status --short && echo '=== Recent Commits ===' && git log --oneline -5"
}
]
}
]
}
}效果: 每次打开 Claude Code,自动显示当前项目状态和最近的操作记录。
9.5 Hook 命令里能用到哪些变量?
写 Hook 命令的时候,可以用这些现成的变量:
| 变量 | 意思 | 举个例子 |
|---|---|---|
$FILE_PATH | 被操作的那个文件的路径 | /project/src/main.py |
$ARGUMENTS | 工具调用的参数(JSON 格式) | {"tool_input":{"command":"ls"}} |
$TOOL_NAME | 工具的名字 | Edit、Bash |
$CLAUDE_EFFORT | 当前思考深度级别 | high |
9.6 Hook 执行完会怎样?
Hook 命令执行完后的"退出码"决定了接下来发生什么:
| 退出码 | 含义 | 会怎样 |
|---|---|---|
0 | 一切正常 | 继续该干嘛干嘛 |
2 | 拦住 | 阻止当前操作 |
| 其他 | 出错了 | 显示错误信息,但一般还会继续 |
9.7 有几点要注意的
1. Hook 命令别太慢
Hook 是同步执行的,就是说 Claude 得等 Hook 跑完才能继续干活。如果你的 Hook 命令要跑好几秒,Claude 就得傻等着。
提示
Hook 命令最好控制在 1 秒以内。
2. Hook 适合干简单的事
Hook 适合做简单的检查和记录,不适合做复杂的数据处理。
3. Hook 没按预期工作怎么办?
排查思路:
- 在终端里手动跑一遍 Hook 命令,看看输出是什么
- 检查变量有没有正确替换
- 确认命令的退出码对不对
4. Hook 的作用范围
跟权限一样,Hook 配置也分全局和项目级的:
| 位置 | 谁生效 |
|---|---|
~/.claude/settings.json | 全局,所有项目都生效 |
项目目录/.claude/settings.json | 只在当前项目生效 |
9.8 一个完整的配置长什么样?
把上面几个例子组合起来,一个完整的 settings.json 大概长这样:
{
// permissions 放权限配置,和 hooks 是平级的
"permissions": {
// allow = 白名单,这些操作不用问你直接放行
"allow": ["Read", "Bash(git status*)", "Bash(npm test*)"],
// deny = 黑名单,这些操作绝对不让执行
"deny": ["Bash(rm -rf*)"]
},
"hooks": {
// 启动时自动看项目状态
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
// --short 是简洁模式,一行一个文件
// -3 表示只看最近3条提交
"command": "git status --short && git log --oneline -3"
}
]
}
],
// 执行命令前检查是否危险
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo '$ARGUMENTS' | jq -r '.tool_input.command' | grep -iqE 'rm -rf|drop table' && exit 2 || exit 0"
}
]
}
],
// 改完文件后记录日志
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
// Modified 用英文是因为日志文件一般保持英文更通用
"command": "echo \"[$(date '+%Y-%m-%d %H:%M:%S')] Modified: $FILE_PATH\" >> ~/.claude/changelog.log"
}
]
}
]
}
}9.9 这一章聊了啥
| 要点 | 简单说 |
|---|---|
| Hooks 是什么 | Claude 干活时自动触发的"规矩" |
| 什么时候触发 | 开始时、用工具前后、结束时 |
| 常用来干什么 | 拦住危险操作、自动整理格式、记录日志 |
| 配在哪 | .claude/settings.json 的 hooks 字段 |
| 注意什么 | 命令要快、操作要简单、记得调试 |
相关信息
一句话总结: Hooks 是 Claude Code 的"自动质检员",在关键时刻自动帮你把关。
下一章来聊聊 怎么在编辑器里直接用 Claude,边写边问更方便!
