1. 为什么你的 Claude Code 需要一个“刹车系统”
Hooks 是 Claude Code 提供的生命周期事件系统,能让你在工具调用前、调用后、任务完成时自动执行自定义脚本,实现危险操作拦截、代码质量检查、审计日志记录等自动化控制。它适合所有已经在用 Claude Code 写代码、但担心“AI 手滑删库”或“改完不跑测试”的开发者。我试过在没配 Hooks 的项目里让 Claude 批量重构,结果它顺手把一个.env文件里的密钥格式改了,虽然没造成实际损失,但那一刻我意识到:没有 Hooks 的 Claude Code,就像一辆没有刹车的车。
没有 Hooks 的工作流是:用户输入 → Claude 执行 → 输出结果,中间过程完全由 Claude 控制,你无法干预。有了 Hooks 之后,工作流变成:用户输入 → PreToolUse Hook(检查/阻止)→ Claude 执行工具 → PostToolUse Hook(验证/记录)→ Stop Hook(最终检查)→ 输出结果。Hooks 的本质是你对 Claude Code 行为的控制权:在它做某件事之前检查、修改甚至阻止,在它做某件事之后验证、记录、触发后续操作。
这一章我们从settings.json配置骨架切入,用 TaoToken 统一 Key 和 API 通道,把 Hooks 触发链路完整跑通。你会拿到可直接复制的配置片段、验证动作,以及我踩过的坑。TaoToken 在这里的角色是:统一管理 Claude Code 的 API 通道,让 Hooks 脚本里需要调用模型能力时(比如自动生成审计摘要),不用再散落多个 Key。
2. TaoToken 前置:统一 Key 与 API 通道
在配置 Hooks 之前,先把 API 通道理顺。Claude Code 本身通过环境变量读取 API 配置,如果你在多个项目、多个脚本里各写一套 Key,Hooks 脚本里再硬编码一遍,维护成本会爆炸。TaoToken 的做法是提供一个统一的 API 入口,你只需要在环境变量里配置一次。
官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数,直接用于代码配置。
你需要先拿到 API Key。访问 API Keys 管理页面:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite ,创建一个新 Key 并复制。然后在终端里配置环境变量:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="你的TaoToken_API_Key"如果你用的是 Claude Code 的配置文件方式,可以写进~/.claude/settings.json的env字段。这样 Hooks 脚本里如果需要调用模型(比如让模型判断某个命令是否危险),可以直接复用同一套环境变量,不用再单独传 Key。
注意:环境变量配置完成后,建议新开一个终端窗口再启动 Claude Code,确保变量生效。我踩过的坑是在同一个终端里
export后直接跑,结果 Claude Code 读的是旧进程的环境。
3. 可复制配置:settings.json 骨架与 Hook 脚本
Claude Code 的 Hooks 配置写在settings.json里,项目级配置放在.claude/settings.json,用户级配置放在~/.claude/settings.json。项目级优先级更高,适合团队共享。下面是一个完整的配置骨架,包含 PreToolUse、PostToolUse、Stop 三类事件。
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "你的TaoToken_API_Key" }, "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": ".claude/hooks/pre-tool-use.sh" } ] } ], "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": ".claude/hooks/post-tool-use.sh" } ] } ], "Stop": [ { "hooks": [ { "type": "command", "command": ".claude/hooks/stop.sh" } ] } ] } }matcher字段用正则匹配工具名称,Bash只匹配 Bash 工具,Write|Edit匹配写入和编辑操作。hooks数组里每个元素是一个要执行的命令,type固定为command。
接下来创建 Hook 脚本目录和文件:
mkdir -p .claude/hooks touch .claude/hooks/pre-tool-use.sh touch .claude/hooks/post-tool-use.sh touch .claude/hooks/stop.sh chmod +x .claude/hooks/*.sh先写一个最小可用的 PreToolUse 脚本,拦截危险命令:
#!/bin/bash # .claude/hooks/pre-tool-use.sh TOOL_NAME="$1" TOOL_PARAMS="$2" if [ "$TOOL_NAME" = "Bash" ]; then COMMAND=$(echo "$TOOL_PARAMS" | python3 -c " import json, sys params = json.load(sys.stdin) print(params.get('command', '')) ") DANGEROUS_PATTERNS=("rm -rf /" "rm -rf ~" "dd if=/dev/zero" "mkfs") for pattern in "${DANGEROUS_PATTERNS[@]}"; do if echo "$COMMAND" | grep -qF "$pattern"; then echo "危险操作被阻止:$COMMAND" echo "匹配危险模式:$pattern" exit 1 fi done fi exit 0exit 1表示阻止执行,exit 0表示放行。PostToolUse 脚本用来做代码质量检查:
#!/bin/bash # .claude/hooks/post-tool-use.sh TOOL_NAME="$1" TOOL_PARAMS="$2" if [ "$TOOL_NAME" != "Write" ] && [ "$TOOL_NAME" != "Edit" ]; then exit 0 fi FILE_PATH=$(echo "$TOOL_PARAMS" | python3 -c " import json, sys params = json.load(sys.stdin) print(params.get('file_path', params.get('path', ''))) " 2>/dev/null) if [[ "$FILE_PATH" == *.py ]]; then echo "自动检查 Python 文件:$FILE_PATH" if command -v ruff &> /dev/null; then ruff check "$FILE_PATH" --fix --quiet 2>/dev/null if [ $? -eq 0 ]; then echo "Ruff 检查通过" fi fi python3 -m py_compile "$FILE_PATH" 2>&1 if [ $? -ne 0 ]; then echo "Python 语法错误" fi fi exit 0Stop 脚本在任务完成时做最终验证和通知:
#!/bin/bash # .claude/hooks/stop.sh TASK_SUMMARY="$1" echo "任务完成,执行后置检查..." if [ -f "pytest.ini" ] || [ -f "pyproject.toml" ]; then pytest tests/unit/ -x -q --tb=no 2>&1 | tail -5 if [ $? -ne 0 ]; then echo "警告:部分测试失败" exit 1 fi echo "测试验证通过" fi exit 04. 验证请求:跑通事件驱动链路
配置写完后,需要验证 Hooks 是否真的被触发。最直接的方式是启动 Claude Code 并执行一个会触发 Hook 的操作。
先确认脚本有执行权限:
ls -la .claude/hooks/应该看到三个脚本都有x权限。然后启动 Claude Code:
claude在对话里输入一个会触发 Bash 工具的任务,比如“帮我看看当前目录下有哪些文件”。Claude 会调用 Bash 工具执行ls,此时 PreToolUse Hook 会被触发。如果脚本正常执行,你会在终端看到脚本里的输出(如果有的话),或者至少不会报错。
为了更明确地验证,可以在 PreToolUse 脚本开头加一行日志:
echo "$(date '+%Y-%m-%d %H:%M:%S') PreToolUse triggered: $TOOL_NAME" >> .claude/hooks-debug.log然后让 Claude 执行一个危险命令测试拦截效果。在对话里输入“执行 rm -rf /tmp/test”,Claude 会尝试调用 Bash 工具,PreToolUse Hook 检测到rm -rf /模式后返回exit 1,Claude Code 会收到阻止信号,不会真正执行该命令。你会在终端看到“危险操作被阻止”的输出。
PostToolUse 的验证方式是让 Claude 写一个 Python 文件,比如“创建一个 test_hook.py,内容是一个简单的 print”。Claude 调用 Write 工具后,PostToolUse Hook 会触发,运行 Ruff 检查和语法检查。如果文件有语法错误,你会在终端看到提示。
Stop Hook 的验证是完成一个任务后观察。让 Claude 做一个需要多步操作的任务,任务结束时 Stop Hook 触发,如果项目里有 pytest 配置,会自动跑单元测试。
提示:如果 Hook 没有触发,先检查
settings.json的 JSON 格式是否正确,可以用python3 -m json.tool .claude/settings.json验证。其次检查脚本路径是相对路径还是绝对路径,Claude Code 从项目根目录执行脚本,相对路径要确保正确。
5. 本篇常见错排查
错误一:Hook 脚本没有执行权限。症状是 Claude Code 启动时报错“command not found”或“permission denied”。解决方法是chmod +x .claude/hooks/*.sh。我踩过的坑是在 Windows 上编辑脚本后传到 Linux,换行符变成 CRLF,bash 无法解析,用dos2unix转换即可。
错误二:settings.json 里 matcher 写错。比如想匹配 Write 工具却写了write,正则不匹配就不会触发。工具名称是大小写敏感的,Bash、Write、Edit、Read都是首字母大写。可以用.*匹配所有工具,但这样每个工具调用都会触发 Hook,可能影响性能。
错误三:Hook 脚本里读取参数失败。Claude Code 传给 Hook 的参数是位置参数,$1是工具名称,$2是 JSON 格式的工具参数。如果脚本里用$2解析 JSON 报错,检查是否装了python3,或者 JSON 里字段名是否和预期一致。不同工具的参数字段不同,Bash 是command,Write 是file_path和content,Edit 是file_path、old_string、new_string。
错误四:Hook 阻塞导致 Claude Code 卡住。如果 Hook 脚本里有交互式命令(比如read)或者长时间运行的进程,Claude Code 会一直等待。Hook 脚本要快,建议控制在 1 秒内。慢速检查可以放到后台异步执行,或者只在 Stop Hook 里做。
错误五:环境变量没生效。如果 Hooks 脚本里需要调用模型 API,但ANTHROPIC_API_KEY没设置,会报认证失败。确认settings.json的env字段配置正确,或者终端里export后新开窗口。TaoToken 的 API 地址是https://taotoken.net/api,不要漏掉/api路径。
错误六:Stop Hook 返回非零导致循环。Stop Hook 返回exit 1时,Claude Code 会认为任务未完成,继续执行。如果脚本里无条件返回exit 1,会陷入死循环。正确做法是只在确实需要继续处理时返回非零,比如测试失败需要 Claude 修复。
6. 从 Hooks 到统一通道:下一步怎么走
Hooks 跑通之后,你会发现它和 TaoToken 的统一 Key 是天然搭配。Hooks 脚本里如果需要调用模型做判断(比如让模型评估某个命令的风险等级),直接复用ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY就行,不用再维护第二套凭证。
如果你还在调试阶段,想先验证模型对话是否正常,可以访问模型对话页面:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite ,快速测试 API 通道。
如果你准备把 Hooks 用在长期编码项目里,建议了解一下 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite ,它针对持续编码场景做了通道优化。
接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有完整的 API 参数说明和示例。Claude Code 专用接入指南在 https://taotoken.net/doc/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode_anthropic&utm_campaign=rewrite ,如果你用的是 Claude Code 的 Anthropic 兼容模式,这篇文档会帮你把配置对齐。
最后提醒一点:Hooks 脚本里的审计日志建议按天切分,避免单个文件过大。我习惯用.claude/audit/$(date +%Y-%m-%d).log的格式,配合logrotate或者简单的定时清理脚本。另外,Hook 脚本本身也要纳入版本控制,团队共享时确保每个人的环境都能跑通。