Claude Code系列第4篇 | 前置阅读:第1篇完全指南 → 第2篇官方插件 → 第3篇MCP连接器
你在用Claude Code写代码的时候,有没有遇到过这些”心惊肉跳”的时刻:
– Claude差点执行了 rm -rf
– 改完代码忘了格式化,提交一堆丑代码
– 长会话上下文被压缩,关键决策丢失
– Claude说”任务完成”,实则还差一截
以前只能靠”提醒”和”自觉”。
目前有Hooks了。
Hooks = 在Claude Code的关键节点,自动执行你定义的规则。
你可以把它理解成:
– 触发器:在特定时机自动执行
– 守护者:拦截危险操作,保护你的代码
– 自动化:格式化、lint、测试,全自动完成
一句话:把确定性规则交给Hooks,把创造性判断留给Claude,把最终责任留给你自己。
今天这篇文章,我把Hooks彻底讲透——从原理到配置,给你8个可以直接复制使用的实战案例。
━━━━━━━━━━━━━━━━
一、Hooks是什么?一张图看懂
Claude Code在运行过程中,会经历一系列”事件节点”:
用户输入 → [UserPromptSubmit] → Claude思考 → [PreToolUse] → 执行工具 → [PostToolUse] → 继续思考 → … → [Stop] → 等待用户
Hooks就是在这些节点上挂载的”钩子”——当Claude Code到达某个节点时,自动执行你预设的命令。
列如:
– PreToolUse:工具执行前拦截 → 可以阻止危险操作
– PostToolUse:工具执行后触发 → 可以自动格式化代码
– Stop:Claude完成时触发 → 可以检查是否真的完成了
– SessionStart:会话开始时触发 → 可以注入项目状态
━━━━━━━━━━━━━━━━
二、5种Hook类型
Claude Code支持5种Hook执行方式:
command — 执行Shell命令 — 拦截操作、格式化代码、运行测试
http — 发送HTTP请求 — 远程审批、团队共享规则
mcp_tool — 调用MCP工具 — 安全扫描、自定义校验
prompt — 让另一个AI判断 — 内容安全审核、质量检查
agent — 启动子代理处理 — 复杂验证、多步检查
90%的场景用 command 就够了。下面的实战案例全部用command类型。
━━━━━━━━━━━━━━━━
三、配置文件放哪?
.claude/settings.json — 当前项目 — 能提交git(团队共享)
.claude/settings.local.json — 当前项目 — 不能提交(个人用)
~/.claude/settings.json — 所有项目 — 不能提交(全局配置)
配置基本结构:
{
“hooks”: {
“事件名”: [
{
“matcher”: “匹配规则”,
“hooks”: [
{
“type”: “command”,
“command”: “要执行的命令”,
“timeout”: 30
}
]
}
]
}
}
matcher 用来筛选触发条件:
– “Write” — 只匹配Write工具
– “Write|Edit” — 匹配写入和编辑
– “*” — 匹配所有
– “Bash(rm *)” — 匹配包含rm的Bash命令
– “mcp__memory__.*” — 正则匹配MCP工具
━━━━━━━━━━━━━━━
四、核心原理:退出码决定一切
Hook脚本通过退出码告知Claude Code该怎么做:
退出码0 — 通过 — 正常继续
退出码2 — 阻止 — 拦截操作,Claude会看到你的拒绝理由
其他 — 错误 — 只显示警告,不阻止
⚠️ 注意:退出码1是非阻止错误!要真正阻止操作,必须用 exit 2。
也可以输出JSON来精细控制,列如:
{
“hookSpecificOutput”: {
“hookEventName”: “PreToolUse”,
“permissionDecision”: “deny”,
“permissionDecisionReason”: “危险命令已被拦截”
}
}
━━━━━━━━━━━━━━━━
五、8个实战配置(直接抄)
【实战1:阻止Claude修改敏感文件 】
场景:防止Claude意外修改 .env、密钥文件、生产配置
配置(.claude/settings.json):
{
“hooks”: {
“PreToolUse”: [
{
“matcher”: “Write|Edit”,
“hooks”: [
{
“type”: “command”,
“command”: “.claude/hooks/block-sensitive-files.sh”
}
]
}
]
}
}
脚本(
.claude/hooks/block-sensitive-files.sh):
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo “$INPUT” | jq -r '.tool_input.file_path // empty')
case “$FILE_PATH” in
*.env|*.env.*|*credentials*|*secrets*|*.pem|*.key|*production*)
echo “⚠️ 禁止修改敏感文件: $FILE_PATH” >&2
exit 2
;;
esac
exit 0
效果:Claude尝试修改 .env 等文件时,直接被拦截。
━━━━━━━━━━━━━━━━
【实战2:阻止危险rm命令 】
场景:防止 rm -rf 误删项目文件
配置:
{
“hooks”: {
“PreToolUse”: [
{
“matcher”: “Bash”,
“hooks”: [
{
“type”: “command”,
“if”: “Bash(rm *)”,
“command”: “.claude/hooks/block-rm.sh”
}
]
}
]
}
}
脚本(.claude/hooks/block-rm.sh):
#!/bin/bash
COMMAND=$(jq -r '.tool_input.command')
if echo “$COMMAND” | grep -q 'rm -rf'; then
jq -n '{
hookSpecificOutput: {
hookEventName: “PreToolUse”,
permissionDecision: “deny”,
permissionDecisionReason: “rm -rf 命令已被安全策略拦截”
}
}'
else
exit 0
fi
效果:rm -rf 被拦截,普通 rm 不受影响。
━━━━━━━━━━━━━━━━
【实战3:写文件后自动格式化 ✨】
场景:Claude每次修改文件,自动运行格式化工具
配置:
{
“hooks”: {
“PostToolUse”: [
{
“matcher”: “Write|Edit”,
“hooks”: [
{
“type”: “command”,
“command”: “.claude/hooks/format-touched-file.sh”,
“timeout”: 30
}
]
}
]
}
}
脚本(
.claude/hooks/format-touched-file.sh):
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo “$INPUT” | jq -r '.tool_input.file_path // empty')
if [ -z “$FILE_PATH” ] || [ ! -f “$FILE_PATH” ]; then
exit 0
fi
case “$FILE_PATH” in
*.js|*.jsx|*.ts|*.tsx|*.json|*.css|*.md)
npx prettier –write “$FILE_PATH”
;;
*.py)
python -m black “$FILE_PATH”
;;
*.go)
gofmt -w “$FILE_PATH”
;;
esac
exit 0
效果:Claude改完代码自动变整齐,不用手动格式化。
━━━━━━━━━━━━━━━━
【实战4:会话开始自动注入项目状态 】
场景:每次打开Claude Code,自动告知它当前分支、未提交改动、TODO
配置:
{
“hooks”: {
“SessionStart”: [
{
“hooks”: [
{
“type”: “command”,
“command”: “.claude/hooks/session-context.sh”
}
]
}
]
}
}
脚本(
.claude/hooks/session-context.sh):
#!/bin/bash
echo “## 当前仓库状态”
echo “分支: $(git branch –show-current 2>/dev/null)”
echo “未提交改动:”
git status –short 2>/dev/null
echo “”
if [ -f TODO.md ]; then
echo “## 项目TODO(前20行)”
sed -n '1,20p' TODO.md
fi
效果:Claude一启动就知道项目当前状态,不用你每次重复说明。
━━━━━━━━━━━━━━━━
【实战5:自动批准/拒绝权限请求 ⚡】
场景:npm test、git status 等安全命令自动批准,含 –force 的危险命令自动拒绝
配置:
{
“hooks”: {
“PermissionRequest”: [
{
“matcher”: “Bash(npm test*)”,
“hooks”: [
{
“type”: “command”,
“command”: “.claude/hooks/auto-permission.sh”
}
]
}
]
}
}
脚本(
.claude/hooks/auto-permission.sh):
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo “$INPUT” | jq -r '.tool_input.command // empty')
case “$COMMAND” in
“npm test”|”npm test “*|”git status”|”git diff”*)
echo '{“decision”:”approve”,”reason”:”安全命令,自动批准”}'
;;
*”–force”*|*”.env”*|*”DROP “*)
echo '{“decision”:”deny”,”reason”:”高危命令,自动拒绝”}'
;;
esac
效果:减少90%的权限弹窗,危险命令自动拦截。
━━━━━━━━━━━━━━━━
【实战6:任务完成前自检 】
场景:Claude说”做完了”,先用AI检查一下是否真的完成
配置:
{
“hooks”: {
“Stop”: [
{
“hooks”: [
{
“type”: “prompt”,
“prompt”: “检查用户的原始请求和已完成的工作。如果所有需求都满足,回复complete。如果还有遗漏,回复continue并列出缺失项。”
}
]
}
]
}
}
效果:减少Claude”过早宣布完成”的概率,确保每个任务真正做完。
━━━━━━━━━━━━━━━━
【实战7:上下文压缩前备份 】
场景:长会话中,上下文被压缩前自动保存关键信息
配置:
{
“hooks”: {
“PreCompact”: [
{
“hooks”: [
{
“type”: “command”,
“command”: “.claude/hooks/backup-before-compact.sh”
}
]
}
]
}
}
脚本(
.claude/hooks/backup-before-compact.sh):
#!/bin/bash
INPUT=$(cat)
TRANSCRIPT=$(echo “$INPUT” | jq -r '.transcript_path // empty')
BACKUP_DIR=”.claude/compact-backups”
mkdir -p “$BACKUP_DIR”
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
if [ -n “$TRANSCRIPT” ] && [ -f “$TRANSCRIPT” ]; then
cp “$TRANSCRIPT” “$BACKUP_DIR/transcript_${TIMESTAMP}.jsonl”
fi
echo “✅ 上下文备份完成: $BACKUP_DIR/transcript_${TIMESTAMP}.jsonl”
exit 0
效果:压缩前自动备份会话记录,关键决策不会丢失。
━━━━━━━━━━━━━━━━
【实战8:MCP工具操作审计 】
场景:记录所有MCP Memory操作,知道Claude”记住了什么”
配置:
{
“hooks”: {
“PreToolUse”: [
{
“matcher”: “mcp__memory__.*”,
“hooks”: [
{
“type”: “command”,
“command”: “echo “$(date +%Y-%m-%d_%H:%M:%S) – $(cat)” >> ~/.claude/mcp-memory-audit.log”
}
]
}
]
}
}
效果:所有MCP Memory的读写操作都被记录,随时可查。
━━━━━━━━━━━━━━━━
六、推荐落地顺序
别一口气全装,按这个顺序来:
第1步:PostToolUse 自动格式化 ← 最简单,效果最直观
第2步:SessionStart 注入项目状态 ← 开会话就有上下文
第3步:PreToolUse 阻止敏感文件 ← 安全底线
第4步:PermissionRequest 自动批准 ← 减少弹窗骚扰
第5步:Stop 任务自检 ← 质量保证
新手提议:先装实战3(自动格式化),感受一下Hook的威力,再逐步加其他。
━━━━━━━━━━━━━━━━
七、避坑指南
❌ 坑1:退出码用错了
exit 1 不是阻止!阻止必须用 exit 2。这是最多人犯的错。
❌ 坑2:UserPromptSubmit输出太长
这个Hook每轮都触发,如果注入大量文本,很快就会塞满上下文窗口。控制在20行以内。
❌ 坑3:matcher大小写写错
“bash” 匹配不到 “Bash”。工具名区分大小写!
❌ 坑4:脚本没有执行权限
Linux/Mac下记得 chmod +x .claude/hooks/*.sh,否则Hook不会执行。
✅ 调试技巧
Hook出错时看不清缘由?在JSON配置里加 statusMessage:
{
“type”: “command”,
“command”: “.claude/hooks/my-hook.sh”,
“statusMessage”: “正在执行安全检查…”
}
statusMessage 会在Hook运行时显示,方便排查问题。
━━━━━━━━━━━━━━━━
总结
禁改敏感文件 — PreToolUse — .env/密钥/生产配置,碰都不让碰
拦截rm -rf — PreToolUse — 危险命令,直接否决
自动格式化 — PostToolUse — 改完代码自动变整齐
注入项目状态 — SessionStart — 一启动就知道当前进度
自动审批权限 — PermissionRequest — 安全命令免弹窗,危险命令自动拒
任务完成自检 — Stop — 用AI检查是否真的做完了
上下文备份 — PreCompact — 压缩前保存关键信息
MCP操作审计 — PreToolUse — 记录Claude”记住了什么”
Hooks是Claude Code里最被低估的功能。
它让你从”靠提醒约束AI”升级到”靠系统约束AI”——这不仅是效率提升,更是工作方式质变。
装上Hooks之后,你会发现:Claude Code不再是一个”需要盯着的AI助手”,而是一个”有安全护栏的自动化系统”。
这就是Hooks的价值:把”人治”变成”法治”。
━━━━━━━━━━━━━━━━
系列导航:
第1篇:Claude Code完全指南——从安装到高效开发的全链路实操
第2篇:Claude Code官方插件详解:13个插件手把手教,装完效率翻倍
第3篇:Claude Code MCP连接器攻略:18个必装服务器,装完效率再翻倍
第4篇:Claude Code Hooks完全攻略:给AI装上”触发器+守护者”(本文)
有问题?评论区聊 关注我,持续分享Claude Code实战经验。
#ClaudeCode #AI编程 #Hooks #AI自动化 #程序员效率#头条创作挑战赛#