news 2026/10/24 3:43:58

在 Claude Code 中注入 Hook 附加上下文:system-reminder-hook-additional-context 模板与 Hooks 反馈通道实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Claude Code 中注入 Hook 附加上下文:system-reminder-hook-additional-context 模板与 Hooks 反馈通道实战解析
  • 文档
  • 提示工程
  • 人工智能

【免费下载链接】claude-code-system-prompts

All parts of Claude Code's system prompt, 27 builtin tool descriptions, sub agent prompts (Plan/Explore/Task), utility prompts (CLAUDE.md, compact, statusline, magic docs, WebFetch, Bash cmd, security review, agent creation). Updated for each Claude Code version.

项目地址:https://gitcode.com/gh_mirrors/cl/claude-code-system-prompts
点击查看免费下载

本文以开源仓库 claude-code-system-prompts 中的 system-prompts/system-reminder-hook-additional-context.md 为骨架,结合同目录下的 system-prompt-hooks-configuration.md 完整配置文档,剖析 Claude Code Hooks 系统中"附加上下文注入"这一核心机制:Hook 如何通过 JSON 输出把additionalContext写回模型上下文、系统提醒模板如何渲染多行内容,以及四类 Hook 反馈提醒(成功、附加上下文、阻塞错误、停止续写)如何协同工作。读完本文,你将掌握 Hook 的标准 JSON 输出协议、hookSpecificOutput的完整字段用法,并能直接写出可运行的注入上下文与权限决策 Hook 配置。

一、背景:Claude Code Hooks 在生命周期中的位置

Hooks 是 Claude Code 在自身生命周期关键节点上执行外部命令、注入或拦截行为的机制。正如 system-prompt-hooks-configuration.md 所定义的:"Hooks run commands at specific points in Claude Code's lifecycle."(Hooks 在 Claude Code 生命周期的特定节点运行命令)。

一个完整的 Hook 配置在.claude/settings.json(或对应作用域的 settings 文件)中呈现为嵌套 JSON 结构,其标准骨架如下:

{ "hooks": { "EVENT_NAME": [ { "matcher": "ToolName|OtherTool", "hooks": [ { "type": "command", "command": "your-command-here", "timeout": 60, "statusMessage": "Running..." } ] } ] } }

其中EVENT_NAME决定 Hook 在生命周期的哪个时点触发,matcher用于筛选具体关联的工具,hooks数组内可以并列多个具体 Hook 定义。当前仓库支持的 Hook 事件及对应 matcher 如下表(来源于 system-prompt-hooks-configuration.md):

事件Matcher用途
PermissionRequest工具名在权限提示之前运行
PreToolUse工具名在工具调用之前运行,可阻断
PostToolUse工具名在工具成功调用之后运行
PostToolUseFailure工具名在工具调用失败之后运行
Notification通知类型在通知发生时运行
Stop-在 Claude 停止时运行(含 clear、resume、compact)
PreCompact"manual"/"auto"在上下文压缩之前运行
PostCompact"manual"/"auto"在上下文压缩之后运行(接收摘要)
UserPromptSubmit-在用户提交提示时运行
SessionStart-在会话启动时运行

常用的工具 matcher 包括Bash、Write、Edit、Read、Glob、Grep,多个工具可用|分隔匹配。

Hook 有三种类型(仅工具类事件 PreToolUse / PostToolUse / PermissionRequest 支持全部三种):

  1. Command Hook——运行一条 shell 命令:
    { "type": "command", "command": "prettier --write $FILE", "timeout": 30 }
  2. Prompt Hook——让 LLM 评估条件:
    { "type": "prompt", "prompt": "Is this safe? $ARGUMENTS" }
  3. Agent Hook——让带工具的 Agent 执行任务:
    { "type": "agent", "prompt": "Verify tests pass: $ARGUMENTS" }

Hook 运行时会通过 stdin 收到一份 JSON 输入,其中包含session_id、tool_name、tool_input,以及仅 PostToolUse 事件才有的tool_response:

{ "session_id": "abc123", "tool_name": "Write", "tool_input": { "file_path": "/path/to/file.txt", "content": "..." }, "tool_response": { "success": true } }

二、Hook 输出协议:additionalContext 从何而来

Hook 命令除了向 stdout 输出普通文本外,还可以输出一段 JSON 来控制 Claude Code 的行为。这段 JSON 是 Hook 与主进程之间唯一的"结构化反馈通道",其完整字段定义(来自 system-prompt-hooks-configuration.md):

