跳到正文
Claude Code Hooks:让 AI 编程有迹可循、可审计、可回滚
0%
工具评测 · · 843 字 · 漫游君 · 深度 · 🔴 进阶 · Claude Code 实战 7/9 · ·

Claude Code Hooks:让 AI 编程有迹可循、可审计、可回滚

大多数人用 Claude Code 的方式是:给指令,看结果,如果不对就撤销。

这能工作,但有一个隐患:你不知道 AI 做了什么,直到它做完

Claude Code 的 Hooks 系统解决了这个问题。它让你能在 AI 执行每一步操作的前后注入自定义逻辑——不只是”允许还是拒绝”,而是完整的可编程拦截层。


Hooks 是什么

Hooks 是 Claude Code 在特定事件发生时自动执行的 shell 命令。

目前支持四种 Hook 事件:

Hook触发时机
PreToolUseAI 调用任何工具之前
PostToolUseAI 调用任何工具之后
NotificationClaude Code 发出通知时
StopClaude Code 完成响应时

每个 Hook 可以:

  • 接收 工具调用的完整上下文(工具名、参数、结果)
  • 执行 任意 shell 命令
  • 影响 工具调用的行为(PreToolUse 可以阻止执行)

配置方式

Hooks 在 ~/.claude/settings.json 里配置:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/pre-bash.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/post-write.sh"
          }
        ]
      }
    ]
  }
}

matcher 支持工具名(BashWriteEditRead 等)或 *(匹配所有工具)。


实战用例一:危险命令拦截

最常见的需求:阻止 AI 执行某些高风险操作。

~/.claude/hooks/pre-bash.sh

#!/bin/bash
# 读取工具调用的 JSON 输入
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# 拦截危险操作
DANGEROUS_PATTERNS=(
  "rm -rf /"
  "git push --force"
  "DROP TABLE"
  "chmod 777"
  "> /dev/sda"
)

for pattern in "${DANGEROUS_PATTERNS[@]}"; do
  if echo "$COMMAND" | grep -qi "$pattern"; then
    echo "🚫 Hook 拦截:检测到危险命令模式 '$pattern'" >&2
    # 退出码 2 = 阻止工具执行并显示错误
    exit 2
  fi
done

exit 0

Hook 的退出码决定行为:

  • 0 — 允许执行
  • 1 — 记录警告但允许执行
  • 2阻止执行,向 Claude 返回错误信息

实战用例二:文件修改自动备份

每次 AI 写文件之前,先备份一份:

~/.claude/hooks/pre-write.sh

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

if [ -f "$FILE_PATH" ]; then
  BACKUP_DIR="$HOME/.claude/backups/$(date +%Y%m%d)"
  mkdir -p "$BACKUP_DIR"

  # 保留目录结构
  RELATIVE_PATH=$(echo "$FILE_PATH" | sed 's|/|_|g')
  cp "$FILE_PATH" "$BACKUP_DIR/${RELATIVE_PATH}.bak"

  echo "✅ 已备份: $FILE_PATH$BACKUP_DIR" >&2
fi

exit 0

这样即使 AI 写坏了文件,~/.claude/backups/ 里永远有当天的版本。


实战用例三:操作日志

记录 Claude Code 所有工具调用,方便事后审计:

~/.claude/hooks/audit-log.sh

#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // "unknown"')
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
LOG_FILE="$HOME/.claude/audit.log"

# 提取关键参数(避免记录完整文件内容)
case "$TOOL_NAME" in
  "Bash")
    DETAIL=$(echo "$INPUT" | jq -r '.tool_input.command // ""' | head -c 200)
    ;;
  "Write"|"Edit")
    DETAIL=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
    ;;
  "Read"|"Glob"|"Grep")
    DETAIL=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.pattern // ""')
    ;;
  *)
    DETAIL=$(echo "$INPUT" | jq -r '.tool_input | to_entries[0].value // ""' | head -c 100)
    ;;
esac

echo "$TIMESTAMP | $TOOL_NAME | $DETAIL" >> "$LOG_FILE"
exit 0

配置到所有工具的 PostToolUse:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "*",
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/audit-log.sh" }]
      }
    ]
  }
}

一天下来,audit.log 会记录 Claude 做的每一件事。


实战用例四:飞书完成通知

长任务结束时推送通知,不用盯着屏幕等:

~/.claude/hooks/notify-done.sh

#!/bin/bash
INPUT=$(cat)
# Stop hook 触发:Claude 完成了一轮响应

# 从环境变量读取飞书 webhook
if [ -z "$FEISHU_WEBHOOK" ]; then exit 0; fi

curl -s -X POST "$FEISHU_WEBHOOK" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "text",
    "content": { "text": "✅ Claude Code 任务完成" }
  }' > /dev/null

exit 0

settings.jsonStop hook 里注册,长编译或大规模重构完成后,手机飞书就收到通知。


组合:完整的安全 + 可观测配置

把上面的 hooks 组合在一起:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/pre-bash.sh" }]
      },
      {
        "matcher": "Write",
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/pre-write.sh" }]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "*",
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/audit-log.sh" }]
      }
    ],
    "Stop": [
      {
        "matcher": "*",
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-done.sh" }]
      }
    ]
  }
}

这套配置实现了:

  • 🛡 危险命令自动拦截
  • 💾 文件修改前自动备份
  • 📋 所有操作完整审计日志
  • 📱 任务完成飞书通知

Hook 脚本的几个设计原则

1. 保持快速

每个工具调用都会触发 Hook,慢 Hook 会明显拖慢 Claude Code 的响应速度。避免在 Hook 里做网络请求(除非是非阻塞的 Stop Hook)。

2. 静默失败

Hook 脚本里的错误不应该崩溃 Claude Code。在脚本里加 set +e,确保即使 Hook 出错,也不影响主流程。

3. 用 stderr 输出诊断信息

Hook 的 stdout 会传给 Claude,stderr 才是给用户看的日志。诊断信息一律写 stderr:

echo "debug: processing $FILE_PATH" >&2  # 正确
echo "debug: processing $FILE_PATH"      # 会被 Claude 读到

4. 幂等设计

同一操作被触发多次,效果应该相同。备份脚本里用时间戳命名,避免覆盖。


与记忆系统结合

Hooks 和记忆架构可以结合使用。

比如,在 PostToolUse 里自动更新 Agent 的操作日志到 logs/

#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
DETAIL=$(echo "$INPUT" | jq -r '.tool_input | tostring' | head -c 100)
DAILY_LOG="./memory/logs/$(date +%Y-%m-%d)_ops.md"

echo "- $(date +%H:%M) [$TOOL] $DETAIL" >> "$DAILY_LOG"
exit 0

这样 Agent 的每次操作都自动沉淀进记忆,下次会话能复盘”上次到底做了什么”。


Hooks 系统把 Claude Code 从”黑盒 AI”变成了”可观测、可审计、可干预的工程工具”。

从信任,到验证——这才是在生产环境放心使用 AI 的正确姿势。


系列文章:Claude Code 实战 · 相关阅读:Claude Code 的记忆架构 · MCP 协议实战

这篇文章对你有帮助吗?

分享这篇文章

X / Twitter

感谢阅读这篇文章

约花了 19 分钟。如果对你有帮助,欢迎订阅 RSS 或收藏待读。

讨论

这篇文章让你感觉

评分

喜欢这篇文章?

订阅 RSS,第一时间收到新文章推送

订阅 RSS

私人笔记

仅保存在本地浏览器

讨论

评论加载中...