
有没有遇到过这种情况,让 Claude Code 做点事,它就是没做?
让它格式化代码,它没做。让它别碰那个文件,它偏碰了。
让它在结束前跑测试,它又忘了。
因为 CLAUDE.md 只是建议。
Claude 会读它,但大约只有 80% 的时候会照着做。Hook 不一样。它们是自动动作,每次 Claude 编辑文件、运行命令,或完成任务时都会触发。
下面分享 8 个自己常用的 hook,你可以直接复制进 settings.json,以后就不用再惦记了 👇
正式开始前,Telegram 频道每天分享 AI 和 vibe coding 的笔记:https://t.me/zodchixquant🧠

Hook 是怎么工作的(30 秒版)
什么是 hook?
Hook 是自动动作,Claude Code 每做一件事,比如编辑文件或运行命令,它就会执行。
设置一次,就会在后台持续工作,不用一直盯着。
最常用的两个:
PreToolUse 在 Claude 做事之前运行。你可以检查它要做的动作,并通过返回 exit code 2 把它拦下来。把它当作门口保安。
PostToolUse 在 Claude 做事之后运行。你可以做清理、格式化、跑测试或记录日志。把它当作流水线上的质检。
https://code.claude.com/docs/en/hooks
在项目根目录的 .claude/settings.json 里配置它们。这个文件会提交到 git,所以整个团队都会自动用上同一套 hook。
完整文档:https://code.claude.com/docs/en/hooks
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npm run test --silent 2>&1 | tail -5; exit 0"
}
]
}
]
}
}
1. 自动格式化 Claude 触碰过的每个文件
问题: Claude 写出的代码逻辑没问题,却破坏了你的格式化规则。你在 CLAUDE.md 里写了总是运行 Prettier,大多数时候有效,但不是每次都有效。
Hook: 每次写入或编辑文件后,自动运行 Prettier。
#!/usr/bin/env bash
set -euo pipefail
file=$(jq -r '.tool_input.file_path // .tool_input.path // ""')
protected=(
".env*"
".git/*"
"package-lock.json"
"yarn.lock"
"*.pem"
"*.key"
"secrets/*"
)
for pattern in "${protected[@]}"; do
if echo "$file" | grep -qiE "^${pattern//\*/.*}$"; then
echo "Blocked: '$file' is protected. Explain why this edit is necessary." >&2
exit 2
fi
done
exit 0
把 npx prettier --write 换成你用的格式化工具即可:Python 用 black,Go 用 gofmt,Rust 用 rustfmt。套路一样。
这是第一个配起来的 hook。说真的,每个项目都该默认有它。再也不会出现 Claude 忘了格式化 的提交。
2. 阻止危险命令
问题: Claude 的能力足够强,它可以去跑 rm -rf、git reset --hard、DROP TABLE,或者 curl 随便一个 URL。它可能不会这么干,但当这是你的生产数据库时,可能 这两个字不够。
Hook: 在执行之前拦住破坏性的命令。
创建 .claude/hooks/block-dangerous.sh:

然后把它加进 settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__github__create_pull_request",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/require-tests-for-pr.sh"
}
]
}
]
}
}
关键是 exit code 2。它会阻止动作,并把你的错误信息回传给 Claude,让它换个更安全的做法。exit code 0 表示继续。其他任何退出码只会记录警告,不会拦截。
3. 保护敏感文件不被改动
问题: Claude 可以读取并编辑项目里的任何文件。这包括 .env、package-lock.json、配置文件,以及你不希望它碰的其他东西。
Hook: 对不该碰的文件,一律禁止编辑。
创建 .claude/hooks/protect-files.sh:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/log-commands.sh"
}
]
}
]
}
}

