Skip to content

Hooks:自动化工作流

Hooks 是用户定义的 shell 命令,在 Claude Code 生命周期的特定节点自动执行。与 CLAUDE.md 指令不同,Hooks 是确定性的——它们保证某些动作一定会发生,而不是依赖 AI 决定要不要执行。

常见用途:

  • 每次文件编辑后自动格式化代码
  • Claude 需要你操作时发送桌面通知
  • 阻止 Claude 修改受保护的文件
  • 压缩上下文后重新注入关键信息

创建第一个 Hook

以桌面通知 Hook 为例:Claude 等待你输入时,你可以切换到其他任务,完成后收到通知。

第一步:添加 Hook 到设置

打开 ~/.claude/settings.json,添加 Notification hook:

macOS:

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

Linux:

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Claude Code needs your attention'"
          }
        ]
      }
    ]
  }
}

Windows(PowerShell):

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
          }
        ]
      }
    ]
  }
}

第二步:验证配置

在 Claude Code 中运行 /hooks,确认 Notification 事件下有你的 Hook。

常见 Hook 配方

编辑后自动格式化

每次 Claude 编辑文件后自动运行 Prettier:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

阻止修改受保护文件

防止 Claude 修改 .envpackage-lock.json 等敏感文件:

第一步:创建校验脚本 .claude/hooks/protect-files.sh

bash
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH 匹配受保护模式 '$pattern'" >&2
    exit 2
  fi
done

exit 0

第二步:赋予执行权限(macOS/Linux):

bash
chmod +x .claude/hooks/protect-files.sh

第三步:注册 Hook:

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

压缩后重新注入上下文

上下文压缩后,重新提醒 Claude 关键规则:

json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo '提醒:使用 Bun 而不是 npm。提交前运行 bun test。当前 sprint:auth 重构。'"
          }
        ]
      }
    ]
  }
}

自动批准计划结束

不想每次计划结束都手动确认?用 PermissionRequest hook 自动批准:

json
{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "ExitPlanMode",
        "hooks": [
          {
            "type": "command",
            "command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
          }
        ]
      }
    ]
  }
}

Hook 生命周期事件

事件触发时机常见用途
SessionStart会话开始或恢复注入上下文、恢复环境
UserPromptSubmit提交提示词、Claude 处理前预处理、添加上下文
PreToolUse工具调用执行前(可阻止)验证、阻止危险操作
PostToolUse工具调用成功后格式化、日志、通知
PermissionRequest权限弹窗出现时自动批准安全操作
NotificationClaude 等待输入时桌面通知
StopClaude 完成响应时验证任务是否完成
SessionEnd会话结束时清理临时文件

Hook 如何工作

输入:Hook 从 stdin 接收 JSON 格式的事件数据:

json
{
  "session_id": "abc123",
  "cwd": "/Users/sarah/myproject",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}

输出:通过退出码和 stdout/stderr 告诉 Claude Code 该做什么:

退出码行为
0操作继续。UserPromptSubmitSessionStart 中 stdout 内容被添加到上下文
2阻止操作。stderr 内容作为反馈发送给 Claude
其他非零操作继续,stderr 记录到日志(按 Ctrl+O 查看)

阻止操作示例:

bash
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')

if echo "$COMMAND" | grep -q "drop table"; then
  echo "Blocked: 不允许执行删表操作" >&2
  exit 2
fi

exit 0

用 matcher 过滤 Hook

不加 matcher 时,Hook 在每次事件触发。用 matcher 缩小范围:

json
{
  "PostToolUse": [
    {
      "matcher": "Edit|Write",    // 只在编辑/写入后触发
      "hooks": [...]
    }
  ]
}

不同事件的 matcher 过滤字段:

事件matcher 过滤字段
PreToolUse, PostToolUse工具名称
SessionStart会话来源(startup/resume/clear/compact)
Notification通知类型(permission_prompt/idle_prompt/auth_success)
ConfigChange配置来源

MCP 工具用 mcp__服务器名__工具名 格式,如 mcp__github__.* 匹配所有 GitHub MCP 工具。

Hook 配置位置

位置作用域是否可共享
~/.claude/settings.json所有项目否(本地)
.claude/settings.json单个项目是(可提交 git)
.claude/settings.local.json单个项目否(gitignore)

高级 Hook 类型

Prompt-based Hooks

需要判断而非固定规则时,用 type: "prompt" 让 Claude 模型(默认 Haiku)来做决定:

json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "检查是否所有任务都已完成。如果没有,返回 {\"ok\": false, \"reason\": \"还需要做什么\"}。"
          }
        ]
      }
    ]
  }
}

返回 {"ok": false} 时,Claude 会根据 reason 继续工作。

Agent-based Hooks

需要读文件或运行命令来验证时,用 type: "agent" 创建能使用工具的验证代理:

json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "验证所有单元测试通过。运行测试套件并检查结果。",
            "timeout": 120
          }
        ]
      }
    ]
  }
}

HTTP Hooks

把事件数据 POST 到 HTTP 端点:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "http",
            "url": "http://localhost:8080/hooks/tool-use",
            "headers": {
              "Authorization": "Bearer $MY_TOKEN"
            },
            "allowedEnvVars": ["MY_TOKEN"]
          }
        ]
      }
    ]
  }
}

常见问题

Hook 不触发

  • 运行 /hooks 确认 Hook 出现在正确事件下
  • 检查 matcher 是否和工具名完全匹配(区分大小写)
  • PermissionRequest 在非交互模式(-p)不触发,改用 PreToolUse

Hook 报错

  • 手动测试脚本:echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh
  • 脚本未执行:检查是否有执行权限(chmod +x
  • 找不到命令:用绝对路径或 $CLAUDE_PROJECT_DIR

Stop hook 无限循环 解析 stop_hook_active 字段,已触发时直接退出:

bash
#!/bin/bash
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0
fi
# ... 其余 hook 逻辑

相关资源