在 Claude Code 中配置 Hook 是构建生产级自动化工作流的关键。本文将基于 Claude HowTo 教程指南中的 8 个实战脚本,手把手教你实现代码自动格式化、安全扫描拦截、用户提示验证、上下文 token 追踪、会话学习进度记录及依赖漏洞检查,让你的 AI 编程助手更安全、更高效。

8 个 Hook 脚本实战:自动格式化、安全扫描、提示验证与上下文追踪

Claude Code 的 Hook 系统允许你在特定事件发生时自动执行脚本,从而实现自动化验证、格式化、安全检查和日志记录。本文将基于 Claude HowTo 教程指南中的 8 个实战脚本,深入解析其核心设计与配置方法,帮助你快速将这些生产就绪的模板应用到自己的项目中。

1. pre-tool-check.sh:双层安全检查与审计日志

这个脚本在 PreToolUse:Bash 事件触发时运行,用于拦截或警告潜在的危险命令。它的核心设计是双层安全检查

工作原理与配置: 脚本首先读取来自 stdin 的 JSON 输入,提取将要执行的 Bash 命令。然后进行两层模式匹配:

  • Blocked patterns:如 rm -rf /dd if=/dev/zeromkfs. 等。这些命令被无条件阻断,脚本以 exit 2 退出,Claude Code 会将 stderr 的内容(即阻断原因)反馈给 Claude。
  • Warning patterns:如 git push --forcechmod -R 777DROP TABLE 等。这些命令被识别为高风险,但允许执行。脚本会记录一条警告到审计日志,并以 exit 0 退出。

关键机制——审计日志: 由于 Claude Code 在 exit 0 时会静默丢弃 stderr,脚本将所有决策(BLOCK/WARN/ALLOW)写入一个独立的审计日志文件 $CLAUDE_PROJECT_DIR/.claude/hooks/audit.log。这是监控警告级别事件的唯一可靠方法。

# 审计日志记录函数
log_decision() {
  echo "$(date -u +%FT%TZ) [$1] $COMMAND" >> "$LOG_FILE"
}

要启用此脚本,将其复制到 ~/.claude/hooks/ 目录,并在你的 Claude Code 设置文件中配置:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/pre-tool-check.sh"
          }
        ]
      }
    ]
  }
}

2. security-scan.sh:多模式密钥与凭据检测

该脚本在 PostToolUse:Write 事件触发后运行,扫描新写入或修改的文件,检测硬编码的密钥、密码和私钥,发出非阻塞警告。

多模式检测规则: 脚本定义了多组 grep 模式,覆盖常见形式:

  • 密码:检测 "password": "value"password = 'value' 格式。
  • API 密钥:检测 "api_key": "value""apikey": "value""access_token": "value"
  • 私钥:检测 BEGIN.*PRIVATE KEY 头。
  • AWS 密钥:检测符合 AKIA[0-9A-Z]{16} 格式的字符串。

外部工具集成: 如果环境中安装了 semgreptrufflehog,脚本会调用它们进行更深入的扫描,并将 stdout 静默以避免污染 JSON 输出。

输出格式: 当发现任何问题时,脚本会按照 Claude Code 的 PostToolUse 协议,输出一个包含 additionalContext 字段的 JSON 对象,将安全警告反馈给 Claude。

printf '{"hookSpecificOutput": {"hookEventName": "PostToolUse", "additionalContext": "Security scan found issues in %s:\\n%sPlease review and use environment variables instead."}}' "$SAFE_PATH" "$SAFE_ISSUES"

3. format-code.sh:多语言代码自动格式化

PostToolUse:WritePostToolUse:Edit 事件后,此脚本自动调用对应语言的格式化工具,确保 Claude 生成的代码风格统一。

多语言格式化器检测: 脚本通过文件扩展名判断语言,并检查相应格式化工具是否可用,实现无侵入式集成:

case "$FILE_PATH" in
  *.js|*.jsx|*.ts|*.tsx)
    command -v prettier &> /dev/null && prettier --write "$FILE_PATH"
    ;;
  *.py)
    command -v black &> /dev/null && black "$FILE_PATH"
    ;;
  *.go)
    command -v gofmt &> /dev/null && gofmt -w "$FILE_PATH"
    ;;
  *.rs)
    command -v rustfmt &> /dev/null && rustfmt "$FILE_PATH"
    ;;
  *.java)
    command -v google-java-format &> /dev/null && google-java-format -i "$FILE_PATH"
    ;;
esac

它支持 JavaScript/TypeScript(prettier)、Python(black)、Go(gofmt)、Rust(rustfmt)和 Java(google-java-format),只要本地安装了这些工具,就会在文件保存后自动执行。

4. validate-prompt.sh:用户提示安全验证

当用户提交提示时,UserPromptSubmit 事件触发此脚本。它会在 Claude 处理提示前进行验证,可阻断危险操作。

危险操作拦截: 脚本定义了一个危险操作列表,并逐一匹配用户提示:

DANGEROUS_PATTERNS=(
  "rm -rf /"
  "delete database"
  "drop database"
  ...
)

一旦匹配,脚本将输出一个包含 "decision": "block" 和原因的 JSON,阻止 Claude 执行该提示。

生产部署审批流程: 对于 deploypushproduction 的提示,脚本会检查项目中是否存在 .deployment-approved 文件。若不存在,则阻断请求并提示创建审批文件,实现了一个简易的审批门控。

5. context-tracker.py:双 Hook 模式下的上下文消耗追踪