4. 每次编辑后都跑测试
问题: Claude 改完说 done,你准备提交时才发现测试炸了,已经过去 20 分钟。
Hook: 每次代码改动后自动跑测试套件。只要失败,Claude 立刻能看到失败信息并马上修。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/protect-files.sh"
}
]
}
]
}
}
这里的 tail -5 把输出截短,避免淹没 Claude 的上下文。希望它看到的是 3 tests failed,而不是完整的 200 行测试输出。
Claude Code 的作者 Boris Cherny 说,给 Claude 这样的反馈回路,输出质量能提升 2-3 倍。它不再是写完就祈祷能跑,而是写完立刻看测试结果,失败就自己修。
5. 创建 PR 前必须测试全绿
问题: Claude 做完一个功能就立刻创建 PR。测试在失败。Reviewer 看到 CI 一片红,又给你打回来。
Hook: 没有全绿测试,不允许创建 PR。
创建 .claude/hooks/require-tests-for-pr.sh:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write 2>/dev/null; exit 0"
}
]
}
]
}
}
这是硬门槛。测试不绿,就没有 PR。Claude 会先把失败修好,因为 exit code 2 会告诉它动作被拦住了,以及拦住的原因。
6. 自动 lint 并回报错误
问题: Claude 写的代码能跑,但违反了你的 ESLint 规则、风格规范或类型检查。你在 review 才发现,只能打回去改。
Hook: 每次编辑后都跑 lint。只要 lint 失败,Claude 就能看到报错,并在你看到代码之前先修掉。
这可以和第 1 条的自动格式化串起来。先跑 Prettier,再跑 ESLint。你看到代码时,它已经格式正确、lint 也干净了。
7. 记录 Claude 跑过的每条命令
问题: 一次会话里 Claude 会跑很多 shell 命令。出了问题时,需要知道它在什么时候跑了什么。
Hook: 把每条 Bash 命令按时间戳追加写进日志文件。
创建 .claude/hooks/log-commands.sh:
#!/usr/bin/env bash
set -euo pipefail
git add -A
if ! git diff --cached --quiet; then
git commit -m "chore(ai): apply Claude edit"
fi
exit 0
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx eslint --fix $(jq -r '.tool_input.file_path') 2>&1 | tail -10; exit 0"
}
]
}
]
}
}
现在就有了一条带时间戳的审计轨迹,记录 Claude 跑过的每条命令。把 .claude/command-log.txt 加进你的 .gitignore,避免把日志文件提交进仓库。
这对排查问题尤其有用:如果 Claude 三次会话前把什么东西搞坏了,看日志就能找到它到底在什么时候跑了什么。
8. 每个任务结束后自动提交
问题: Claude 做完一个任务,你忘了 commit。它又开始下一个任务,两个不相关的改动就混进了同一个提交。
Hook: Claude 停止处理一个任务时,自动提交所有改动。
创建 .claude/hooks/auto-commit.sh:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": ".claude/hooks/block-dangerous.sh" },
{ "type": "command", "command": ".claude/hooks/log-commands.sh" }
]
},
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": ".claude/hooks/protect-files.sh" }
]
},
{
"matcher": "mcp__github__create_pull_request",
"hooks": [
{ "type": "command", "command": ".claude/hooks/require-tests-for-pr.sh" }
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write 2>/dev/null; exit 0" },
{ "type": "command", "command": "npx eslint --fix $(jq -r '.tool_input.file_path') 2>&1 | tail -10; exit 0" }
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{ "type": "command", "command": ".claude/hooks/auto-commit.sh" }
]
}
]
}
}
每次 Claude 结束一次回复,改动都会自动提交。你的 git 历史会保持干净,每个任务一个原子提交,而不是一天结束时一坨 Claude changes 大杂烩。
再配合 claude -w feature-branch(worktrees),就能为每个任务拿到隔离的、自动提交的 feature 分支。
完整的 settings.json
下面是把所有内容合并后的一个文件,你可以直接复制粘贴:
方便截图:

把这个文件复制到 .claude/settings.json,在 .claude/hooks/ 里创建这些 hook 脚本,用 chmod +x .claude/hooks/*.sh 让它们可执行,然后把所有东西提交到 git。整个团队都会自动拥有同样的安全网。
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/auto-commit.sh"
}
]
}
]
}
}
一套不错的 Claude Code 配置和一套很强的配置,差别不在模型,也不在提示词,而在 hooks。
它们会在你不注意的时候执行,把那些你本来要到 code review 才发现的错误,甚至更糟糕,到生产环境才发现的错误,提前兜住。
今天先把第 1 条(自动格式化)和第 2 条(阻止危险命令)配上。这两条就能挡住最常见的 Claude Code 失误。剩下的按需加就行。
Telegram 频道每天分享 AI、金融和 vibe coding 的笔记:https://t.me/zodchixquant
感谢阅读 🙏🏼
```markdown Where hooks live:
.claude/settings.json project-level (shared via git) ~/.claude/settings.json user-level (all your projects) .claude/settings.local.json local only (not committed)