{ "systemMessage": "Warning shown to user in UI", "continue": false, "stopReason": "Message shown when blocking", "suppressOutput": false, "decision": "block", "reason": "Explanation for decision", "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "Context injected back to model" } }

各字段的作用:

  • systemMessage—— 向用户界面显示一条消息(所有 Hook 通用)。
  • continue—— 设为false可阻断/停止(默认true)。
  • stopReason—— 当continue为false时向用户展示的消息。
  • suppressOutput—— 隐藏 stdout 使其不进入会话记录(默认false)。
  • decision—— 对 PostToolUse / Stop / UserPromptSubmit Hook 可设为"block"(PreToolUse 已弃用此字段,改用hookSpecificOutput.permissionDecision)。
  • reason—— 对决策的解释说明。
  • hookSpecificOutput—— 事件专属输出,必须包含hookEventName字段:
    • additionalContext—— 注入模型上下文的文本;
    • permissionDecision——"allow"、"deny"或"ask"(仅 PreToolUse);
    • permissionDecisionReason—— 权限决策的原因(仅 PreToolUse);
    • updatedInput—— 修改后的工具输入(仅 PreToolUse)。

可以看到,hookSpecificOutput.additionalContext就是"Hook 附加上下文"这一机制的数据来源:Hook 在 JSON 输出中声明一段文本,Claude Code 主进程便将其作为附加上下文交还给模型。而 system-reminder-hook-additional-context.md 正是这段上下文在系统层渲染为"系统提醒"的模板。

三、模板逐行解剖:system-reminder-hook-additional-context 的结构

本仓库的 system-reminder-hook-additional-context.md 全文如下:

<!-- name: "System Reminder: Hook additional context" description: "Additional context from a hook" ccVersion: "2.1.18" variables: - "ATTACHMENT_OBJECT" --> ${ATTACHMENT_OBJECT.hookName} hook additional context: ${ATTACHMENT_OBJECT.content.join(` `)}

这是一个带元数据的模板文件,其结构可以拆解为三个部分:

1. 元数据头(HTML 注释块)

与仓库中其它 system-reminder / system-prompt 模板一致,该文件头部是一个<!-- ... -->注释,声明了:

  • name—— 模板的逻辑名称"System Reminder: Hook additional context",用于日志与内部识别;
  • description—— 一句话说明"Additional context from a hook"(来自 Hook 的附加上下文);
  • ccVersion—— 引入该模板的 Claude Code 版本"2.1.18";
  • variables—— 该模板依赖的注入变量列表,这里只有一项"ATTACHMENT_OBJECT"。

2. 模板正文(渲染表达式)

正文只有一行渲染表达式:

${ATTACHMENT_OBJECT.hookName} hook additional context: ${ATTACHMENT_OBJECT.content.join(` `)}

它的语义是:

  • 从注入变量ATTACHMENT_OBJECT中取出hookName字段,作为提醒的前缀(例如PostToolUse、PreToolUse等事件名,或用户自定义的 Hook 名称);
  • 取出content字段——这是一个字符串数组,每一行/每一段都是 hook 返回的附加上下文内容;
  • 调用content.join("\n")将这些数组元素按换行符连接成一个多行文本,拼接在hook additional context:之后。

也就是说,模板的最终渲染形态为:

<HookName> hook additional context: <第 1 行附加上下文> <第 2 行附加上下文> <第 3 行附加上下文>

3.ATTACHMENT_OBJECT变量的来源

ATTACHMENT_OBJECT是仓库内多个系统提醒模板共享的注入变量类型。同样声明该变量的模板还包括:

  • system-reminder-hook-success.md(Hook 成功消息);
  • system-reminder-hook-stopped-continuation.md(Hook 停止续写);
  • system-reminder-hook-blocking-error.md(阻塞型 Hook 命令报错);
  • system-reminder-token-usage.md(Token 用量);
  • system-reminder-usd-budget.md(USD 预算);
  • system-reminder-lines-selected-in-ide.md(IDE 选中行);
  • system-reminder-compact-file-reference.md(压缩前的文件引用);
  • system-reminder-plan-file-reference.md(计划文件引用)等。

从这些模板的用法可以推断:ATTACHMENT_OBJECT是 Claude Code 主进程在运行时把"某类事件产生的结构化附件"整体注入模板的载体对象,其具体字段随模板语义不同而不同。对本模板而言,该对象被要求至少携带hookName: string与content: string[]两个字段。

四、渲染实例:从 additionalContext 到模型可见文本

结合第二节的 JSON 输出协议,我们构造一个真实的运行示例。假设.claude/settings.json中配置了一个 PostToolUse Hook,用jq从 stdin JSON 中提取被 Write 的文件路径,并回注一段建议性上下文:

{ "hooks": { "PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; echo \"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"File was just modified: $f. Consider running lint.\"}}"; }" }] }] } }

当该 Hook 触发并输出上述 JSON 后,Claude Code 主进程会把hookSpecificOutput.additionalContext的值组装进ATTACHMENT_OBJECT.content数组,交由 system-reminder-hook-additional-context.md 渲染。若 Hook 返回的是多段内容(数组),例如:

{ "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "First observation: build passed.\nSecond observation: 3 warnings emitted." } }

渲染进模型上下文后即为(hookName为PostToolUse):

PostToolUse hook additional context: First observation: build passed. Second observation: 3 warnings emitted.

这段文本以系统提醒的身份出现在模型上下文中,模型随后即可基于它调整后续行为。这正是"Hook 附加上下文"机制的核心价值:让外部命令的观测结果、格式化输出、测试结论等,成为模型决策时可感知的事实输入,而不是仅仅停留在终端 stdout 上。

五、四类 Hook 反馈提醒:一条完整的反馈通道

hook additional context并不是 Hook 唯一的反馈形态。仓库中同一族模板构成了完整的"Hook → 主进程 → 模型/用户"反馈通道,理解了它们的差异才能正确设计 Hook 输出:

模板文件渲染格式触发语义
system-reminder-hook-success.md${hookName} hook success: ${content}Hook 命令成功结束,回传一段成功消息
system-reminder-hook-additional-context.md${hookName} hook additional context: ${content.join("\n")}Hook 通过 JSON 输出回注附加上下文(多行)
system-reminder-hook-stopped-continuation.md${hookName} hook stopped continuation: ${message}Hook 请求停止当前续写流程(如continue: false),附带停止原因
system-reminder-hook-blocking-error.md${hookName} hook blocking error from command: "${command}": ${error}阻塞型 Hook 命令执行失败,暴露具体命令与错误信息

其中,hook stopped continuation还有配套的前缀模板 system-reminder-hook-stopped-continuation-prefix.md,其内容为常量文本hook stopped continuation:,用于组合拼接消息。

这四类提醒回答了同一个 Hook 在不同结局下的模型侧呈现:成功时告知结果、有观测时注入上下文、被阻断时给出原因、命令崩溃时报出错误。而本篇文章的主角——additional context——是其中最"有建设性"的一类,因为它不是中断或告警,而是主动向模型提供更多决策依据。

六、实战:可复制的完整 Hook 配置示例

以下示例完整继承自 system-prompt-hooks-configuration.md,均围绕"输出附加上下文 / 控制行为"设计,可直接放入 settings.json 的hooks字段中。

示例 1:写入后自动格式化(回注已格式化文件)

{ "hooks": { "PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; prettier --write \"$f\"; } 2>/dev/null || true" }] }] } }

