Claude Code Hooks 超详细教程,附源码
上周五晚上十一点半,我让 Claude Code 帮我改一段 API 认证逻辑。结果它改完顺手把 .env 文件里的数据库密码给删了——你没看错,直接清空了。部署上去之后服务全挂,我硬生生排查到凌晨两点才发现问题。
当时我就想:能不能让 AI 在碰关键文件之前拦它一下?
翻了两天文档,发现 Claude Code 在 2026 年初正式上了 Hooks 系统。说白了就是给 AI 编码助手装了个"保险丝"——改文件之前自动检查,改完之后自动跑测试,完事了还能给你发个通知。
今天这篇文章把我踩过的坑和最终跑通的配置全部整理出来,你直接抄就行。
Hooks 到底是啥?
Hooks 就是你在 settings.json 里定义的自动触发规则。Claude Code 在特定的时间点会执行你指定的 shell 命令,比如:
- 改文件之前 → 检查这个文件是不是受保护的
- 改文件之后 → 自动跑 prettier 格式化
- AI 干完活之后 → 发一条桌面通知
- Claude 要执行命令之前 → 拦截危险操作(比如
rm -rf)
配置文件放在项目根目录的 .claude/settings.json 里。
环境准备
先确认你的 Claude Code 版本支持 Hooks:
claude --version
# 需要 2026.1 以上版本
没有的话更新一下:
npm install -g @anthropic-ai/claude-code@latest
然后在项目根目录创建配置目录:
mkdir -p .claude
touch .claude/settings.json
六个核心事件
Claude Code Hooks 支持这些触发时机:
| 事件 | 触发时间 | 能不能拦截 |
|---|---|---|
PreToolUse | AI 执行工具之前 | ✅ 能,exit 1 就拦住了 |
PostToolUse | 工具执行之后 | ❌ 只能做后续处理 |
Stop | AI 完成整轮回答后 | ❌ |
Notification | AI 发通知时(等你确认等) | ❌ |
UserPromptSubmit | 你提交 prompt 时 | ❌ |
SessionStart | 新会话开始时 | ❌ |
其中 PreToolUse 是唯一能拦截动作的 hook——它就像一个安全门卫,不满意就直接 exit 1 拒绝执行。
实战一:保护关键文件(别再让 AI 碰 .env 了)
这是我配置的第一个 hook,也是我认为每个人都应该加的。
先写一个拦截脚本 .claude/hooks/block-critical.sh:
#!/bin/bash
# 从 stdin 读取 Claude 传来的 JSON 数据
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# 受保护文件列表
BLOCKED_FILES=(
".env"
".env.production"
"src/middleware.ts"
"src/app/api/auth/route.ts"
"docker-compose.yml"
)
for file in "${BLOCKED_FILES[@]}"; do
if [[ "$FILE_PATH" == *"$file"* ]]; then
echo "⛔ BLOCKED: $FILE_PATH 是受保护文件,需要手动编辑!"
exit 2 # exit 2 = 拦截并告知原因
fi
done
exit 0 # 放行
然后在 settings.json 里注册:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/block-critical.sh"
}
]
}
]
}
}
matcher 用的是正则匹配工具名——Edit|Write|MultiEdit 覆盖了所有文件编辑操作。
现在 Claude Code 想动我的 .env?直接弹红字拒绝:
⛔ BLOCKED: .env 是受保护文件,需要手动编辑!
舒服了。
实战二:改完代码自动格式化 + 跑 lint
说实话,AI 写的代码功能没问题,但风格经常一言难尽。缩进忽大忽小、引号单双混用、import 顺序乱七八糟。
用 PostToolUse hook 在每次编辑后自动格式化:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $FILEPATH && npx eslint --fix $FILEPATH"
}
]
}
]
}
}
Python 项目换成这样:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "black $FILEPATH && isort $FILEPATH"
}
]
}
]
}
}
跑起来之后你发现 Claude 写完代码,eslint 自动修了一堆小问题,prettier 统一了风格——基本不需要手动调格式了。
实战三:拦截危险命令
这条救过我好几次命。AI 有时候会执行 npm install xxx 往 dependencies 里塞东西,或者跑 rm -rf 清目录。
创建 .claude/hooks/block-dangerous-cmd.sh:
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
# 危险命令黑名单
DANGEROUS_PATTERNS=(
"rm -rf /"
"rm -rf ~"
"DROP TABLE"
"truncate"
"DROP DATABASE"
"> /dev/sda"
)
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
if [[ "$CMD" == *"$pattern"* ]]; then
echo "🚫 DANGER: 检测到危险命令 '$CMD',已拦截!"
exit 2
fi
done
# 拦截生产依赖安装(除非带 --save-dev)
if echo "$CMD" | grep -qE "npm install|yarn add|pnpm add"; then
if ! echo "$CMD" | grep -q "\-\-save-dev\|-D"; then
echo "⚠️ 拦截: 往生产依赖里装包需要人工确认。加上 --save-dev 或 -D 可以绕过。"
exit 2
fi
fi
exit 0
注册到 settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/block-dangerous-cmd.sh"
}
]
}
]
}
}
这条规则拦住了 AI 往 dependencies 里塞包的行为——想装包?行,加 --save-dev 说明是开发依赖,否则不让装。
实战四:任务完成自动通知
跑长任务的时候(比如让 Claude 重构一整个模块),我不想一直盯着终端。用 Stop hook 发个桌面通知:
macOS 用户:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code 任务完成\" with title \"提示\" sound name \"default\"'"
}
]
}
]
}
}
Linux 用户(需要 notify-send):
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' '任务完成!可以回来看了'"
}
]
}
]
}
}
搭配 Slack webhook 还能推到群里,远程协作的时候特别方便。
我的完整配置(直接抄)
把上面几个 hook 合到一起,这是我目前在用的完整 settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/block-critical.sh"
}
]
},
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/block-dangerous-cmd.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $FILEPATH && npx eslint --fix $FILEPATH 2>/dev/null || true"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude 干完活了\" with title \"Claude Code\"' 2>/dev/null || true"
}
]
}
]
}
}
注意 2>/dev/null || true——这很关键。hook 执行失败默认会中断 AI 操作,加上这俩可以确保通知失败也不影响正常流程。
三种 Handler 类型
上面我全用的 command 类型,其实 Hooks 还支持另外两种:
| 类型 | 怎么工作 | 适合干啥 |
|---|---|---|
| command | 跑 shell 命令,stdin 传 JSON | 格式化、lint、文件检查 |
| prompt | 把上下文发给 Claude 模型做单轮判断 | 安全审查、架构评审 |
| agent | 启动一个子 Agent 深度检查 | 跨文件依赖分析、数据库迁移验证 |
prompt 类型挺有意思的——可以在 AI 改代码之前,让另一个 Claude 实例判断这个改动安不安全:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "prompt",
"prompt": "分析这次编辑操作:$ARGUMENTS。如果涉及认证逻辑、数据库操作、支付相关、密钥处理中的任何一项,回复 DENY 并说明原因。否则回复 APPROVE。"
}
]
}
]
}
}
不过这个会多消耗一次 API 调用的 token,我目前只在处理支付和认证模块的时候才开。
常见问题 FAQ
Q: Hooks 配置了但没生效?
检查三个地方:
- 文件路径对不对——必须在项目根目录的
.claude/settings.json - JSON 格式有没有错——
jq .claude/settings.json跑一下验证 - hook 脚本有没有执行权限——
chmod +x .claude/hooks/*.sh
Q: hook 脚本里怎么拿到 Claude 正在操作的文件路径?
通过 stdin 传入的 JSON。用 jq 提取:
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
Q: 能不能在 CI/CD 里用 Hooks?
当然可以。Claude Code 的 headless 模式(claude -p)同样触发 hooks。搭配 --allowedTools 参数可以把 AI 的权限锁死在特定命令范围内,再加上 hooks 做安全兜底,双层保险。
Q: prompt 类型的 hook 延迟太高怎么办?
确实,prompt 类型要调一次 API,通常多 2-5 秒。建议只在关键操作(认证、支付、数据库)上用 prompt hook,日常编辑用 command hook 就够了。
Q: 能不能异步执行 hook?
目前所有 hook 都是同步的——Claude 会等 hook 执行完再继续。所以 hook 脚本别写太重的操作(比如跑完整测试套件),会卡住 AI。轻量级检查(lint 单文件、检查文件名)通常几百毫秒搞定。
踩坑总结
搞了一周 Hooks,踩了几个坑分享下:
- hook 脚本里不要用
set -e——Claude 靠 exit code 判断结果,set -e会让某些预期内的失败变成意外退出 - PostToolUse 里不要跑全量测试——太慢了,AI 会等你跑完才继续,体验很差。只对单个文件做 lint 就行
- matcher 是正则不是 glob——
Edit|Write这样写,别写成Edit,Write - Windows 用户注意——command 里的路径分隔符用
/,不要用\
对了,Hooks 目前还在快速迭代中。Anthropic 最近几周每周都在加新功能(Week 13 加了条件 if hooks,Week 14 加了 per-tool MCP result-size override)。建议关注官方的 What's New 页面,每周看一眼。
说个有意思的事:自从配了 Hooks,我的 .env 再没被 AI 动过。上个月 Claude Code 改挂生产环境的事情再也没发生过——不是 AI 变聪明了,是 Hooks 帮我挡住了。
如果你觉得有帮助,欢迎点赞收藏 ❤️ 更多AI工具实战教程,关注我第一时间获取~