多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Claude Code Hook 系统详解与 Hello World 实操:用 TaoToken 统一 Key 跑通 settings.json 配置

Claude Code Hook 系统详解与 Hello World 实操:用 TaoToken 统一 Key 跑通 settings.json 配置 1. 为什么要在 Claude Code 里折腾 HookClaude Code 用久了你会发现一个尴尬它每次调用工具、每次提交 prompt、每次结束响应你都是「事后才知道」。想加个日志、想在git commit前自动跑 lint、想在它改文件前拦一道默认情况下没有入口。Hook 就是补上这个入口的机制。简单说Hook 是 Claude Code 在特定运行时事件上自动执行你自定义脚本的能力。事件发生时harness 把上下文通过环境变量塞给你的脚本脚本爱干嘛干嘛——写日志、跑检查、发通知、拦命令都行。我习惯用嵌入式打比方Claude Code 像一块 BMC 芯片harness 是跑在上面的 RTOS 内核而 Hook 就是注册进去的中断服务例程。事件来了内核跳转到你的 ISR执行完再回来。区别只是这里的「中断」是PreToolUse、PostToolUse、UserPromptSubmit、Stop这些。这篇要解决三件事一是把 Hook 的 6 种事件和 matcher 匹配机制讲清楚二是给一份能直接复制的settings.json和脚本模板跑通 Hello World三是把模型调用通道用 TaoToken 统一起来避免 Key 散落各处。适合已经在用 Claude Code、想往工程化方向走一步的人。2. TaoToken 前置把 Key 和 Base URL 统一掉在写 Hook 之前先把模型调用这条链路理顺。Claude Code 默认走官方通道但很多团队希望 Key 集中管理、按项目隔离、方便审计。TaoToken 提供的就是这样一个统一入口一个 Key、一个 Base URLClaude Code、Codex、Cline 这些工具都能接。官网入口在这里https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。API 地址是 https://taotoken.net/api 注意这个不带 UTM 参数配置里直接写它。你需要准备三样东西我称之为「三件套」Base URLhttps://taotoken.net/apiAPI Key在控制台生成形如sk-...Model ID比如claude-sonnet-4-5这类具体模型标识生成 Key 的入口在控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keys 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。Claude Code 侧的配置有两种常见方式。第一种是环境变量写进 shell 的 profileexport ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的Key export ANTHROPIC_MODELclaude-sonnet-4-5第二种是写进 Claude Code 的配置文件。如果你用 Claude Code 的 settings 体系可以在~/.claude/settings.json里加env字段{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-5 } }这里有个坑要提前说settings.json里env和hooks是并列的顶层字段别把hooks塞进env里也别覆盖已有字段。很多人第一次配就是在这里把 permissions 弄丢了。配完之后Claude Code 的所有模型请求都走 TaoToken 通道。Hook 脚本本身不直接调模型但它记录的事件日志里会带上工具名、输入参数配合统一通道排查问题时能对上号。如果你更习惯用 Coding Plan 做长期编码任务入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。想先在网页里验证模型是否通可以用模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。3. 可复制配置settings.json Hook 脚本模板这一节是核心直接给能跑的东西。先建目录结构mkdir -p .claude/hooks然后创建脚本.claude/hooks/hello_hook.sh#!/bin/bash # Hello World Hook —— 演示 Claude Code Hook 系统的基本用法 # 环境变量 CLAUDE_TOOL_NAME / CLAUDE_TOOL_INPUT / CLAUDE_PROJECT_DIR 由 harness 自动注入 LOG_FILE$CLAUDE_PROJECT_DIR/.claude/hooks/hook_log.txt TIMESTAMP$(date %Y-%m-%d %H:%M:%S) EVENT${1:-unknown} case $EVENT in UserPromptSubmit) echo [$TIMESTAMP] 用户提交了 Prompt $LOG_FILE ;; Stop) echo [$TIMESTAMP] Claude 响应结束 $LOG_FILE ;; PreToolUse) echo [$TIMESTAMP] 即将调用工具: $CLAUDE_TOOL_NAME $LOG_FILE ;; PostToolUse) echo [$TIMESTAMP] 工具执行完毕: $CLAUDE_TOOL_NAME $LOG_FILE ;; *) echo [$TIMESTAMP] 事件触发: $EVENT | 工具: ${CLAUDE_TOOL_NAME:-none} $LOG_FILE ;; esac脚本通过$1接收事件类型case分支写不同格式的日志。$CLAUDE_PROJECT_DIR由 harness 注入指向项目根目录所以日志路径是稳定的。给执行权限chmod x .claude/hooks/hello_hook.sh接着是.claude/settings.json。如果你已经有这个文件把hooks作为顶层字段加进去和permissions、env并列{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-5 }, hooks: { PreToolUse: [ { matcher: , hooks: [ { type: command, command: bash \${CLAUDE_PROJECT_DIR}/.claude/hooks/hello_hook.sh\ PreToolUse } ] } ], PostToolUse: [ { matcher: , hooks: [ { type: command, command: bash \${CLAUDE_PROJECT_DIR}/.claude/hooks/hello_hook.sh\ PostToolUse } ] } ], UserPromptSubmit: [ { hooks: [ { type: command, command: bash \${CLAUDE_PROJECT_DIR}/.claude/hooks/hello_hook.sh\ UserPromptSubmit } ] } ], Stop: [ { hooks: [ { type: command, command: bash \${CLAUDE_PROJECT_DIR}/.claude/hooks/hello_hook.sh\ Stop } ] } ] } }字段含义对照一下字段含义hooks.事件名事件类型支持 PreToolUse / PostToolUse / UserPromptSubmit / Stop / Notification / SubagentStopmatcher匹配器匹配该事件所有实例也可写Edit、Bash或正则type执行类型command为 shell 命令还支持prompt注入提示词command要执行的命令${CLAUDE_PROJECT_DIR}由 harness 替换为项目根目录matcher 是这里最值得琢磨的。空字符串是「全匹配」写Edit只对 Edit 工具生效写Bash只对 Bash 生效。更细的玩法是用正则匹配命令内容比如Bash(git commit.*)这种形式只在 git commit 时触发。注意UserPromptSubmit和Stop这类事件没有工具名matcher 通常留空。注意settings.json必须是合法 JSON多一个逗号都会导致整个配置不生效而且 Claude Code 不一定报错只是静默忽略。改完用python -m json.tool .claude/settings.json验一下。4. 验证请求跑一轮对话看日志配置写完重启 Claude Code然后随便发一句话比如「读一下 README 文件」。等它响应完去看日志cat .claude/hooks/hook_log.txt正常输出长这样[2026-05-17 14:30:01] 用户提交了 Prompt [2026-05-17 14:30:02] 即将调用工具: Read [2026-05-17 14:30:02] 工具执行完毕: Read [2026-05-17 14:30:05] Claude 响应结束这四行对应了完整的数据流用户发消息触发UserPromptSubmitClaude 思考后调用 Read 工具触发PreToolUse工具执行完触发PostToolUse最后响应结束触发Stop。如果中间调用了多个工具PreToolUse和PostToolUse会成对出现多次。想验证 matcher 是否生效把PreToolUse的 matcher 从改成Bash重启后再让它读文件。你会发现 Read 不再记录只有 Bash 调用才写日志。这就是 matcher 的过滤作用。再进一步验证正则匹配。把 matcher 改成Bash(git status.*)然后让它执行git status日志里会出现执行ls则不会。正则匹配的是命令内容不是工具名这点容易搞混。如果你在验证过程中想确认模型通道是否正常可以单独用模型对话页面发一条测试https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。通道通了Hook 日志里的工具调用才会正常出现。还有一个实用技巧Hook 脚本里可以读$CLAUDE_TOOL_INPUT它是 JSON 格式的工具参数。比如在PreToolUse里加一行echo [$TIMESTAMP] 参数: $CLAUDE_TOOL_INPUT $LOG_FILE这样你能看到每次工具调用的具体入参排查「它到底改了什么文件」这类问题时特别有用。5. 本篇常见错排查报错一401 Unauthorized或invalid api key这是模型通道的问题不是 Hook 的问题。检查ANTHROPIC_API_KEY是否写对有没有多余空格。如果你用的是 TaoToken确认 Base URL 是https://taotoken.net/apiKey 是在控制台生成的。三件套缺一不可Base URL、Key、Model ID。改完环境变量记得重开终端或者source一下 profile。报错二local proxy failed或连接超时通常是 Base URL 写错比如漏了/api后缀或者写成了带 UTM 的完整链接。配置里只写https://taotoken.net/api不要带查询参数。另外检查网络是否能正常访问该地址可以用curl -I https://taotoken.net/api快速验证连通性。报错三reading choices相关解析错误这类错误一般出现在响应格式不符合预期时。先确认 Model ID 是通道支持的模型别写了个不存在的名字。如果换了模型后出现换回默认模型试试。Hook 本身不解析模型响应所以这个错和 Hook 无关是通道配置问题。报错四Hook 完全不触发日志文件不生成按顺序排查第一settings.json是不是合法 JSON用python -m json.tool验第二脚本有没有执行权限ls -l .claude/hooks/hello_hook.sh看有没有x第三${CLAUDE_PROJECT_DIR}是否被正确替换可以在脚本开头加echo DIR$CLAUDE_PROJECT_DIR调试第四改完配置有没有重启 Claude CodeHook 配置是启动时加载的。报错五OAuth相关提示如果你之前用官方登录方式认证过环境变量和 OAuth 可能冲突。清掉旧的认证缓存确保走的是 API Key 方式。检查~/.claude下有没有残留的凭据文件必要时备份后移除。报错六matcher 写了但不生效matcher 是大小写敏感的edit和Edit不一样。正则写法要符合规范Bash(git commit.*)这种形式里括号和点号都有含义。先用空 matcher 确认 Hook 能触发再逐步收紧匹配条件。提示调试 Hook 时最省事的办法是在脚本第一行加set -x把执行过程打到 stderrClaude Code 的日志里能看到。确认没问题再删掉。6. 把 Hook 用起来从 Hello World 到真实场景Hello World 跑通只是起点。真正有价值的是把 Hook 接到你的工作流里。一个我常用的场景是「提交前自动检查」。用PreToolUse匹配Bash(git commit.*)脚本里跑npm run lint不通过就返回非零退出码Claude Code 会感知到并停下来。这样就不会出现「AI 帮你提交了一堆格式错误的代码」这种事。另一个场景是审计。把所有PostToolUse事件写进结构化日志记录工具名、参数、时间戳。配合 TaoToken 统一通道你能把「模型请求」和「工具调用」两条线对上分析 AI 的行为模式。这在团队协作里很有用谁改了什么、什么时候改的一目了然。再进阶一点Hook 脚本可以调用外部 HTTP 接口。比如Stop事件触发时往你的通知服务发一条消息或者PreToolUse检测到高风险命令rm -rf、git push --force时先发个确认请求。这些都不需要改 Claude Code 本身全在脚本里完成。如果你在做长期编码任务把 Hook 和 Coding Plan 结合起来会更顺https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。统一的 Key 管理加上事件驱动的自动化基本就是一套轻量的 AI 开发流水线。最后提醒一句Hook 脚本里不要写死敏感信息Key 走环境变量或配置文件。脚本本身建议纳入版本控制但日志文件记得加进.gitignore。跑通之后先从一个小场景开始用别一上来就挂一堆 Hook出问题不好定位。
返回列表