Claude Code Hooks 教程:自动化你的 AI 编程工作流
学习如何使用 Claude Code hooks 自动化任务、强制编码规范并创建强大的自定义工作流。完整教程包含 PreToolUse、PostToolUse 和 Notification hooks 的实用示例。
ClaudeCode.Guide Team
hooks自动化教程工作流高级
Claude Code Hooks 教程:自动化你的 AI 编程工作流
Hooks 是 Claude Code 中最强大的功能之一,允许你自动化任务、强制编码规范并创建自定义工作流。本教程从基础设置到高级用例,全面覆盖 hooks 的使用方法。
什么是 Claude Code Hooks?
Hooks 是在 Claude Code 操作过程中特定时刻自动执行的 shell 命令。它们能让你:
- 自动化重复任务 - 自动运行格式化器、代码检查器或测试
- 强制项目规范 - 阻止某些操作或要求特定模式
- 扩展功能 - 与外部工具和服务集成
- 创建护栏 - 在破坏性操作前添加安全检查
Hooks 类型概览
Claude Code 支持四种类型的 hooks:
| Hook 类型 | 运行时机 | 用途 |
|---|---|---|
PreToolUse | 工具执行前 | 验证、审批、阻止 |
PostToolUse | 工具完成后 | 格式化、通知、日志 |
Notification | Claude 发送通知时 | 提醒、集成、日志 |
Stop | Claude 完成任务时 | 清理、验证、报告 |
设置 Hooks
Hooks 在 .claude/settings.json 文件中配置:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"command": "echo '即将编辑: $CLAUDE_FILE_PATH'"
}
],
"PostToolUse": [
{
"matcher": "Edit",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
]
}
}
配置位置
Hooks 可以在以下位置定义:
- 项目级别:项目根目录的
.claude/settings.json - 用户级别:
~/.claude/settings.json用于全局 hooks - CLAUDE.md:内联 hook 定义(功能有限)
PreToolUse Hooks
PreToolUse hooks 在 Claude 执行工具之前运行。它们可以:
- 记录即将发生的操作
- 通过返回非零退出码阻止操作
- 根据条件修改行为
基础示例:记录所有编辑
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"command": "echo \"[$(date)] 编辑: $CLAUDE_FILE_PATH\" >> ~/.claude/edit.log"
}
]
}
}
阻止危险操作
防止编辑关键文件:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"command": "if [[ \"$CLAUDE_FILE_PATH\" == *\".env\"* ]]; then echo '不能编辑 .env 文件!' && exit 1; fi"
}
]
}
}
对破坏性命令要求确认
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "if [[ \"$CLAUDE_COMMAND\" == *\"rm -rf\"* ]]; then echo '已阻止: 不允许 rm -rf' && exit 1; fi"
}
]
}
}
模式匹配
matcher 字段支持:
- 精确匹配:
"Edit"、"Bash"、"Write" - 通配符:
"*"匹配所有工具 - 正则表达式:
"/Edit|Write/"匹配 Edit 或 Write
PostToolUse Hooks
PostToolUse hooks 在工具成功完成后运行。适用于:
- 自动格式化代码
- 运行代码检查器
- 更新文档
- 发送通知
编辑后自动格式化
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
},
{
"matcher": "Write",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
}
]
}
}
JavaScript 更改后运行 ESLint
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "if [[ \"$CLAUDE_FILE_PATH\" == *.js ]] || [[ \"$CLAUDE_FILE_PATH\" == *.ts ]]; then npx eslint --fix \"$CLAUDE_FILE_PATH\"; fi"
}
]
}
}
自动运行测试
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "if [[ \"$CLAUDE_FILE_PATH\" == *\"test\"* ]]; then npm test -- --findRelatedTests \"$CLAUDE_FILE_PATH\"; fi"
}
]
}
}
Notification Hooks
Notification hooks 在 Claude 发送通知(任务完成、错误等)时触发。
桌面通知(macOS)
{
"hooks": {
"Notification": [
{
"matcher": "*",
"command": "osascript -e 'display notification \"$CLAUDE_MESSAGE\" with title \"Claude Code\"'"
}
]
}
}
桌面通知(Linux)
{
"hooks": {
"Notification": [
{
"matcher": "*",
"command": "notify-send 'Claude Code' \"$CLAUDE_MESSAGE\""
}
]
}
}
Slack 集成
{
"hooks": {
"Notification": [
{
"matcher": "*",
"command": "curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"Claude Code: '$CLAUDE_MESSAGE'\"}' $SLACK_WEBHOOK_URL"
}
]
}
}
微信/钉钉集成
{
"hooks": {
"Notification": [
{
"matcher": "*",
"command": "curl -X POST -H 'Content-type: application/json' --data '{\"msgtype\":\"text\",\"text\":{\"content\":\"Claude Code: '$CLAUDE_MESSAGE'\"}}' $DINGTALK_WEBHOOK_URL"
}
]
}
}
Stop Hooks
Stop hooks 在 Claude 完成任务或对话轮次时运行。
生成摘要报告
{
"hooks": {
"Stop": [
{
"matcher": "*",
"command": "echo \"任务完成于 $(date)\" >> ~/.claude/completed.log"
}
]
}
}
完成时自动提交
{
"hooks": {
"Stop": [
{
"matcher": "*",
"command": "if [ -n \"$(git status --porcelain)\" ]; then git add -A && git commit -m '自动提交: Claude Code 更改'; fi"
}
]
}
}
环境变量
Hooks 可以访问以下环境变量:
| 变量 | 说明 | 可用于 |
|---|---|---|
CLAUDE_FILE_PATH | 正在编辑的文件路径 | Edit, Write, Read |
CLAUDE_TOOL_NAME | 当前工具名称 | 所有 hooks |
CLAUDE_COMMAND | 正在运行的 Bash 命令 | Bash 工具 |
CLAUDE_MESSAGE | 通知消息 | Notification hooks |
CLAUDE_SESSION_ID | 当前会话 ID | 所有 hooks |
CLAUDE_WORKING_DIR | 当前工作目录 | 所有 hooks |
高级 Hook 模式
基于文件类型的条件 Hooks
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "case \"$CLAUDE_FILE_PATH\" in *.py) black \"$CLAUDE_FILE_PATH\";; *.js|*.ts) npx prettier --write \"$CLAUDE_FILE_PATH\";; *.go) gofmt -w \"$CLAUDE_FILE_PATH\";; esac"
}
]
}
}
链接多个操作
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\" && npx eslint --fix \"$CLAUDE_FILE_PATH\" && echo '已格式化和检查!'"
}
]
}
}
使用外部脚本
创建 hook 脚本 ~/.claude/hooks/post-edit.sh:
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
# 根据扩展名格式化
case "${FILE##*.}" in
py)
black "$FILE"
isort "$FILE"
;;
js|ts|jsx|tsx)
npx prettier --write "$FILE"
npx eslint --fix "$FILE"
;;
go)
gofmt -w "$FILE"
;;
esac
# 记录编辑
echo "[$(date)] 已编辑: $FILE" >> ~/.claude/edits.log
在设置中引用它:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "~/.claude/hooks/post-edit.sh"
}
]
}
}
项目特定 Hooks
在项目的 .claude/settings.json 中:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "if [[ \"$CLAUDE_COMMAND\" == *\"npm publish\"* ]]; then echo '请先运行测试!' && npm test || exit 1; fi"
}
],
"PostToolUse": [
{
"matcher": "Edit",
"command": "npm run lint:fix -- \"$CLAUDE_FILE_PATH\""
}
],
"Stop": [
{
"matcher": "*",
"command": "npm run typecheck"
}
]
}
}
调试 Hooks
启用详细日志
{
"hooks": {
"PreToolUse": [
{
"matcher": "*",
"command": "echo \"[DEBUG] 工具: $CLAUDE_TOOL_NAME, 文件: $CLAUDE_FILE_PATH\" >> /tmp/claude-hooks.log"
}
]
}
}
手动测试 Hooks
# 模拟环境变量
export CLAUDE_FILE_PATH="/path/to/test.js"
export CLAUDE_TOOL_NAME="Edit"
# 运行你的 hook 命令
npx prettier --write "$CLAUDE_FILE_PATH"
常用 Hook 配方
1. 强制分支保护
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "BRANCH=$(git branch --show-current); if [[ \"$BRANCH\" == \"main\" || \"$BRANCH\" == \"master\" ]]; then echo '不能在受保护的分支上运行命令!' && exit 1; fi"
}
]
}
}
2. 自动更新测试
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "TEST_FILE=$(echo \"$CLAUDE_FILE_PATH\" | sed 's/\\.ts$/.test.ts/'); if [ -f \"$TEST_FILE\" ]; then echo \"记得更新: $TEST_FILE\"; fi"
}
]
}
}
3. 安全扫描
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "if grep -q 'password\\|secret\\|api_key' \"$CLAUDE_FILE_PATH\"; then echo '警告: 检测到可能的敏感数据!'; fi"
}
]
}
}
4. 文档提醒
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"command": "if [[ \"$CLAUDE_FILE_PATH\" == *\"/src/\"* ]]; then echo '如果这是公共 API,请记得更新文档!'; fi"
}
]
}
}
最佳实践
- 保持 hooks 快速 - 慢的 hooks 会拖慢整个工作流程
- 优雅处理错误 - 对非关键 hooks 使用
|| true - 正确使用退出码 - 在 PreToolUse 中返回非零值来阻止操作
- 记录重要事件 - 为团队项目创建审计跟踪
- 充分测试 hooks - 错误的 hooks 可能破坏你的工作流程
- 文档化项目 hooks - 帮助团队成员理解自定义行为
故障排除
Hook 未运行
- 检查
matcher模式是否与工具名称完全匹配 - 验证命令语法是否正确
- 检查外部脚本的文件权限
- 查找 settings.json 中的拼写错误
Hook 阻止所有操作
- 检查 PreToolUse 的退出码
- 验证条件逻辑是否正确
- 手动测试命令
性能问题
- 将重型操作移到 PostToolUse 或 Stop hooks
- 尽可能使用异步操作
- 考虑使用后台进程:
command &
相关资源
- Claude Code 命令参考 - 所有 CLI 命令
- CLAUDE.md 指南 - 项目配置
- 最佳实践指南 - 工作流优化
最后更新:2025 年 1 月