← 所有文章

Claude Code Hooks 详解:围绕 Agent 的确定性层

来自指南: Claude Code Comprehensive Guide

什么是 Claude Code hooks? Hooks 是用户自定义的 shell 命令(外加 HTTP 端点、MCP 工具和模型提示词),由 Claude Code 在其生命周期的固定节点自动执行:工具调用之前、编辑之后、会话启动时、Claude 结束响应时。1 CLAUDE.md 给模型的是它大概率会遵循的指令,而 hooks 无论模型是否配合都会执行。在任意会话中输入 /hooks,即可查看每个生命周期事件以及挂载在其上的内容。 {.answer-block}

大多数开发者运行 Claude Code 时依赖两层控制:权限限定 agent 可以做什么,CLAUDE.md 描述它应该做什么。Hooks 是第三层,也是唯一能提供保证的一层。下文包括:心智模型、当前文档中的全部生命周期事件、精确的输入/输出契约、配置方式、五个可用的模式,以及一个决策框架。所有 API 细节均已对照官方 hooks 参考文档和指南核实(截至 2026 年 7 月 1 日)——这套系统迭代很快,如果本文与参考文档有出入,以参考文档为准。(刚接触 Claude Code?不妨从 5 分钟上手Claude Code 新手路径开始。)

TL;DR: Hooks 从 stdin 接收 JSON,并通过退出码或 stdout 上的 JSON 作出应答。退出码 0 表示放行,退出码 2 表示阻止(仅对支持阻止的事件有效),而退出码 1——Unix 惯例中的失败码——什么都不会阻止,这是 hooks 最大的一个坑。2settings.json 中以 PreToolUseStop 等事件名进行配置,并用 matcher 过滤。凡是必须每次都发生的事情用 hooks;模型只需知道的事情用 CLAUDE.md。

心智模型:非确定性内核之外的确定性保证

编码 agent 是一个概率系统。让它每次编辑后运行 Prettier,它会照做——大多数时候。当改动看起来微不足道、上下文过长,或者您的措辞恰好换了个说法时,它可能就跳过这一步。CLAUDE.md、技能(skills)和提示词都只是建议:质量很高,通常会被遵循,但从无保证。

Hooks 就是包裹这个内核的确定性外壳。官方定义是:”用户自定义的 shell 命令、HTTP 端点或 LLM 提示词,在 Claude Code 生命周期的特定节点自动执行”,从而提供”对 Claude Code 行为的确定性控制,确保某些操作始终发生,而不是依赖 LLM 自己选择是否运行”。3 格式化器在每次编辑后触发。命令守卫评估每一次 Bash 调用。完成门控检查每一次收尾。

这种强制力是真实的,而非装饰性的:PreToolUse hooks 在任何权限模式检查之前触发,因此返回 permissionDecision: "deny" 的 hook 即使在 bypassPermissions 模式下或使用 --dangerously-skip-permissions 时也能阻止该工具。反过来则不成立——返回 "allow" 的 hook 无法放宽 settings 中的 deny 规则。Hooks 可以把策略收得比权限更紧,但永远不能放松它。4

生命周期:全部 hook 事件

截至 2026 年 7 月 1 日,参考文档共记录了 30 个 hook 事件1 它们按三种节奏划分:每会话一次(SessionStartSessionEnd)、每轮对话一次(UserPromptSubmitStopStopFailure),以及 agentic 循环内的每次工具调用(PreToolUsePostToolUse)。其余事件在特定条件下触发——配置变更、上下文压缩、子代理、MCP 交互。

