ep09-hooks-in-claude-code

Claude Code 101 系列教程 · 第 9 课

Claude (Anthropic)

2026-05-20

Hooks in Claude Code
第 9 课 · Hooks in Claude Code

Hooks in Claude Code

Claude Code 101 系列教程 · 第 9 课 · 来自 Claude 官方频道


什么是 Hooks?

Hooks 让你在 Claude Code 生命周期的关键节点上运行自定义命令——提供确定性控制,确保某些操作始终发生,而不是依赖 LLM 来选择是否执行。

关键区别: CLAUDE.md 里的指令是建议性的(Claude 可能不遵守),而 Hooks 是确定性的(每次都会执行)。


Hook 的五种类型

类型 工作方式 适合场景
command 运行 Shell 命令 格式化、拦截、通知
http POST 到一个 URL 外部服务、审计日志
mcp_tool 调用 MCP Server 上的工具 MCP 集成
prompt 单轮 LLM 评估 需要判断力的决策
agent 多轮子代理(实验性) 需要文件检查的验证

生命周期事件

Hooks 在以下时刻触发:

每个工具调用

事件 时机 能否拦截
PreToolUse 工具执行之前 可以阻止
PostToolUse 工具执行之后 可以添加反馈

每轮对话

事件 时机
UserPromptSubmit 用户提交 Prompt 时
Stop Claude 完成响应时

会话级

事件 时机
SessionStart 会话开始时
Notification Claude 发送通知时

配置位置

Hooks 定义在 settings.json 中,有三个位置:

位置 作用范围
.claude/settings.json(项目根目录) 当前项目,可提交到版本控制
.claude/settings.local.json 当前项目,不提交
~/.claude/settings.json 所有项目,个人偏好

实战示例

1. 编辑后自动格式化

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

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

2. 阻止危险操作

阻止 rm -rf 和保护敏感文件。

脚本 .claude/hooks/protect-files.sh

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

# 阻止 rm -rf
if echo "$COMMAND" | grep -q 'rm -rf'; then
  echo "Blocked: rm -rf is not allowed" >&2
  exit 2
fi

# 保护敏感文件
for pattern in ".env" "package-lock.json" ".git/"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH matches protected pattern" >&2
    exit 2
  fi
done
exit 0
chmod +x .claude/hooks/protect-files.sh

配置:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protect-files.sh"
          }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(rm *)",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

3. Claude 需要输入时发送通知

在 macOS 上弹出桌面通知:

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

Matcher 和 if 过滤

Matcher — 按工具名过滤

Matcher 值 含义
省略或 "*" 匹配所有
"Edit" 仅匹配 Edit 工具
"Edit\|Write" 匹配 Edit 或 Write

if — 按权限规则语法过滤

更精细的条件控制,只匹配特定命令模式:

{
  "type": "command",
  "if": "Bash(git push *)",
  "command": "./check-git-policy.sh"
}

退出码的含义

退出码 行为
0 正常,继续执行
2 阻止操作(PreToolUse 时阻止工具执行)
其他 错误,反馈给 Claude

最佳实践


总结


本教程基于 Claude 官方视频 Hooks in Claude Code 整理,属于 Claude Code 101 系列第 9 课。