首页 / ai-tutorial / Claude Code Hooks 实战:5 个钩子让 AI 编程效率翻倍 3 次阅读
Claude Code Hooks 实战:5 个钩子让 AI 编程效率翻倍 — AI 实战教程
AI 实战教程 中级

Claude Code Hooks 实战:5 个钩子让 AI 编程效率翻倍

⏱ 20 分钟 📋 6 个步骤 📅 2026-02-28

用 Claude Code 写代码,你有没有遇到这种情况:Claude 修改完文件忘记格式化、执行危险命令没有阻拦、等了半天不知道 AI 还在工作……这些问题都可以用 Hooks(钩子) 一次性解决。Hooks 是 Claude Code 最被低估的特性——它允许你在 AI 工作流的任意时间点插入自定义脚本,让 AI 的每个动作都符合你的开发规范。本文用 5 个真实场景,带你从零配置一套完整的 Hooks 自动化系统。

你将学到
  • Claude Code Hooks 的工作原理与 14 个事件类型
  • settings.json 配置格式(项目级 & 全局级)
  • 5 个即用型钩子脚本:自动格式化、危险命令拦截、运行测试、桌面通知、Git 自动存档
  • 使用 /hooks 命令管理钩子的完整流程
v1.0.59+
Claude Code 版本
jq
JSON 命令行工具
中级
难度要求
20 min
预计学时

核心概念:Hooks 是什么?

Hooks 是什么?14 个事件类型

把 Claude Code 的工作流想象成一条流水线。Hooks 就是这条流水线上的"检查站"——在特定时机自动触发你写好的脚本,接收当前操作的 JSON 上下文,并可以输出决策影响 Claude 的行为。

Hook 的生命周期

用户提问 → [UserPromptSubmit Hook] → Claude 思考
    → [PreToolUse Hook] → Claude 执行工具
    → [PostToolUse Hook] → Claude 完成动作
    → [Stop Hook] → 会话结束

14 个事件类型速查

事件触发时机典型用途
SessionStart会话开始时初始化环境、加载项目规则
UserPromptSubmit用户发送消息时注入上下文、记录提问
PreToolUse工具调用前(可阻止)危险命令拦截、权限检查
PermissionRequest弹出权限对话框时自动批准/拒绝特定操作
PostToolUse工具调用成功后自动格式化、运行测试
PostToolUseFailure工具调用失败后错误日志、自动重试
NotificationClaude 需要用户关注时桌面通知、手机推送
StopClaude 完成所有工作时Git 存档、生成报告
PreCompact上下文压缩前保存重要信息
SubagentStart/Stop子 Agent 启动/停止时多 Agent 协调

实战步骤

01

了解配置结构

Hooks 配置通过 settings.json 文件管理,有三个作用域:

# 全局钩子(对所有项目生效)
~/.claude/settings.json

# 项目钩子(仅当前项目生效)
.claude/settings.json

# 本地钩子(仅本人可见,不纳入 Git)
.claude/settings.local.json
配置结构与 JSON 格式

配置格式模板

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "your-script-here"
          }
        ]
      }
    ]
  }
}
💡 推荐做法:通用的钩子放全局配置(~/.claude/settings.json),项目特定的放 .claude/settings.json,敏感的放 .claude/settings.local.json 并加入 .gitignore
02

/hooks 命令管理钩子(推荐入口)

Claude Code 提供交互式的钩子管理命令,比直接编辑 JSON 更安全:

# 在 Claude Code 对话框中输入:
/hooks

操作流程:选择事件类型 → 选择"Add new hook" → 输入 matcher → 输入命令 → 保存。

验证配置是否生效

# 查看全局配置
cat ~/.claude/settings.json

# 期望看到 hooks 字段
{
  "hooks": {
    "PostToolUse": [...]
  }
}
03

钩子1 — 自动格式化代码(PostToolUse + Write)

场景:Claude 每次写完文件,自动运行格式化工具,告别手动 black .prettier

自动格式化 + 危险命令拦截

