Claude Code Hooks 实战:5 个让我效率翻倍的自动化配置
用 Claude Code 写代码已经几个月了,最大的感受不是它有多聪明,而是它有多"听话"——你让它干啥它就干啥,但问题是,有些事情你得反复提醒它。
比如每次改完代码不格式化、动了 .env 文件你都不知道、context 压缩之后关键信息丢了……这些事你当然可以每次都手动处理,但说实话,烦。
直到我发现了 Hooks。
Hooks 是什么
简单说,Hooks 就是 Claude Code 生命周期里的"钩子"。你可以在特定时间点自动执行 shell 命令,比如:
- Claude 改完文件后自动跑格式化
- Claude 要执行危险命令前自动拦截
- Claude 等你输入时发桌面通知
- 上下文压缩后自动注入关键信息
跟 Git Hooks 是一个思路——你不用每次手动 git add 再 git commit,pre-commit hook 帮你干了。Claude Code Hooks 也是这个逻辑:把重复性的、需要强制执行的操作自动化掉。
我的 5 个实战 Hook
下面这 5 个是我每天都在用的,配置文件放在 ~/.claude/settings.json 里(全局生效)或者项目目录的 .claude/settings.json(只对当前项目生效)。
1. 桌面通知:再也不用盯着终端了
这是我配的第一个 Hook。用 Claude Code 写代码的时候,经常是让它跑着,我切到浏览器查东西。结果它早就跑完了,在那等我输入,我过了五分钟才切回终端看到。效率拉满。
配了通知之后,Claude 一完成任务或者需要我确认权限,系统就弹通知,我秒切回去。
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
Linux 用 notify-send,macOS 用 osascript -e 'display notification "Claude Code 等你了" with title "Claude Code"',Windows 用 PowerShell。
matcher 留空表示所有通知类型都触发。你也可以只监听特定类型:
permission_prompt:需要你批准工具调用idle_prompt:完成任务等你下一步指令auth_success:认证完成
2. 自动格式化:改完代码不用手动 prettier
Claude 写代码挺快的,但格式不一定完全符合你的项目规范。以前我都是它改完文件,我再手动跑一遍 prettier --write。现在不用了。
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
PostToolUse 是工具调用之后触发,matcher 是 Edit|Write,意思是只在 Claude 编辑或写入文件后才跑。jq 从 hook 的输入 JSON 里提取文件路径,然后传给 prettier。
这个配置用下来最大的好处是:Claude 改什么文件,什么文件就自动格式化,完全无感。你不配这个的话,要么手动跑,要么在 CLAUDE.md 里写"每次改完文件都要跑 prettier"——但那是靠 LLM 自觉,不如 hook 靠谱。
3. 保护敏感文件:不让 Claude 动 .env 和 lock 文件
这个是我踩过坑之后加的。有一次让 Claude 重构项目,它顺手把 .env 里的环境变量也"优化"了——把我的 API Key 格式化了一下,然后整个项目跑不起来了。
从那以后,我配了一个 PreToolUse hook,在 Claude 编辑文件之前检查目标路径,如果是敏感文件就拦截。
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
check_protected.py 的逻辑很简单:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
exit code 的含义:
0:允许,继续执行2:拒绝,Claude 会收到你 stderr 里的拒绝原因,然后调整方案
这个 hook 救了我好几次。有一次 Claude 想删 node_modules 再重新安装来解决依赖问题,被我拦下来了——那可是一个 monorepo,重新装要二十分钟。
4. 上下文注入:压缩后不丢关键信息
用 Claude Code 写复杂功能的时候,对话会越来越长,context window 快满了就会触发压缩。压缩之后很多关键信息就丢了——比如你之前说的项目规范、当前在做什么任务、要用哪个分支。
SessionStart hook 可以在压缩后自动注入这些信息:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
context-reminder.md 长这样:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
matcher: "compact" 表示只在压缩后触发。cat 的输出会直接注入到 Claude 的 context 里,相当于压缩后自动"恢复记忆"。
还有一个骚操作:用 git log --oneline -5 作为 command,这样压缩后 Claude 能看到最近 5 次提交,知道你做到哪了。
5. 权限自动批准:计划模式不用每次确认
Claude Code 有个计划模式(plan mode),它会先给你看执行方案,然后问你"可以开始吗?"每次都要手动点确认,烦。
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
这个 hook 只自动批准 ExitPlanMode(退出计划模式开始执行)的权限请求,其他权限请求(比如执行 shell 命令、写文件)还是正常弹窗让你确认。
警告:matcher 千万别用 .* 或者留空,那会自动批准所有权限请求,包括执行任意 shell 命令。Claude 想跑 rm -rf / 你都不拦着。一定要把 matcher 缩到最小范围。
Hook 的生命周期事件
上面 5 个 Hook 涵盖了最常用的事件类型,但 Claude Code 支持的事件远不止这些。完整列表:
SessionStart:会话开始或恢复UserPromptSubmit:你提交 prompt 之后、Claude 处理之前PreToolUse:工具调用之前(可以拦截)PostToolUse:工具调用之后PostToolUseFailure:工具调用失败之后Notification:Claude 发通知时Stop:Claude 完成回复时ConfigChange:配置文件变更时CwdChanged:工作目录变更时FileChanged:监听的文件变更时PreCompact/PostCompact:上下文压缩前后PermissionRequest:权限弹窗出现时SubagentStart/SubagentStop:子 agent 启动/结束SessionEnd:会话结束
每个事件都有自己的输入数据(通过 stdin 传给你的脚本,JSON 格式),你的脚本可以通过 stdout 返回控制指令。
高级玩法:Prompt 和 Agent 类型的 Hook
除了 command 类型(跑 shell 命令),还有两种高级 hook 类型:
Prompt Hook
用 LLM 做判断。比如你想在 Claude 写代码之前,让另一个模型检查你的 prompt 是否合理:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
适合做安全审计、质量检查这种需要"理解"而非"规则匹配"的场景。
Agent Hook
多轮对话 + 工具调用。比 prompt hook 更强,可以调用工具、做多步推理。目前还是实验性功能。
我个人觉得这两个高级类型用得不多,command 类型已经能覆盖 90% 的场景了。但如果你在做企业级的 Claude Code 部署,prompt hook 做安全审计还是很有价值的。
配置文件放哪里
Hook 配置有三个层级:
~/.claude/settings.json:全局生效,所有项目都用- 项目根目录的
.claude/settings.json:只对当前项目生效 .claude/settings.local.json:本地配置,不进 git
我的建议:
- 通知类的 hook 放全局(你总需要通知)
- 格式化 hook 放项目级(不同项目可能用不同的格式化工具)
- 保护文件的 hook 放全局(所有项目都应该保护
.env) - 上下文注入放项目级(每个项目的规范不同)
调试 Hook
Hook 配错了不会报明显错误,就是不触发,挺难排查的。几个调试技巧:
- 在 Claude Code 里输入
/hooks看当前注册了哪些 hook - 手动跑你的命令看看能不能正常执行
- 加
set -x看 shell 脚本的执行过程 - 用
jq验证你的 JSON 配置格式是否正确
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
进阶:HTTP Hook 发 Webhook 通知
除了跑 shell 命令,hook 还能直接发 HTTP 请求。比如你想在 Claude 完成任务后发个消息到 Slack 或者企业微信:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
这个比 command 类型干净——不用写脚本,直接在配置里声明 HTTP 请求。如果你团队用 Slack/飞书/钉钉做通知,这个很实用。
不过要注意,HTTP hook 的 body 里可以引用事件数据(用模板语法),但具体支持哪些字段得看官方文档。我目前还没深入用这个,主要是 command 类型已经够灵活了。
跟 MCP 配合使用
Hooks 和 MCP 是两个独立的扩展机制,但可以配合使用。比如你有一个 MCP server 提供了代码审查工具,可以用 mcp_tool 类型的 hook 在特定时机调用它:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
这样每次 Claude 写入新文件,自动调用 MCP 服务做代码审查。比在 CLAUDE.md 里写"每次写完文件都要检查一遍"靠谱得多——hook 是确定性执行的,不会被 LLM 忽略。
在 CI/CD 中用 Hooks
Claude Code 有个 Setup 事件,专门给 CI 和脚本用。当 Claude Code 以 --init-only 或 -p 模式启动时触发:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
适合在自动化流水线里用 Claude Code 的场景——每次启动前自动安装依赖、设置环境变量、生成配置文件。
实际场景:一个完整的 hooks 配置
把上面讲的都整合起来,这是我目前在用的完整配置(项目级 .claude/settings.json):
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | |
| 59 | |
注意格式化那个 hook 加了 2>/dev/null || true——如果 prettier 不支持某个文件类型会报错,加这个让它静默失败,不影响 Claude 的工作流。
踩过的坑
Hook 命令路径问题
Hook 执行时的工作目录不一定是你的项目目录。如果你的脚本用了相对路径,可能会找不到文件。建议用绝对路径,或者在脚本里先 cd 到项目目录。
jq 不是所有系统都预装
PostToolUse 的 hook 经常用 jq 解析 JSON。Linux 一般有,macOS 装了 Homebrew 也有,但有些 CI 环境可能没有。提前确认一下。
exit code 2 不是报错
在 hook 里 exit 2 的意思是"拒绝操作",不是"脚本报错"。exit 1 才是真正的错误。别搞混了。
多个 hook 的执行顺序
如果同一个事件有多个匹配的 hook,它们会并行执行,不是按顺序。一个 hook 拒绝不会阻止其他 hook 执行。最严格的结果生效(deny > defer > ask > allow)。
Hooks vs CLAUDE.md vs Skills:该用哪个
很多人会问:我想让 Claude 自动格式化代码,是用 hook 还是在 CLAUDE.md 里写规则?
区别在于确定性。CLAUDE.md 里写"每次改完文件都要跑 prettier",Claude 大概率会遵守,但不是 100%。有时候它会忘,有时候它觉得不需要。Hook 是确定性的——只要触发条件满足,命令一定会执行,没有"LLM 觉得不需要"这回事。
我的建议:
- 需要强制执行的规则(保护文件、格式化、安全检查)→ 用 Hook
- 需要 Claude 理解的指导(代码风格偏好、架构决策)→ 用 CLAUDE.md
- 可复用的工作流(特定语言的开发流程、测试策略)→ 用 Skills
三者不冲突,可以同时用。Hook 管"必须做"的事,CLAUDE.md 管"应该怎么做"的事,Skills 管"怎么做得好"的事。
写在后面
Hooks 是 Claude Code 里比较低调但实用性很高的功能。用好它能省掉很多重复操作,也能避免一些危险情况。
我现在基本是"能 hook 的就 hook",让 Claude 专注在它擅长的事情上——理解需求、写代码、做架构。格式化、保护文件、通知这种"体力活"交给 hook 自动处理。
有啥问题评论区聊。后面打算试试 prompt hook 做代码审查,搞完了再写一篇。