Claude Code Hooks 入门 5 分钟让 AI 编码助手自动干活

目标读者:用过 Claude Code、想做工作流自动化的开发者预计阅读时间:6 分钟


令人困扰的操作环节

每次 Claude Code 完成代码修改后,你是不是还得亲自再跑一次 prettier 进行格式化?

格式化结束,紧接着还得记得运行测试?

更让人捏把汗的是,它偶尔会生成一条 rm -rf 命令——即使它大概率不会真删错,你的手指已经下意识准备按下 Ctrl+C 了。

这些重复性强又至关重要的步骤,能否让它自行完成?能不能在危险指令真正生效之前,为你设下一道防护?

hooks 就是干这个的。

理解 Hook

一句话概括:Hook 是在 Claude Code 生命周期的特定节点自动运行的命令

你可以将它类比为 Git 的 pre-commit 钩子,但触发时机变成了“用户提交 prompt”“工具调用前后”以及“响应结束”等节点。

当相应事件发生时,Claude 会自动执行你预设好的脚本。

⚡ Hook 与 CLAUDE.md 的区别

CLAUDE.md 指令

Hook

执行方式

模型“理解”后自主决定

由代码触发,确定性执行

可靠性

偶尔遗漏

每次必运行,无一例外

适用场景

需要判断力的软性规则

必须强制遵守的硬性规则

下图展示了一次完整交互中 Hook 的触发位置:

图1:Hook 生命周期触发顺序

图1:Hook 生命周期触发顺序——从左侧入口进入,右侧出口退出,中间可能循环多次。你的 Hook 可以挂载在任何一个标注了事件名称的箭头上。

从左侧进入、右侧退出,中间环节可能重复循环。你可以在图中任何一个标注了事件名的箭头上挂载 Hook。

5 分钟上手:你的第一个 hook

hook 写在 settings.json 里,结构是三层嵌套:

事件名 → matcher(匹配的工具)→ hooks(执行的动作)

这看似套娃式结构,实际配置起来非常直观。

以下 hook 的作用:每当 Claude 完成文件写入或编辑后,自动执行 prettier 格式化。