创建脚本文件

mkdir -p ~/.claude/hooks
cat > ~/.claude/hooks/auto-format.sh << 'EOF'
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

if [ -z "$FILE_PATH" ]; then
  exit 0
fi

case "$FILE_PATH" in
  *.py)
    python -m black "$FILE_PATH" 2>/dev/null && echo "✅ Python 格式化完成: $FILE_PATH"
    ;;
  *.ts|*.tsx|*.js|*.jsx)
    npx prettier --write "$FILE_PATH" 2>/dev/null && echo "✅ JS/TS 格式化完成: $FILE_PATH"
    ;;
  *.go)
    gofmt -w "$FILE_PATH" 2>/dev/null && echo "✅ Go 格式化完成: $FILE_PATH"
    ;;
esac
EOF
chmod +x ~/.claude/hooks/auto-format.sh

添加到配置~/.claude/settings.json):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [{"type": "command", "command": "~/.claude/hooks/auto-format.sh"}]
      },
      {
        "matcher": "Edit",
        "hooks": [{"type": "command", "command": "~/.claude/hooks/auto-format.sh"}]
      }
    ]
  }
}
04

钩子2 — 拦截危险命令(PreToolUse + Bash)

场景:防止 Claude 执行 rm -rfgit reset --hard 等高风险命令,在执行前提示确认。

cat > ~/.claude/hooks/block-dangerous.sh << 'EOF'
#!/usr/bin/env bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if [ -z "$COMMAND" ]; then
  exit 0
fi

DANGEROUS_PATTERNS=(
  "rm -rf /"
  "rm -rf ~"
  "rm -rf \."
  "git reset --hard"
  "git push --force"
)

for pattern in "${DANGEROUS_PATTERNS[@]}"; do
  if echo "$COMMAND" | grep -qF "$pattern"; then
    jq -n \
      --arg reason "⚠️ 危险命令被钩子拦截: $pattern" \
      '{
        hookSpecificOutput: {
          hookEventName: "PreToolUse",
          permissionDecision: "deny",
          permissionDecisionReason: $reason
        }
      }'
    exit 0
  fi
done

exit 0
EOF
chmod +x ~/.claude/hooks/block-dangerous.sh

添加到全局配置

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{"type": "command", "command": "~/.claude/hooks/block-dangerous.sh"}]
      }
    ]
  }
}
⚠️ 关键:PreToolUse Hook 输出 permissionDecision: "deny" 时,Claude 会收到拒绝原因并改变策略,不会强行执行。
05

钩子3 — 桌面通知(Notification Hook)

场景:Claude 需要你输入时,自动弹出系统通知(macOS/Linux 均支持)。

通知 + 测试 + Git 存档

macOS 通知脚本

cat > ~/.claude/hooks/notify-mac.sh << 'EOF'
#!/usr/bin/env bash
INPUT=$(cat)
MESSAGE=$(echo "$INPUT" | jq -r '.message // "Claude Code 需要你的关注"')

osascript -e "display notification \"$MESSAGE\" with title \"Claude Code\" sound name \"Ping\""
EOF
chmod +x ~/.claude/hooks/notify-mac.sh

添加到全局配置~/.claude/settings.json):

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [{"type": "command", "command": "~/.claude/hooks/notify-mac.sh"}]
      }
    ]
  }
}
06

钩子4 & 5 — 运行测试 + Git 自动存档

钩子4:写文件后自动运行测试

cat > ~/.claude/hooks/run-tests.sh << 'EOF'
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

if echo "$FILE_PATH" | grep -qE '\.(test|spec)\.(ts|js|py)$'; then
  echo "🧪 检测到测试文件变更,运行测试..."
  cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
  if [ -f "package.json" ]; then
    npm test --silent 2>&1 | tail -5
  elif [ -f "pyproject.toml" ] || [ -f "setup.py" ]; then
    python -m pytest --tb=short -q 2>&1 | tail -10
  fi