事件 触发时机 一个实际用途
SessionStart 会话开始或恢复 将 git 分支和未关闭的 issue 注入为上下文
Setup --init-only,或 -p 模式下的 --init/--maintenance 在 agent 运行前于 CI 中安装依赖
UserPromptSubmit 您提交提示词后、Claude 处理之前 附加当前日期;拒绝包含机密信息的提示词
UserPromptExpansion 键入的命令展开为提示词时 审计或否决技能/命令的展开
PreToolUse 工具调用执行之前 阻止破坏性 shell 命令
PermissionRequest 权限对话框出现时 自动批准可信命令,免去人工确认
PermissionDenied 自动模式分类器拒绝工具调用时 返回 retry: true,允许模型重试
PostToolUse 工具调用成功之后 自动格式化每个被编辑的文件
PostToolUseFailure 工具调用失败之后 记录失败命令以便排查
PostToolBatch 一批并行工具调用结束后、下一次模型调用之前 为 agentic 循环设检查点或中止它
Notification Claude Code 发送通知时 Claude 需要输入时弹出桌面提醒
MessageDisplay 助手消息文本显示期间 屏幕显示脱敏(仅影响显示;会话记录不变)
SubagentStart 子代理被启动时 注入特定 agent 类型的上下文
SubagentStop 子代理完成时 在子代理输出返回前进行校验
TaskCreated 通过 TaskCreate 创建任务时 强制执行任务命名或范围规则
TaskCompleted 任务被标记为完成时 在完成生效前核验验收标准
Stop Claude 结束响应时 完成门控:测试通过前阻止收尾
StopFailure 对话轮因 API 错误而结束时 rate_limitbilling_error 发出警报(仅记录;输出被忽略)
TeammateIdle agent 团队成员即将进入空闲时 让团队成员持续处理队列中的工作
InstructionsLoaded CLAUDE.md 或 .claude/rules/*.md 文件加载进上下文时 记录哪些指令进入了会话
ConfigChange 会话中途配置文件发生变化时 阻止未经授权的设置修改
CwdChanged 工作目录变化时 重新加载 direnv 风格的环境
FileChanged 被监视的文件在磁盘上发生变化时 .env 变化时刷新环境变量
WorktreeCreate 通过 --worktreeisolation: "worktree" 创建 worktree 时 替换默认的 git worktree 供给流程
WorktreeRemove worktree 被移除时 在会话或子代理退出时执行自定义清理
PreCompact 上下文压缩之前 保存不容丢失的状态
PostCompact 压缩完成之后 重新注入关键上下文
Elicitation MCP 服务器请求用户输入时 在无头(headless)运行中自动填写表单
ElicitationResult 您回应 MCP elicitation 之后 在响应返回前校验或覆盖它
SessionEnd 会话终止时 归档日志、清理资源

其中大多数您都用不上。几乎所有生产环境的配置都由五个事件构成:PreToolUsePostToolUseUserPromptSubmitSessionStartStop。其余的留待需要的那天再用。

契约:JSON 进,退出码或 JSON 出

命令型 hooks 从 stdin 接收 JSON,并通过退出码、stdout 和 stderr 作出应答。(HTTP 型 hooks 以 POST 请求体的形式接收同样的 JSON,通过响应体应答。)2

每个事件都会传递一个通用信封——session_idtranscript_pathcwdhook_event_name,大多数事件还带有 permission_mode——外加事件特有的字段。针对 Bash 命令的 PreToolUse hook 会收到:

{
  "session_id": "abc123",
  "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",
  "cwd": "/home/user/my-project",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": { "command": "npm test" }
}

其他事件替换的是尾部字段:UserPromptSubmit 携带 promptSessionStart 携带 sourcestartup/resume/clear/compact),Stop 携带 stop_hook_activelast_assistant_message。在子代理内部触发的 hooks 还会额外收到 agent_idagent_type2

退出码

三种结果:2

  • 退出码 0——成功。Claude Code 会解析 stdout 中的 JSON 输出字段。对大多数事件而言,stdout 只进入调试日志;而对 UserPromptSubmitUserPromptExpansionSessionStart,纯文本 stdout 会作为 Claude 可见的上下文加入。
  • 退出码 2——阻止性错误。stdout(包括其中的任何 JSON)会被忽略;stderr 作为错误消息反馈给 Claude。”阻止”的具体含义取决于事件。
  • 其他任何退出码——非阻止性错误。会话记录中会显示 <hook name> hook error 提示,执行继续。

最后这一条值得加粗:退出码 1 不会阻止任何东西。 文档对此有直接警告——尽管 1 是 Unix 惯例中的失败码,Claude Code 仍将退出码 1 视为非阻止性错误并继续执行。策略类 hooks 必须 exit 22

退出码 2 在各事件上的效果:2

事件 退出码 2 的效果
PreToolUse 阻止该工具调用
PermissionRequest 拒绝该权限
UserPromptSubmit 阻止处理并清除该提示词
UserPromptExpansion 阻止展开
Stop / SubagentStop 阻止停止;对话继续
TeammateIdle 阻止该团队成员进入空闲
TaskCreated / TaskCompleted 回滚创建/阻止完成
ConfigChange 阻止配置变更(policy_settings 除外)
PreCompact 阻止压缩
PostToolBatch 在下一次模型调用前停止 agentic 循环
Elicitation / ElicitationResult 拒绝该 elicitation/将响应转为拒绝
WorktreeCreate 任何非零退出码都会中止 worktree 创建

其余事件都无法阻止。PostToolUsePostToolUseFailure 会把 stderr 展示给 Claude(工具已经运行过了);SessionStartNotificationSessionEndCwdChangedFileChangedPostCompactSubagentStartSetup 只把 stderr 展示给用户;StopFailureInstructionsLoadedMessageDisplayPermissionDenied 会忽略退出码——对 PermissionDenied 而言,唯一的控制手段是 JSON 的 retry: true2

JSON 输出

如果需要比”阻止或沉默”更精细的控制,可以以退出码 0 结束并向 stdout 打印一个 JSON 对象。先记住一条规则:退出码和 JSON 二选一,绝不同时用——JSON 只在退出码为 0 时被处理,退出码 2 会将其丢弃。5

通用字段对每个事件都有效:continue: false 让 Claude 完全停止(stopReason 会展示给用户),suppressOutput 在会话记录中隐藏 stdout,systemMessage 向用户显示一条警告,terminalSequence 发出一个在允许列表内的终端转义序列(桌面通知、窗口标题、响铃)。决策字段则因事件而异:5

事件 决策模式 关键字段
UserPromptSubmitUserPromptExpansionPostToolUsePostToolUseFailurePostToolBatchStopSubagentStopConfigChangePreCompact 顶层 decision decision: "block" + reason(展示给 Claude)。省略 decision 即为放行
PreToolUse hookSpecificOutput permissionDecision"allow" | "deny" | "ask" | "defer",外加 permissionDecisionReason,以及在执行前重写工具参数的 updatedInput
PermissionRequest hookSpecificOutput decision.behavior"allow" | "deny",可选 decision.updatedInput
PermissionDenied hookSpecificOutput retry: true 告知模型可以重试
PostToolUse hookSpecificOutput updatedToolOutput 替换工具结果
Stop / SubagentStop hookSpecificOutput additionalContext:非错误反馈,让对话继续而不计为 hook 错误
SessionStartSetupSubagentStart 仅上下文 additionalContext,外加 SessionStart 独有的 initialUserMessagesessionTitlewatchPathsreloadSkills。不可阻止
MessageDisplay hookSpecificOutput displayContent 仅替换屏幕上显示的文本
Elicitation / ElicitationResult hookSpecificOutput action"accept" | "decline" | "cancel",外加 content
WorktreeRemoveNotificationSessionEndPostCompactInstructionsLoadedStopFailureCwdChangedFileChanged 仅用于副作用

有两个细节常让人栽跟头。第一,PreToolUse 是顶层 decision 模式的例外:它在历史上曾使用顶层 decision/reason,但这两个字段对此事件已被弃用("approve"/"block" 分别映射到 "allow"/"deny");请改用 hookSpecificOutput.permissionDecision5 第二,当多个 PreToolUse hooks 意见不一致时,优先级为 deny > defer > ask > allow5

配置:settings.json、matcher 与作用域

Hook 配置嵌套三层:选择一个事件,添加一个 matcher 组来过滤触发时机,再定义一个或多个要运行的 hook 处理器6

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "/path/to/lint-check.sh" }
        ]
      }
    ]
  }
}

放置位置决定作用域:~/.claude/settings.json 适用于您的所有项目,.claude/settings.json 为项目级且可提交到版本库,.claude/settings.local.json 为项目级且被 gitignore 忽略,同时适用标准的设置优先级——托管策略高于 local,local 高于项目,项目高于用户。9 Hooks 还可以随插件(hooks/hooks.json)以及技能或 agent 的 frontmatter 一起分发,企业管理员还能强制启用用户无法覆盖的托管 hooks。6

Matcher 按其字符内容求值:"*""" 或省略 matcher 会匹配一切;只包含字母、数字、_-、空格、逗号和 | 的值是精确字符串或列表(BashEdit|Write);其他任何值都会成为未锚定的 JavaScript 正则表达式,因此 Edit.* 会同时匹配 EditNotebookEdit——如果只想精确匹配一个工具,请用 ^Edit$ 加锚。Matcher 区分大小写,且每个事件按自己的字段匹配:工具事件按工具名,SessionStartsourceSubagentStart 按 agent 类型,Notification 按通知类型。6 若要在工具事件上做更精细的过滤,每个处理器的 if 字段接受一条权限规则,例如 "Bash(git *)"——但它是尽力而为的(遇到无法解析的命令时会放行),所以硬性保证请使用权限规则而不是 if6

处理器共有五种类型:command(shell)、http(POST 端点)、mcp_toolprompt(单轮模型评估)和 agent(拥有 Read/Grep/Glob 访问权限的子代理;实验性)。默认超时:command/http/mcp_tool 为 600 秒(UserPromptSubmit 降至 30 秒、MessageDisplay 降至 10 秒),prompt 为 30 秒,agent 为 60 秒——可通过 timeout 按 hook 单独覆盖。6 所有匹配的 hooks 并行运行,完全相同的处理器会被去重,$CLAUDE_PROJECT_DIR 会把脚本指向项目根目录。

/hooks 验证:这是一个只读浏览器,显示每个事件、其已配置的 hooks,以及各自来自哪个设置文件。要修改任何内容,请编辑 JSON(或让 Claude 来改)。要临时关闭全部 hooks,设置 "disableAllHooks": true6

五个模式

以下模式经过通用化处理,保持最小实现。hooks 教程为其中几个构建了更完整的生产版本,Hooks 在 Apple 开发中的应用则将它们应用到 iOS 工具链。

1. 编辑后自动格式化(PostToolUse)

直接取自官方指南——Claude 碰过的每个文件都会被格式化,无一例外:3

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }
        ]
      }
    ]
  }
}

按技术栈需要,将命令换成 ruff formatgofmtswiftformat

2. 阻止危险命令(PreToolUse,退出码 2)

#!/bin/bash
# .claude/hooks/guard-bash.sh — register on PreToolUse, matcher "Bash"
command=$(jq -r '.tool_input.command // empty')
case "$command" in
  *"rm -rf"* | *"git push --force"* | *"DROP TABLE"*)
    echo "Blocked: matches a destructive pattern. Propose a safer alternative." >&2
    exit 2 ;;
esac
exit 0

退出码 2 会阻止该调用并把 stderr 反馈给 Claude,Claude 由此调整方向,而不是盲目重试。等价的 JSON 写法——带原因的 permissionDecision: "deny"——效果相同,并留有升级空间:"ask"(上报给人类)或 updatedInput(重写命令)。5

3. 会话启动时注入上下文(SessionStart)

SessionStart hook 的纯文本 stdout 会成为 Claude 可见的上下文——无需 JSON:1

#!/bin/bash
# .claude/hooks/session-context.sh — register on SessionStart
echo "Current branch: $(git branch --show-current)"
echo "Recent commits:"
git log --oneline -5
echo "Uncommitted files: $(git status --porcelain | wc -l | tr -d ' ')"
exit 0

此模式用于动态状态。静态约定应放在 CLAUDE.md 中——官方文档本身也建议,不需要脚本的上下文放在那里。1

4. Stop 上的完成门控

Stop 在 Claude 结束响应时触发。阻止它会迫使 agent 持续工作,直到条件满足:

#!/bin/bash
# .claude/hooks/stop-gate.sh — register on Stop
input=$(cat)
if [ "$(echo "$input" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0  # already continuing because of this hook; don't loop forever
fi
if ! npm test --silent > /tmp/stop-gate.log 2>&1; then
  jq -n '{decision: "block", reason: "Tests are failing. Fix them before finishing. Log: /tmp/stop-gate.log"}'
fi
exit 0

stop_hook_active 检查很重要:Claude Code 对 Stop hook 设有连续 8 次阻止的硬上限,一个从不检查自己是否已触发续跑的门控会径直烧穿这个额度。7 若想要更温和的引导,可返回 hookSpecificOutput.additionalContext 而非 decision: "block"——续跑效果相同,但被标记为反馈而不是 hook 错误。对于一次性条件,内置的 /goal 命令就是一个会话级、基于提示词的 Stop hook,零配置。1

5. 调度器:一个入口,多个小 hooks

注册十个 hooks 意味着 settings.json 里有十个条目,会在不同机器和项目之间逐渐失去同步。替代方案:每个事件只注册一个调度器,按约定路由。

#!/bin/bash
# .claude/hooks/dispatch.sh — register once per event you care about
input=$(cat)
event=$(echo "$input" | jq -r '.hook_event_name')
dir="$CLAUDE_PROJECT_DIR/.claude/hooks/$event"
[ -d "$dir" ] || exit 0
for hook in "$dir"/*.sh; do
  [ -x "$hook" ] || continue
  echo "$input" | "$hook" || exit $?
done
exit 0

现在,新增一个守卫就是在 .claude/hooks/PreToolUse/ 下对新文件执行 chmod +x——settings.json 从不改动,每个脚本都小到可以独立测试,且第一个退出码 2 会向上传播。一点注意事项:调度器把 Claude Code 本会并行运行的内容串行化了,它最适合退出码型 hooks——输出 JSON 的 hook 应保持独立注册,因为 stdout 必须恰好包含一个 JSON 对象。5

Hook、CLAUDE.md、技能与记忆的取舍

四种机制,各司其职:

机制 职责 选择规则
Hook 强制执行 如果它必须不可能被跳过——格式化、安全、门控——那就是 hook
CLAUDE.md 指导 如果它是模型每个会话都应知道的约定——技术栈、风格、命令——那就是 CLAUDE.md
技能 能力 如果它是带有自身指令和脚本、在相关时才被调用的流程,那就是技能
记忆 回忆 如果它是在某次会话中学到、未来会话需要的事实,那就是记忆

失误在两个方向上都会发生。把约定编码成 hooks,换来的是一堆脆弱的脚本,去强制执行一句指导语就能搞定的事。把策略写成 CLAUDE.md 的散文,换来的是 agent 在最要命的那天把 main 分支强制推送掉。判断标准:模型忽略这条规则一次的代价是什么?恼人 → CLAUDE.md。事故 → hook。

Hooks 做不到的事

如实列出限制,全部来自官方文档:7

  • Hooks 无法调用工具或斜杠命令。 命令型 hooks 只会通过 stdout、stderr 和退出码表达——仅此而已。通过 additionalContext 返回的上下文会以纯文本形式注入。
  • PostToolUse 无法撤销。 工具已经运行完了。预防要放在 PreToolUse 里。
  • Stop 在每次响应结束时都会触发,而不仅在”任务完成”时,且从不在用户打断时触发(API 错误触发的是 StopFailure)。门控逻辑必须容忍任务中途的停止。
  • PermissionRequest 在无头(-p)模式下不会触发。 自动化权限决策请使用 PreToolUse
  • PreToolUse 看不到通过 @ 引用的文件。 在提示词中用 @ 拉入的文件不涉及工具调用;要防住这条路径,请用 Read deny 规则保护相关路径。1
  • 并行的 updatedInput 是非确定性的。 当多个 PreToolUse hooks 重写同一个工具的参数时,最后完成的那个获胜。每类重写只让一个 hook 负责。
  • 超时会取消该 hook。 命令型 hooks 默认 600 秒(UserPromptSubmit 为 30 秒,MessageDisplay 为 10 秒);一个因超时被取消的慢门控,等于没有运行的门控。
  • 输出上限为 10,000 个字符——超出部分会被写入文件,并以预览替代。
  • Hooks 以您的完整用户权限运行。 参考文档自己的警告:它们”可以修改、删除或访问您的用户账户能访问的任何文件。在将 hook 命令加入配置之前,请审查并测试所有命令”。8 给变量加引号、使用绝对路径、避开敏感文件。
  • 一个坏掉的 hook 会拖累每一个会话,直到被修复。调试可用会话记录视图(Ctrl+O)、claude --debug-file /tmp/claude.log,或在会话中使用 /debug;一个经典的坑是 shell 配置文件在启动时输出内容,污染了 hook 的 JSON 输出。7

常见问题

什么是 Claude Code hooks?

Hooks 是用户自定义的命令——shell 脚本、HTTP 端点、MCP 工具或模型提示词——由 Claude Code 在特定生命周期节点自动执行。3 它们从 stdin 接收事件 JSON,并以退出码或 JSON 应答:阻止工具调用、注入上下文、重写参数、让 agent 继续工作。与 CLAUDE.md 指令不同,它们每次都会执行,与模型行为无关。

PreToolUse hooks 与权限有什么区别?

权限规则是声明式的:静态的 allow/deny/ask 模式,由 Claude Code 自行求值。PreToolUse hooks 是可编程的:由您的代码检查完整的工具输入并做出决定。Hooks 在权限模式检查之前触发,因此 hook 的 "deny" 即使在 bypassPermissions 模式下也依然生效——但 hook 的 "allow" 无法覆盖 settings 中的 deny 规则。4 凡是模式匹配能表达的,用权限规则;当决策需要逻辑、外部状态或输入重写时,才动用 hook。

Hooks 在无头(-p)模式下能用吗?

能——只有一个文档中注明的例外:PermissionRequest hooks 在非交互模式下不会触发,因此自动化权限决策应放在 PreToolUse 中。7 无头模式还解锁了一个交互式会话会忽略的选项:permissionDecision: "defer",它会暂停工具调用,让外层包装进程(Agent SDK 应用、自定义 UI)收集输入后再恢复会话。5

为什么我的 hook 运行了却什么都没阻止?

几乎总是违反了契约。退出码 1 不会阻止——只有退出码 2 会,而且仅对支持阻止的事件有效。2 JSON 决策只在退出码为 0 时被解析——打印 {"decision": "block"} 之后又以退出码 2 退出的脚本,其 JSON 会被丢弃。此外 matcher 区分大小写——bash 永远匹配不到 Bash。先用 /hooks 确认注册情况,再把示例 JSON 通过管道传给脚本并检查 echo $? 进行测试。7

来源

已于 2026 年 7 月 1 日对照官方文档核实。Hooks API 在 Claude Code v2.1.x 各版本间发生过实质性变化(新事件、新字段、matcher 语义),因此对版本敏感的细节请以”截至本文日期”来理解。

本站相关内容: Claude Code 指南的 hooks 章节提供包含 prompt 型与 agent 型 hooks 在内的全系统视角,hooks 教程提供五个带完整配置的生产级构建,Hooks 在 Apple 开发中的应用展示应用于 iOS 的实战模式;如果您还没安装 Claude Code,请从快速上手开始。


  1. Anthropic, “Hooks reference — Hook lifecycle and hook events.” code.claude.com/docs/en/hooks#hook-events 

  2. Anthropic, “Hooks reference — Hook input and output; exit code output; exit code 2 behavior per event.” code.claude.com/docs/en/hooks#exit-code-output 

  3. Anthropic, “Automate actions with hooks.” code.claude.com/docs/en/hooks-guide 

  4. Anthropic, “Hooks guide — Hooks and permission modes.” code.claude.com/docs/en/hooks-guide#hooks-and-permission-modes 

  5. Anthropic, “Hooks reference — JSON output and decision control.” code.claude.com/docs/en/hooks#json-output 

  6. Anthropic, “Hooks reference — Configuration: hook locations, matcher patterns, hook handler fields, the /hooks menu.” code.claude.com/docs/en/hooks#configuration 

  7. Anthropic, “Hooks guide — Limitations and troubleshooting.” code.claude.com/docs/en/hooks-guide#limitations-and-troubleshooting 

  8. Anthropic, “Hooks reference — Security considerations.” code.claude.com/docs/en/hooks#security-considerations 

  9. Anthropic, “Claude Code settings.” code.claude.com/docs/en/settings 

相关文章

Codex CLI 与 Claude Code 2026 年对比:架构、定价与中国访问

深度对比 Codex CLI 与 Claude Code:内核沙箱 vs 26 个钩子治理、Opus 4.7 vs GPT-5.4 基准测试、附人民币示例的按 token 定价,以及中国地区的云访问方案(Bedrock / Vertex /…

8 分钟阅读

Claude Code Hooks:我的95个钩子,每一个都有存在的理由

我为Claude Code构建了95个钩子。每一个的诞生,都源于某次出错的经历。本文讲述它们的起源故事,以及由此演化出的架构。

2 分钟阅读