示例 2:记录所有 Bash 命令到日志

{ "hooks": { "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "jq -r '.tool_input.command' >> ~/.claude/bash-log.txt" }] }] } }

示例 3:Stop Hook 向用户显示消息

Stop Hook 必须输出带systemMessage字段的 JSON 才会被展示给用户:

# 输出: {"systemMessage": "Session complete!"} echo '{"systemMessage": "Session complete!"}'

示例 4:代码变更后自动跑测试

{ "hooks": { "PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path // .tool_response.filePath' | grep -E '\\.(ts|js)$' && npm test || true" }] }] } }

示例 5:向模型回注多行附加上下文(本文主题的落地形态)

{ "hooks": { "PostToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "jq -r '.tool_input.command' > /tmp/last_cmd.txt; if grep -qE 'npm test|pytest' /tmp/last_cmd.txt; then echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUse\",\"additionalContext\":\"A test command just ran.\\nIf it passed, consider committing.\\nIf it failed, inspect the first error trace.\"}}'; fi" }] }] } }

执行流程为:Bash 工具调用完成后 → Hook 检查命令是否为测试命令 → 是则输出 JSON,声明hookEventName: PostToolUse与多行additionalContext→ 主进程将其拆为数组并经本模板渲染成Bash hook additional context: ...注入上下文 → 模型据此决定是否提交、如何排查。

七、设计与注意事项