// 📁 .claude/settings.json
{
  "hooks": {
    "PostToolUse": [          // ← 事件名:工具执行完毕后触发
      {
        "matcher": "Edit|Write",  // ← 限定只匹配写文件类的工具
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

逐字段解析:

  1. PostToolUse — 事件名称,表示“工具执行完成后触发”
  2. matcher: "Edit|Write" — 使用管道符号匹配两个工具名称,仅当涉及写文件操作时才会激活
  3. type: "command" — 执行一条 shell 命令
  4. jq -r '.tool_input.file_path' — 从标准输入的 JSON 中提取文件路径,通过 xargs 传递给 prettier

💡 核心机制

hook 的事件上下文通过 stdin 以 JSON 格式传入,包含 tool_nametool_input 等字段,脚本利用 jq 进行解析。所有案例中提取数据都沿用这一模式。

将这段 JSON 粘贴到配置文件中,保存后 hook 会立刻生效。

想要验证?让 Claude 随便修改一个文件,观察缩进是否变得规整——如果变化了,就说明 hook 正在运行。

配置文件存放位置

文件路径

作用范围

适用场景
~/.claude/settings.json
用户级别,适用于所有项目

个人偏好:通知、日志
.claude/settings.json
项目级别,可提交到仓库

团队规范:代码格式化、lint 检查
.claude/settings.local.json
本地级别,被 gitignore 忽略

临时配置,不影响团队其他人

核心事件速查表

在日常开发中,最常用的其实只有 5 个事件,掌握这张表格基本就能应对大部分场景:

事件名 触发时机 典型用途 记忆口诀
PreToolUse 工具调用前 拦截危险命令、保护敏感文件 拦截用 Pre
PostToolUse 工具调用后 自动格式化、lint、类型检查 善后用 Post
UserPromptSubmit 用户提交 prompt 后 注入上下文、校验输入 开头加料用它
Notification 触发通知时 软提醒、消息推送 旁路轻量提醒
Stop Claude 结束响应时 桌面通知、强制跑测试 结尾卡关用 Stop

📚 延伸阅读

官方还提供了 SessionStartSubagentStopPreCompact 等 30 多个事件,具体可查阅官方文档。对于绝大多数日常需求,以上五个事件就已经足够覆盖。

3 个实战案例

案例一:拦截危险命令

PreToolUse 上部署一个检查脚本,如果检测到 rm -rfDROP TABLE 这样的危险指令,就用 exit 2 进行拦截:

// 📁 .claude/settings.json{  "hooks": {    "PreToolUse": [      {        "matcher": "Bash",        "hooks": [          {            "type": "command",            "command": "COMMAND=$(jq -r '.tool_input.command'); echo \"$COMMAND\" | grep -qE 'rm -rf|DROP TABLE' && exit 2 || exit 0"          }        ]      }    ]  }}

这一行代码的核心逻辑很清晰:从标准输入读取命令 → 用 grep 检查是否匹配危险模式 → 命中时 exit 2 阻止执行 → 未命中时 exit 0 放行。

实际测试显示:Claude 会收到"操作被阻断"的提示,随后改用更安全的方式完成任务,而不会强行突破限制。


案例二:任务完成时弹出桌面通知

执行耗时任务时无需一直盯着终端——在 Stop 事件上绑定系统通知即可:

// 📁 .claude/settings.json{  "hooks": {    "Stop": [      {        "hooks": [          {            "type": "command",            "command": "osascript -e 'display notification \"任务已完成\" with title \"Claude Code\"'"          }        ]      }    ]  }}

💡 跨平台使用说明

  • macOS 系统 → 使用 osascript
  • Linux 系统 → 使用 notify-send "任务已完成"

配置完成后,每次 Claude 执行完任务,屏幕右上角就会弹出一个气泡提示,提醒你回来查看结果。


案例三:注入 git 分支上下文

通过 UserPromptSubmit 将当前分支名称传递给 Claude,让它清楚自己正在哪个分支上工作:

// 📁 .claude/settings.json{  "hooks": {    "UserPromptSubmit": [      {        "hooks": [          {            "type": "command",            "command": "echo \"当前分支: $(git branch --show-current)\""          }        ]      }    ]  }}

UserPromptSubmit 输出的纯文本 stdout 会直接作为上下文注入到对话中。效果很明显:Claude 在生成提交信息或操作文件时,会自动感知当前所处的分支——比如你在 feature/auth 分支上,它就不会误操作 main 分支的内容。

规避陷阱与安全底线

Exit Code 通信协议

hook 与 Claude 之间的交互机制相当简洁——全部依靠 exit code 来决定:

Exit Code 含义 行为表现
0 放行 一切正常,程序继续推进
2 阻断 当前操作被拦截,stderr 内容回传给 Claude
其他非零值 非阻断错误 仅 verbose 模式下显示,操作照常执行

⚠️ 常见误区exit 1 并不能阻止操作!如果需要强制拦截,必须使用 exit 2

调试方法

手动向脚本传入数据进行测试:

# 模拟危险指令输入,检验 hook 是否能正确拦截
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | your-hook.sh
echo $?  # 预期结果:2

如果已经配置了 hook 却始终无法触发,多半是 JSON 语法存在错误——可以通过 /hooks 菜单查看配置是否成功加载。

⚠️ 安全底线

hook 会以你当前的本地权限执行任意指令,恶意脚本可能窃取数据或删除文件。切勿随意复制网上的 hook 配置,在注册之前务必读懂每一行代码的作用。hook 运行在 agent 循环中,自动触发、无需确认,一旦出现问题你可能毫无察觉。

Hook 的适用场景

Hook 并非万能工具,只有在合适的场景下使用才能真正省心:

场景 推荐方案 理由
确定性自动化、强制规则 ✅ Hook 格式化、拦截、提交前测试等"必须每次执行"的操作
需要判断力的任务 ❌ 用 subagent 或 prompt handler 规则难以写死、需要模型进行思考判断的场景
一次性临时操作 ❌ 手动执行 仅为执行一次的命令配置 hook,反而徒增复杂度

💡 实用判断标准

如果你在某个操作之后总是手动重复执行同一条命令,那么就应该考虑将它改造成 hook。反之,如果操作不固定、逻辑涉及分支判断,使用 CLAUDE.md 指令或 subagent 更为恰当。

后续步骤

现在你已熟悉 hook 的核心机制,可以尝试以下进阶操作:

  1. 从单个 hook 入手 — 将你最常用的某条命令配置为一个 hook,先试用两天,体验其效果
  2. 循序渐进地扩展 — 依次添加格式化、lint 检查、危险操作拦截、通知提醒等功能,逐步完善你的配置
  3. 查阅完整事件清单 — 除了文中提到的 5 个事件,Git 还提供了 30 余个事件,等待你进一步探索

参考链接

  • 自动化工作流:Claude Code Hooks — 事件类型与配置结构详解
  • 2026年3月版Claude Code Hooks完整指南 — 事件、处理器与退出代码机制
  • 使用Claude Code Hooks实现自动化操作 — 实战配置范例
  • Claude Code中文教程第24章:hooks — 面向入门的中文讲解
0 1

评论区 (3)

发表评论

共有 3 条评论

avatar
Ctrl+C恐惧症27 天前

这个`rm -rf`防护的比喻简直说到我心坎里去了,每次看到AI生成那条命令都得先默念三遍"别手抖"。hooks自动格式化确实能省不少事,以前老忘记跑lint,现在终于不用事后补救了。

avatar
代码敲不碎1 个月前

之前一直用CLAUDE.md加软性提示,结果经常漏掉格式化步骤。看了这个hooks确定性执行的对比,果断去配了PostToolUse的prettier,自动跑起来的感觉真爽。

avatar
全栈小菜鸟1 个月前

刚按文章把prettier hook配上了,真的5分钟搞定!以前每次手动跑格式化烦死了,现在改了文件自动美颜,可操作性满分,就差把测试也挂上去了。