这是一个巧妙的 Python 脚本,通过成对使用 UserPromptSubmitStop 事件来计算每次请求的 token 消耗增量。

双 Hook 协同工作原理:

  1. UserPromptSubmit:在用户提示被处理前,读取当前会话的 transcript 文件,估算当前的 token 总数,并保存到临时文件。
  2. Stop:在 Claude 响应完成后,再次估算 token 总数,减去之前保存的值,得到本次请求的 token 增量,并计算上下文使用百分比和剩余量。

两种 Token 计数方法:

  • 字符估算(默认):基于每 4 个字符约等于 1 个 token 的经验法则,零依赖,准确率约 80-90%。
  • tiktoken(可选):使用 tiktoken 库和 p50k_base 编码,准确率约 90-95%,需要安装额外依赖。

关键实现细节:

  • 使用 session_id 作为临时文件名的一部分,隔离不同会话的状态。
  • 通过读取 transcript_path 获取上下文内容,该文件记录了用户和 Claude 的对话历史。
  • 将报告输出到 stderr,避免干扰 Hook 的正常 JSON 输出。

配置此脚本需要在设置中同时为 UserPromptSubmitStop 事件添加相同的命令:

{
  "hooks": {
    "UserPromptSubmit": [{
      "hooks": [{"type": "command", "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/context-tracker.py\""}]
    }],
    "Stop": [{
      "hooks": [{"type": "command", "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/context-tracker.py\""}]
    }]
  }
}

6. session-end.sh:交互式学习进度追踪

此脚本挂载在 SessionEnd 事件上,在 Claude Code 会话终止时触发,用于记录你本次会话学习了哪些模块。

交互式设计与关键模式:

  • 会话结束触发:使用 SessionEnd 而非 Stop,确保只在会话彻底结束时记录一次。
  • 终端输入:由于 Hook 的 stdin 被 JSON 输入占用,脚本使用 read -r INPUT </dev/tty 直接从终端读取用户输入。
  • 进度持久化:学习进度保存在用户主目录的 ~/.claude-howto-progress.json 文件中,位于仓库之外,避免被 git pull 覆盖。
  • 防护性守卫:脚本开头检查 CLAUDE_PROJECT_DIRPWD 是否包含 claude-howto,防止在无关项目中误触发。

安装后,在会话结束时,脚本会提示你输入本次学习的模块编号(如 06,07),并将记录追加到进度文件中,为你的学习旅程留下足迹。

7. dependency-check.sh:多包管理器漏洞扫描

PostToolUse:Write 事件写入依赖清单文件(如 package.jsonrequirements.txtgo.mod)时,此脚本会自动触发,扫描已知的安全漏洞。

多包管理器支持与 trivy 兜底: 脚本通过文件名判断包管理器类型,并调用对应的审计工具:

  • Node.js:调用 npm audit,并用 Python 解析 JSON 输出,仅报告 high 和 critical 级别的漏洞。
  • Python:优先使用 pip-audit,回退到 safety
  • Go:使用 govulncheck
  • Rust:使用 cargo audit
  • Ruby:使用 bundler-audit
  • 通用回退:如果安装了 trivy,会使用它进行一次通用的文件系统扫描,查找 HIGH/CRITICAL 问题。

设计特点:

  • 仅警告不阻断:脚本始终以 exit 0 退出,将发现的漏洞以建议形式反馈给用户,不会阻止工作流。
  • 清晰的摘要输出:扫描完成后,会明确告知是“通过”还是“检测到漏洞”。

8. log-bash.sh:Bash 命令日志记录

这是一个轻量级的审计脚本,在 PostToolUse:Bash 事件后运行,将所有执行的 Bash 命令记录到日志文件中。

实现逻辑:

COMMAND=$(echo "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
LOGFILE="$HOME/.claude/bash-commands.log"
echo "[$TIMESTAMP] $COMMAND" >> "$LOGFILE"

脚本从输入 JSON 中提取命令,加上时间戳,追加到 ~/.claude/bash-commands.log 文件。这对于审计 Claude 自动执行的所有 shell 命令非常有用,尤其是在调试或审查自动化任务时。

如何应用这些脚本

  1. 复制脚本:将需要的脚本从 06-hooks/ 目录复制到你的项目 .claude/hooks/ 或用户级 ~/.claude/hooks/ 目录。
  2. 赋予执行权限chmod +x .claude/hooks/your-script.sh
  3. 配置 settings.json:在项目的 .claude/settings.json 或用户级 ~/.claude/settings.json 中,根据配置模板添加相应的 Hook 事件配置。
  4. 测试:启动新的 Claude Code 会话,触发对应的操作(如写入文件、提交提示、结束会话),观察脚本是否按预期工作。

FAQ

Q: 如何调试 Hook 脚本? A: 可以在脚本中添加 set -x 开启调试输出,或在脚本中打印日志到 stderr(echo "debug info" >&2)。Claude Code 在详细模式下会显示 stderr 输出。对于 exit 0 的脚本,将调试信息写入独立文件(如审计日志)是更可靠的方式。

Q: Hook 脚本出错或阻断了正常操作怎么办? A: 首先检查脚本的 stderr 输出(Claude Code 会显示)。如果是 pre-tool-check.sh 这类安全脚本误判,可以暂时注释掉对应模式或调整正则表达式。如果问题紧急,可以通过在设置文件中将 "disableAllHooks": true 来临时禁用所有 Hook,然后排查问题。