从模板实现与配置文档中可以总结出以下关键约束:

  1. hookSpecificOutput必须带hookEventName:配置文档明确要求该字段必须包含hookEventName,否则事件专属输出无法被正确路由,additionalContext也就不会进入本模板的渲染路径。

  2. content是数组、多行靠join("\n"):模板用ATTACHMENT_OBJECT.content.join("\n")把多段内容拼为多行文本,说明主进程会先把additionalContext按行拆分(或本身以数组传递),模板层负责拼接。这意味着你可以在additionalContext中直接使用换行符组织多条观测结论。

  3. 附加上下文是"注入"而非"展示":与systemMessage(面向 UI 用户)不同,additionalContext的目标是模型上下文,因此措辞应面向模型——给出结论、事实与建议动作,而非面向终端用户的通知文案。

  4. 事件与字段的可用范围:permissionDecision/permissionDecisionReason/updatedInput仅 PreToolUse 可用;decision: "block"仅 PostToolUse / Stop / UserPromptSubmit 可用;additionalContext则面向模型注入,适用范围最广。设计 Hook 输出时应按事件类型选择合法字段组合。

  5. ccVersion 标识:本模板标注的 ccVersion 为2.1.18,与仓库中其余 Hook 族模板(hook-success、hook-stopped-continuation、hook-blocking-error 均为2.1.18)一致,表明这一组反馈模板在 2.1.18 版本中已定型;若你使用的 Claude Code 版本早于此,相关行为可能有所不同。

八、结语

system-reminder-hook-additional-context虽然只是仓库中一行渲染表达式,但它背后是一整套设计严谨的 Hook 反馈协议:Hook 通过 stdout JSON 输出hookSpecificOutput.additionalContext,主进程将其承载进ATTACHMENT_OBJECT,再由本模板以<hookName> hook additional context:前缀 + 多行join的方式注入模型上下文。理解这条链路后,你便可以在实际项目中构建"命令观测 → 上下文注入 → 模型自适应"的闭环工作流,例如自动格式化、测试结果回注、变更摘要上报等场景。更完整的字段定义、事件表与更多示例,可继续阅读 system-prompt-hooks-configuration.md,以及同目录下的 hook-success、hook-stopped-continuation、hook-blocking-error 三个配套模板。

  • 文档
  • 提示工程
  • 人工智能

【免费下载链接】claude-code-system-prompts

All parts of Claude Code's system prompt, 27 builtin tool descriptions, sub agent prompts (Plan/Explore/Task), utility prompts (CLAUDE.md, compact, statusline, magic docs, WebFetch, Bash cmd, security review, agent creation). Updated for each Claude Code version.

项目地址:https://gitcode.com/gh_mirrors/cl/claude-code-system-prompts
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 3:59:10

C++安全编程实战:从内存管理到并发防御的完整指南

写C安全编程相关的文章&#xff0c;网上已经很多&#xff0c;但大多要么站在概念定义的角度泛泛而谈&#xff0c;要么直接甩一份规条清单让你背。我自己出来做事这些年&#xff0c;最深的体会是&#xff1a;很多人写C时根本没意识到自己正在踩坑&#xff0c;直到线上崩溃、用户…

作者头像 李华
网站建设 2026/10/24 3:58:40

MIT 6.005 软件构建讲义(七)

parsePitch : String → Pitch (MusicLanguage.java:77) 通过解析 pitch 语法产生来返回一个 Pitch。你应该能够理解递归 — 基本情况是什么&#xff1f;递归情况是什么&#xff1f; 阅读练习 parsePitch parsePitch 的基本情况处理这些输入中的哪些&#xff1f; &#xff…

作者头像 李华
网站建设 2026/10/16 6:45:11

循环队列实现与面试全攻略:从环形数组到边界处理

如果你在准备面试&#xff0c;拿到“循环队列怎么实现”这道题&#xff0c;恭喜你&#xff0c;这是一道性价比极高的常考题——前提是你真把它想明白了。我第一次在美团一面碰到这题时&#xff0c;第一反应是“教科书上的数组队列改一改就完事”&#xff0c;结果在“队空和队满…

作者头像 李华
网站建设 2026/10/14 21:19:31

dll缺失修复全攻略:避开全家桶陷阱,官方工具与实操步骤详解

你用着正欢的软件突然弹窗“由于找不到 xxx.dll&#xff0c;无法继续执行代码”&#xff0c;或者游戏启动时提示“缺少 d3dcompiler_47.dll”&#xff0c;大概率会先一愣&#xff1a;dll 是个啥&#xff1f;为啥会缺&#xff1f;更烦人的是百度一搜“dll修复工具”&#xff0c;…

作者头像 李华
网站建设 2026/10/19 17:23:13

Python程序员必会的Linux命令实战:从部署到排查

我认识的大部分Python程序员&#xff0c;真正开始啃Linux命令往往是被一次线上事故逼出来的。本地跑得好好的脚本&#xff0c;一上服务器就报ModuleNotFoundError&#xff1b;代码部署完进程找不到踪影&#xff1b;端口被占用了翻遍日志也没头绪。这时候才会意识到&#xff0c;…

作者头像 李华