fi
EOF
chmod +x ~/.claude/hooks/run-tests.sh

钩子5:每次 Claude 完成工作自动 Git 存档

cat > ~/.claude/hooks/git-checkpoint.sh << 'EOF'
#!/usr/bin/env bash
cd "$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0

if ! git diff --quiet || ! git diff --staged --quiet || \
   [ -n "$(git ls-files --others --exclude-standard)" ]; then
  TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
  git add -A
  git commit -m "checkpoint: Claude Code 自动存档 [$TIMESTAMP]" --no-verify 2>/dev/null
  echo "📦 Git 存档完成: [$TIMESTAMP]"
fi
EOF
chmod +x ~/.claude/hooks/git-checkpoint.sh

在项目配置中启用.claude/settings.json):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [{"type": "command", "command": "~/.claude/hooks/run-tests.sh"}]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [{"type": "command", "command": "~/.claude/hooks/git-checkpoint.sh"}]
      }
    ]
  }
}

效果验证

配置完成后,在 Claude Code 中执行以下操作验证钩子工作:

# 1. 验证格式化钩子:让 Claude 写一个 Python 文件,观察是否自动运行 black
# 2. 验证拦截钩子:让 Claude 执行 "rm -rf /tmp/test",期望看到拒绝提示
# 3. 验证 Notification:长时间运行任务后,期望收到桌面通知

# 4. 验证 Stop 钩子:完成一次对话后查看 git log
git log --oneline -3
# 期望输出:
# abc1234 checkpoint: Claude Code 自动存档 [2026-02-28 20:30]
# def5678 上一次手动提交

常见问题

问题原因解决方案
钩子没有触发配置 JSON 格式错误运行 jq . ~/.claude/settings.json 验证语法
command not found: jqjq 未安装brew install jqapt install jq
脚本权限不足没有执行权限chmod +x ~/.claude/hooks/*.sh
PreToolUse 没有阻止命令JSON 输出格式错误确保输出完整的 hookSpecificOutput JSON 结构
格式化钩子报错格式化工具未安装安装对应工具(black/prettier/gofmt)

进阶技巧

1
钩子日志记录
将所有工具调用写入 ~/.claude/hook-log.txt,追踪 Claude 的完整操作历史
2
多钩子组合
同一事件挂载多个钩子,按顺序执行:格式化 → 测试 → 日志,互不干扰
3
Matcher 精确过滤
"matcher": "Write|Edit|MultiEdit" 正则匹配多个工具,减少不必要的触发
4
CI 环境检测
在钩子中检查 [ -z "$CI" ],在 CI 环境下跳过桌面通知等本地操作

完整日志钩子(通用,建议全局挂载):

cat > ~/.claude/hooks/logger.sh << 'EOF'
#!/usr/bin/env bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // "unknown"')
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$TIMESTAMP] $TOOL: $(echo "$INPUT" | jq -c '.tool_input' | cut -c1-200)" \
  >> ~/.claude/hook-log.txt
EOF
chmod +x ~/.claude/hooks/logger.sh

总结

  • 格式化钩子:每次 AI 写文件后自动运行 black / prettier / gofmt
  • 拦截钩子:危险命令在执行前被阻止,返回清晰的拒绝原因
  • 通知钩子:AI 等待输入时弹出系统通知,无需盯屏幕
  • 测试钩子:写测试文件后自动运行测试套件
  • Git 存档钩子:每次 AI 工作结束自动创建检查点提交

下一步探索:Claude Code Hooks 官方文档(code.claude.com/docs/en/hooks)、MCP 服务器开发、Claude Code 记忆系统实战。

选择栏目
今日简报 播客电台 AI 实战教程 关于我
栏目
全球AI日报国内AI日报全球金融日报国内金融日报全球大新闻日报国内大新闻日报Claude Code 玩法日报OpenClaw 动态日报GitHub 热门项目日报AI工具实战AI应用开发编程实战工作流自动化AI原理图解AI Agent开发
我的收藏
播客版
0:00
--:--