Claude Code Hooks 完全指南——自动化你的开发工作流
Claude Code Hooks 完全指南——自动化你的开发工作流 Claude Code Hooks 是 Claude Code 提供的生命周期脚本机制 ,允许你在特定时机自动执行自定义脚本。通过 Hooks,你可以实现代码保存时自动格式化、运行前自动检查、任务完成后自动通知等场景,将重复性工作完全自动化。
目录
什么是 Hooks?
Hooks 的类型与触发时机
环境配置与前置要求
创建你的第一个 Hook
Hook 脚本编写指南
实战案例
调试与排查
安全注意事项
常见问题
一、什么是 Hooks? Hooks 是 Claude Code 的生命周期回调系统 。你可以为特定事件(如文件保存前、任务完成后)注册自定义脚本,Claude Code 会在对应时机自动调用这些脚本。
Hooks vs Skills vs Commands
概念
触发方式
用途
Hooks
自动触发(事件驱动)
自动化流程、格式化、检查
Skills
自动匹配(自然语言触发)
教会 Claude 怎么做某事
Commands
手动调用(斜杠命令)
用户主动执行的流程
Agents
手动调用(@引用)
专用子代理完成子任务
工作流程示意 1 2 3 4 5 6 用户编辑代码 → 文件保存 → [before_write Hook 触发] ↓ 自动格式化/检查 文件写入磁盘 → [after_write Hook 触发] ↓ 自动编译/lint 任务完成 → [after_task Hook 触发] ↓ 自动总结/通知
二、Hooks 的类型与触发时机 Claude Code 支持以下 7 种 Hook 类型:
Hook 名称
触发时机
典型用途
before_read
读取文件之前
文件解密、权限验证
after_read
读取文件之后
内容过滤、日志记录
before_write
写入文件之前(可修改内容)
格式化代码、注入版权头
after_write
写入文件之后
运行 linter、编译检查
before_command
执行 shell 命令之前
安全检查、环境验证
after_command
执行 shell 命令之后
结果分析、日志记录
after_task
整个任务完成之后
生成报告、发送通知
重要:Hook 的执行顺序 1 2 3 任务开始 → before_read → after_read → ... → before_write → 写入 → after_write → ... → before_command → 执行命令 → after_command → ... → after_task → 任务完成
三、环境配置与前置要求 系统要求
Claude Code CLI 已安装(npm install -g @anthropic-ai/claude-code)
Node.js 18+(部分 Hook 需要)
Bash/Zsh shell 环境
配置位置 Hooks 配置在 Claude Code 的 settings.local.json 文件中:
项目级 :<项目根目录>/.claude/settings.local.json
全局级 :~/.claude/settings.local.json
⚠️ 优先级 :项目级配置覆盖全局级配置。settings.local.json 不会被提交到 Git(已添加到 .gitignore),适合存放个人配置。
配置文件结构 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 { "hooks" : { "before_write" : { "command" : "node scripts/pre-format.js" , "timeout" : 5000 , "blocking" : true , "files" : ["*.ts" , "*.tsx" , "*.js" , "*.jsx" ] }, "after_write" : { "command" : "./scripts/lint-check.sh" , "timeout" : 10000 , "blocking" : false }, "before_command" : { "command" : "bash scripts/command-guard.sh" , "timeout" : 3000 , "blocking" : true , "exclude_commands" : ["git*" , "npm*" , "pnpm*" ] }, "after_task" : { "command" : "node scripts/task-summary.js" , "timeout" : 15000 , "blocking" : false } } }
配置字段说明
字段
类型
默认值
说明
command
string
必填
要执行的命令或脚本路径
timeout
number
10000
超时时间(毫秒),超过此时间 Hook 会被终止
blocking
boolean
true
是否阻塞主流程(false 表示异步执行,不等待结果)
files
string[]
全部
文件匹配模式(仅对 before_write/after_write 有效)
exclude_commands
string[]
无
排除的命令匹配模式(仅对 before_command 有效)
四、创建你的第一个 Hook 步骤 1:创建配置目录
步骤 2:编写 Hook 脚本 创建一个通用的格式化 Hook 脚本:
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 cat > .claude/hooks/format-code.sh << 'SCRIPT' FILE_PATH="$1 " FILE_EXT="${FILE_PATH##*.} " case "$FILE_EXT " in js|jsx|ts|tsx) npx prettier --write "$FILE_PATH " 2>/dev/null || true ;; py) python -m black --quiet "$FILE_PATH " 2>/dev/null || true ;; go) gofmt -w "$FILE_PATH " 2>/dev/null || true ;; rs) rustfmt "$FILE_PATH " 2>/dev/null || true ;; esac echo "[Hook] 已格式化: $FILE_PATH " SCRIPT chmod +x .claude/hooks/format-code.sh
步骤 3:注册 Hook 创建或编辑 .claude/settings.local.json:
1 2 3 4 5 6 7 8 9 10 { "hooks" : { "before_write" : { "command" : "bash .claude/hooks/format-code.sh \"$CLAUDE_HOOK_FILE\"" , "timeout" : 5000 , "blocking" : true , "files" : ["*.js" , "*.ts" , "*.tsx" , "*.py" , "*.go" , "*.rs" ] } } }
步骤 4:验证 Hook 生效 在 Claude Code 中让 Claude 修改一个代码文件:
五、Hook 脚本编写指南 环境变量 Hook 脚本可以访问以下环境变量:
变量名
说明
适用 Hook
CLAUDE_HOOK_FILE
当前操作的文件路径
before_write, after_write, before_read, after_read
CLAUDE_HOOK_TYPE
Hook 类型名称
全部
CLAUDE_HOOK_COMMAND
即将执行的命令
before_command, after_command
CLAUDE_PROJECT_ROOT
项目根目录路径
全部
脚本签名规范 1 2 3 4 5 6 7 8 9 10 11 12 #!/bin/bash set -euo pipefail echo "[Hook:$CLAUDE_HOOK_TYPE ] 开始处理 $CLAUDE_HOOK_FILE " echo "[Hook:$CLAUDE_HOOK_TYPE ] 处理完成"
返回值约定
退出码 0 :Hook 执行成功,主流程继续
退出码非 0 (仅在 blocking=true 时):Hook 执行失败,主流程停止 并报错
1 2 3 4 5 6 7 if ! npx eslint "$CLAUDE_HOOK_FILE " ; then echo "[Hook] ESLint 检查失败,阻止写入" exit 1 fi
超时处理 为所有 Hook 设置合理的超时时间:
Hook 类型
建议超时
原因
before_write
3-10 秒
格式化应该很快
after_write
5-15 秒
Lint/编译可能需要更多时间
before_command
3-5 秒
安全检查应迅速
after_task
10-30 秒
报告生成可能稍慢
六、实战案例 案例 1:Python 项目自动格式化 + 类型检查 .claude/hooks/python-check.sh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #!/bin/bash set -euo pipefailFILE="$CLAUDE_HOOK_FILE " if [[ ! "$FILE " =~ \.py$ ]]; then exit 0 fi echo "[Hook] Python 格式化检查: $FILE " black --quiet "$FILE " isort --quiet "$FILE " mypy "$FILE " --show-error-codes 2>&1 | head -5 || true echo "[Hook] Python 文件处理完成"
注册配置:
1 2 3 4 5 6 7 8 9 10 { "hooks" : { "before_write" : { "command" : "bash .claude/hooks/python-check.sh" , "timeout" : 10000 , "blocking" : true , "files" : ["*.py" ] } } }
案例 2:安全命令守卫 .claude/hooks/command-guard.sh:
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 #!/bin/bash set -euo pipefailCOMMAND="$CLAUDE_HOOK_COMMAND " DANGEROUS_COMMANDS=( "rm -rf /" "sudo rm" "dd if=/dev/zero" "chmod -R 777" ">.*/dev/" "DROP DATABASE" "TRUNCATE TABLE" "git push --force" ) echo "[安全卫士] 检查命令: ${COMMAND:0:100} ..." for pattern in "${DANGEROUS_COMMANDS[@]} " ; do if echo "$COMMAND " | grep -iqE "$pattern " ; then echo "[安全卫士] ⚠️ 检测到危险命令: $pattern " echo "[安全卫士] 操作已阻止!如需执行,请在 Claude Code 中手动确认。" exit 1 fi done echo "[安全卫士] 命令安全检查通过 ✓"
案例 3:任务完成自动生成摘要 .claude/hooks/task-summary.sh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #!/bin/bash set -euo pipefailSUMMARY_FILE="$CLAUDE_PROJECT_ROOT /.claude/task-summary.md" TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S" ) { echo "## 任务完成报告 — $TIMESTAMP " echo "" echo "**项目**: $CLAUDE_PROJECT_ROOT " echo "**Hook 类型**: $CLAUDE_HOOK_TYPE " echo "" echo "### 修改的文件" git diff --name-only 2>/dev/null || echo "(未检测到 Git 仓库)" echo "" echo "---" echo "" } >> "$SUMMARY_FILE " echo "[Hook] 任务摘要已追加到 $SUMMARY_FILE "
案例 4:TypeScript/React 项目全流程自动化 完整的 .claude/settings.local.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 { "hooks" : { "before_write" : { "command" : "bash .claude/hooks/pre-write.sh" , "timeout" : 8000 , "blocking" : true , "files" : ["*.ts" , "*.tsx" , "*.js" , "*.jsx" , "*.css" , "*.json" ] }, "after_write" : { "command" : "bash .claude/hooks/post-write.sh" , "timeout" : 15000 , "blocking" : false , "files" : ["*.ts" , "*.tsx" ] }, "before_command" : { "command" : "bash .claude/hooks/command-guard.sh" , "timeout" : 3000 , "blocking" : true , "exclude_commands" : ["npm*" , "pnpm*" , "yarn*" , "git status*" , "ls*" , "cat*" ] }, "after_task" : { "command" : "bash .claude/hooks/task-summary.sh" , "timeout" : 5000 , "blocking" : false } } }
七、调试与排查 检查 Hook 是否生效 1 2 3 4 5 claude config list cat .claude/settings.local.json
查看 Hook 执行日志 Claude Code 会在终端输出 Hook 的执行信息。如果 Hook 出错,你会看到类似:
1 2 [Hook] before_write: ❌ 退出码 1 [Hook] 错误: ESLint 检查失败
常用调试技巧
先跑脚本本身 :在终端直接运行 Hook 脚本,确保它独立工作正常
1 2 CLAUDE_HOOK_FILE="src/app.ts" bash .claude/hooks/format-code.sh
逐步减少复杂性 :先用一个简单的 echo "Hello" 脚本确认 Hook 机制工作,再替换为真实逻辑
检查路径 :Hook 脚本的工作目录是项目根目录 ,不是脚本所在目录。使用绝对路径或 $CLAUDE_PROJECT_ROOT
日志重定向 :将日志写入文件而非仅输出到终端
1 2 3 exec >> "$CLAUDE_PROJECT_ROOT /.claude/hooks.log" 2>&1echo "[$(date) ] Hook 开始: $CLAUDE_HOOK_TYPE "
常见错误与解决方案
错误现象
可能原因
解决方案
Hook 不执行
配置文件语法错误
检查 JSON 格式,用 jsonlint 验证
Hook 超时
脚本执行时间过长
增大 timeout 值或优化脚本
文件写入被阻止
blocking=true 的 Hook 返回非 0
检查 Hook 脚本逻辑
环境变量为空
使用方式不正确
使用 $CLAUDE_HOOK_FILE 而非参数传递
脚本路径错误
相对路径问题
使用脚本所在目录的完整路径
八、安全注意事项 正确做法
✅ 使用 files 字段限制 Hook 只作用于特定文件类型
✅ 使用 exclude_commands 跳过已知安全的命令
✅ 在开发和测试阶段使用 blocking: false
✅ 为脚本设置合理的 timeout 值
✅ 定期审查 Hook 脚本的内容
错误做法
❌ 在 Hook 中执行 rm -rf 等破坏性操作
❌ Hook 脚本读取敏感信息(密码、密钥)
❌ 设置过长(> 60 秒)的 blocking 超时
❌ 跳过错误处理(不使用 set -e)
❌ 在生产环境中调试未测试的 Hook
九、常见问题 Q1:Hook 脚本可以访问网络吗? 可以。Hook 脚本可以执行任何 shell 命令,包括网络请求。但建议将网络操作放在 blocking: false 的 Hook 中,避免阻塞主流程。
Q2:多个 Hook 可以同时注册吗? 是的。可以为同一个事件注册多个 Hook,但每个事件只能有一个 command 配置。如果需要执行多个操作,请在脚本内部串联:
1 2 3 4 5 #!/bin/bash npm run format npm run lint npm run test :quick
Q3:如何在不同项目间共享 Hook? 你可以将 Hook 脚本放在 Git 仓库中共享,或者创建一个模板项目:
1 2 3 4 5 6 mkdir -p ~/.claude-templates/hooks/ cp my-hooks/* ~/.claude-templates/hooks/ ln -s ~/.claude-templates/hooks/ .claude/hooks/
Q4:before_write Hook 修改了文件内容会怎样? Claude Code 会将你修改后的内容写入磁盘。这意味着 Hook 可以修改即将写入的内容 ——这是格式化和代码注入的基础机制。
Q5:生产环境 vs 开发环境需要不同的 Hook 配置? 推荐使用 Git 分支或环境变量区分:
1 2 3 4 5 6 7 8 9 10 { "hooks" : { "before_write" : { "command" : "bash .claude/hooks/pre-write.sh --env ${NODE_ENV:-development}" , "timeout" : 10000 , "blocking" : true , "files" : ["*.ts" , "*.tsx" ] } } }
然后在脚本内根据 $NODE_ENV 执行不同的逻辑。
Q6:Hook 执行失败会影响我正在编辑的代码吗?
blocking: true :如果 Hook 返回非 0 退出码,会阻止操作进行 (如阻止文件写入)。你的代码不会被修改。
blocking: false :Hook 异步执行,即使失败也不影响主流程。
总结 :Hooks 是 Claude Code 中极具威力的自动化工具。通过合理配置 before_write 实现格式化自动化、before_command 提供安全防护、after_task 生成报告总结,你可以大幅减少重复性工作,将精力集中在真正需要创造力的编码任务上。