ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Agent Hooks 实战入门:手把手配置你的第一个 Hook(二)——用 TaoToken 统一 Key 打通 settings.json

Agent Hooks 实战入门:手把手配置你的第一个 Hook(二)——用 TaoToken 统一 Key 打通 settings.json 1. 为什么你的 Hook 总是配了不生效很多人第一次接触 Agent Hooks都是被自动化三个字吸引进来的让 Claude Code 在每次写完文件后自动跑格式化、在提交前自动检查敏感文件、在会话启动时自动注入项目上下文。听起来很美好但真正动手时十个人里有八个卡在同一个地方——配置写进去了命令也执行了Hook 就是没反应。我见过最典型的场景是这样的你在settings.json里认认真真写了一段PreToolUse保存重启 Claude Code然后让 Claude 执行一条rm -rf ./test-dir结果它二话不说就把目录删了。你打开日志一看Hook 压根没被触发。问题出在哪可能是 JSON 语法错了一个逗号可能是matcher写成了bash而不是Bash也可能是脚本没有执行权限还可能是你改的是用户级配置但项目级配置把它覆盖了。这一篇要解决的就是从配置到跑通这最后一公里。我们不讲概念直接上手从settings.json的文件位置讲起把 Hook 的触发链路拆开给你看然后给出可以直接复制的配置片段最后用一个真实的危险命令拦截案例带你走完配置—触发—验证—排障的完整闭环。同时这一篇还会解决另一个容易被忽略的问题Key 的统一管理。当你在 Claude Code、CodeBuddy 之间来回切换每个工具都要单独配一遍 API Key、Base URL、Model ID改一次要改三个地方非常容易出错。我会用 TaoToken 的统一 Key 通道把这件事一次性理顺让 Hook 配置和模型接入解耦后面无论你换哪个 Agent 工具配置都能复用。适合谁读已经装好 Claude Code 或 CodeBuddy、想跑通第一个 Hook 的开发者被settings.json各种作用域搞晕的人以及想让多个 Agent 工具共用一套 Key 配置的人。读完你至少能得到三样东西一份能直接跑的 Hook 配置、一套统一的 Key 接入写法、一份真实报错的排查对照表。2. settings.json 文件位置与 Hook 触发链路拆解在写第一行配置之前先把文件位置搞清楚。这是最多人踩坑的地方——配置写对了但写错了文件等于没写。Claude Code 和 CodeBuddy 都兼容同一套 Hooks 规范配置文件都是 JSON 格式的settings.json区别只在目录名。Claude Code 用~/.claude/CodeBuddy 用~/.codebuddy/。按作用范围分有三个层级作用域Claude Code 路径CodeBuddy 路径说明用户级~/.claude/settings.json~/.codebuddy/settings.json对所有项目生效个人通用配置项目级项目根/.claude/settings.json项目根/.codebuddy/settings.json团队共享可提交 Git项目本地项目根/.claude/settings.local.json项目根/.codebuddy/settings.local.json本地覆盖不提交 Git关键点在于多个配置文件同时存在时Hooks 是合并而不是覆盖。但优先级是项目本地 项目级 用户级。这意味着你可以在用户级放通用规则比如全局的危险命令拦截在项目级放项目特定规则比如这个项目专用的格式化脚本。如果你发现用户级配的 Hook 没生效第一件事就是检查项目级是不是有同名配置把它盖住了。Windows 用户注意~在 Git Bash 里对应C:\Users\你的用户名\。如果你用记事本编辑记得保存时选 UTF-8 编码否则中文提示会乱码。目录不存在就手动新建settings.json不存在就新建一个空文件内容先写{}。接下来拆触发链路。一个 Hook 从Claude 决定调用工具到脚本执行完返回结果中间经过这么几步第一步Claude 准备调用某个工具比如Bash。第二步系统检查当前事件类型如果是工具调用前就触发PreToolUse事件。第三步遍历PreToolUse数组里的所有 matcher看哪个 matcher 能匹配上当前工具名。第四步匹配成功后执行该 matcher 下hooks数组里的每一条命令。第五步脚本通过 stdin 收到一段 JSON里面包含tool_input等上下文。第六步脚本通过 stdout 输出决策 JSON并用退出码告诉系统结果exit 0放行exit 2阻止。这里有个容易搞混的点退出码和输出 JSON 是两套机制。退出码2表示阻止这是硬性的而输出里的permissionDecision: deny是给 Claude 看的理由。两者配合使用效果最好——退出码负责拦截JSON 负责解释原因这样 Claude 会知道为什么被拦而不是一脸懵。理解了这条链路排障就有方向了Hook 没触发查 matcher 和事件名触发了但没拦住查退出码拦住了但没提示查 JSON 格式。3. 可复制的 settings.json Hook 配置与 TaoToken 统一 Key 接入这一节给你两份可以直接复制的配置一份是 Hook 配置一份是 TaoToken 的 Key 接入配置。两者分开管理互不干扰。先看 Hook 配置。我们实现一个最实用的场景拦截rm -rf危险命令。直接写在settings.json里{ hooks: { PreToolUse: [ { matcher: Bash, hooks: [ { type: command, command: ~/.codebuddy/hooks/check-dangerous-command.sh } ] } ] } }注意这里command指向的是一个脚本文件而不是把逻辑全塞进 JSON。这是最佳实践——配置保持简洁复杂逻辑放脚本。脚本内容如下保存到~/.codebuddy/hooks/check-dangerous-command.sh#!/bin/bash input$(cat) command$(echo $input | jq -r .tool_input.command // empty) if [[ $command *rm -rf* ]]; then echo {hookSpecificOutput:{hookEventName:PreToolUse,permissionDecision:deny,permissionDecisionReason:禁止执行 rm -rf 危险命令请手动操作}} exit 2 fi exit 0给脚本加执行权限chmod x ~/.codebuddy/hooks/check-dangerous-command.sh。这里依赖jq解析 JSON没装的先装一下macOS 用brew install jqUbuntu 用apt install jqWindows 用 Git Bash 自带的包管理器或直接下二进制。现在说 TaoToken 的接入。TaoToken 提供统一的 API 通道让你在 Claude Code、CodeBuddy 等工具里共用一套 Key。接入信息如下官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 地址https://taotoken.net/api模型对话入口https://taotoken.net/api/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewriteAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite在 Claude Code 里模型接入配置通常放在~/.claude/settings.json或环境变量里。如果你用settings.json方式可以这样写注意这是模型配置和上面的 Hook 配置在同一个文件的不同字段互不影响{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: 你的TaoToken Key, ANTHROPIC_MODEL: claude-sonnet-4-20250514 }, hooks: { PreToolUse: [ { matcher: Bash, hooks: [ { type: command, command: ~/.claude/hooks/check-dangerous-command.sh } ] } ] } }三件套要写全Base URL Key Model ID。Base URL 固定是https://taotoken.net/apiKey 从 API Keys 页面获取Model ID 按你实际要用的模型填。CodeBuddy 的写法类似把ANTHROPIC_前缀换成 CodeBuddy 对应的环境变量名即可具体字段名参考接入文档。如果你用 Codex配置在~/.codex/auth.json结构不太一样但同样是三件套齐全{ base_url: https://taotoken.net/api, api_key: 你的TaoToken Key, model: claude-sonnet-4-20250514 }这样配下来你的 Hook 逻辑和模型接入就彻底解耦了。以后换工具、换模型只改 Key 配置那一段Hook 配置原封不动。4. 触发一次 Hook 并查看日志验证结果配置写完最激动人心的时刻到了验证它到底有没有生效。第一步重启你的 Agent 工具。settings.json改动后不会热加载必须重启。Claude Code 直接退出重进CodeBuddy 同理。第二步用 debug 模式启动这样能看到 Hook 的执行日志。CodeBuddy 用codebuddy --debugClaude Code 用claude --debug。启动后你会看到一堆 DEBUG 输出重点找这几行[DEBUG] Executing hooks for PreToolUse:Bash [DEBUG] Found 1 hook matchers [DEBUG] Matched 1 hooks for query Bash [DEBUG] Hook command completed with status 2这四行分别对应事件触发、找到 matcher、匹配成功、脚本返回退出码 2。如果只看到第一行没有后面几行说明 matcher 没匹配上如果看到status 0说明脚本放行了检查一下你的判断条件。第三步在会话里输入/hooks命令。这会列出当前已注册的所有 Hook确认你配的那条在列表里。如果不在说明配置文件没被读到回去检查文件路径和 JSON 语法。第四步实际触发一次。让 Claude 执行一条危险命令请帮我删除测试目录rm -rf ./test-dir预期结果是 Claude 被拦住并显示你配置的提示语禁止执行 rm -rf 危险命令请手动操作。如果它真的把目录删了别慌先看 debug 日志里 Hook 有没有执行。第五步验证放行路径。让 Claude 执行一条安全命令比如ls -la确认它能正常执行。这一步很重要——很多人只测了拦截没测放行结果发现 Hook 把所有命令都拦了因为脚本逻辑写错了。实测下来整个流程从配置到验证熟练的话五分钟能跑通。第一次可能会在jq没装、脚本没权限、路径写错这几个地方卡一下都属于正常。5. 常见报错排查401、local proxy failed、reading choices、OAuth跑通之后你可能会遇到一些报错。这一节把最常见的几类列出来对照排查。401 Unauthorized。这个几乎都是 Key 的问题。检查三件事Key 有没有复制完整前后别带空格、Key 有没有过期、Base URL 有没有写对。特别注意 Base URL 结尾不要多加斜杠https://taotoken.net/api和https://taotoken.net/api/在某些工具里行为不一样。如果用的是 TaoToken 的 Key去 API Keys 页面确认一下 Key 状态。local proxy failed。这个报错通常出现在工具尝试连接本地代理时。检查你的环境变量里有没有残留的HTTP_PROXY、HTTPS_PROXY设置有的话清掉。另外确认ANTHROPIC_BASE_URL指向的是https://taotoken.net/api而不是某个本地地址。Error reading choices / reading choices。这个报错一般出现在响应解析阶段说明请求发出去了但返回格式不对。常见原因是 Model ID 写错了或者 Base URL 指向了一个不兼容 OpenAI 格式的端点。确认你的 Model ID 和 Base URL 是配套的TaoToken 的 API 地址统一用https://taotoken.net/api。OAuth 相关报错。如果你在 Claude Code 里看到 OAuth 报错通常是因为工具在尝试走官方登录流程而不是用你配的 Key。检查settings.json里的env字段有没有生效或者环境变量有没有被 shell 的其它配置覆盖。用echo $ANTHROPIC_BASE_URL确认一下实际生效的值。Hook 未触发。回到第 2 节的触发链路先确认事件名对不对PreToolUse不是PreToolUseHook再确认 matcher 大小写Bash不是bash最后确认文件路径。用/hooks命令能看到注册列表是最快的确认方式。脚本执行失败。最常见的是没有执行权限chmod x解决。其次是路径问题脚本里引用其它文件时用绝对路径或者用$CODEBUDDY_PROJECT_DIR、$CLAUDE_PROJECT_DIR这类环境变量。Windows 用户确保脚本能在 Git Bash 里跑别用 PowerShell 语法写 bash 脚本。JSON 语法错误。这个最隐蔽因为工具可能不报错只是静默忽略你的配置。用编辑器的 JSON 校验功能或者jq . settings.json跑一下有语法错会直接报出来。常见错误多了一个逗号、少了一个引号、中文引号混进去了。把这张表存下来遇到报错先对照能省不少时间。6. 把 Key 配置和 Hook 逻辑分开管理跑通第一个 Hook 之后给你一个实用建议把 Key 配置和 Hook 逻辑彻底分开。具体做法是settings.json里只放 Hook 的 matcher 和脚本路径所有复杂逻辑都放脚本文件。Key 配置单独用一个文件或环境变量管理不要和 Hook 配置混在一起。这样带来的好处是换 Key 的时候不用碰 Hook 配置改 Hook 逻辑的时候不用担心影响模型接入。如果你要在多个项目里复用同一套 Hook把脚本放到用户级目录~/.claude/hooks/或~/.codebuddy/hooks/然后在各个项目的settings.json里引用绝对路径。项目特定的 Hook 才放项目级目录。另外脚本里尽量用环境变量而不是硬编码路径。Claude Code 提供$CLAUDE_PROJECT_DIRCodeBuddy 提供$CODEBUDDY_PROJECT_DIR用它们引用项目根目录脚本就能跨项目复用。最后Hook 脚本建议加日志。在脚本开头加一行echo $(date) - Hook triggered /tmp/hook.log出问题时翻日志比看 debug 输出还快。这个习惯在 Hook 数量多起来之后尤其有用。到这里你的第一个 Hook 应该已经稳定运行了。下一步可以尝试PostToolUse做自动格式化或者SessionStart做上下文注入思路和这一篇完全一样——配置、触发、验证、排障四步走。
返回列表