☰
context-mode stdin JSON 协议详解:上下文优化 Hooks 与 17 个平台间的线协议完全指南
2026/10/14 18:46:29 网站建设 项目流程

context-mode stdin JSON 协议详解:上下文优化 Hooks 与 17 个平台间的线协议完全指南

【免费下载链接】context-modeContext window optimization for AI coding agents. Sandboxes tool output (98% reduction), persists session memory, and enforces routing across 17 platforms via MCP + hooks.项目地址: https://gitcode.com/GitHub_Trending/cl/context-mode

context-mode 是一款面向 AI 编程助手的上下文优化(context window optimization)MCP 插件:它通过沙箱化工具输出(最高 98% 上下文缩减)、持久化会话记忆,以及基于 MCP + Hooks 的强制路由,让 Claude Code、Cursor、Gemini CLI 等 17 个平台的 Agent 不再把原始字节塞进上下文窗口。本文带你读懂它最容易被忽视、却撑起整个架构的底层机制——Hooks 与宿主平台之间的 stdin JSON 线协议:数据怎么进、决策怎么出、跨平台差异如何抹平。

什么是 stdin JSON 线协议:先搞清楚这条"线"

很多 Hook 系统的本质是"事件订阅 + 进程管道"。当宿主平台(Claude Code、Cursor、Codex CLI……)即将执行某个工具调用时,它会fork 一个node X.mjs子进程,把事件载荷以 JSON 写入该进程的 stdin;Hook 进程读完后,再把一行 JSON 决策写回stdout,宿主据此决定放行、拦截、改写或注入上下文。

这条"stdin 进 / stdout 出"的通道就是 context-mode 的线协议(wire protocol)。全部 17 个平台适配层最终都收敛到同一套核心模块:

  • 读入侧:hooks/core/stdin.mjs(跨平台 stdin 读取器)
  • 解析侧:hooks/session-helpers.mjs(parseStdin/getSessionId/getInputProjectDir)
  • 决策侧:hooks/core/routing.mjs(归一化路由决策)
  • 输出侧:hooks/core/formatters.mjs(平台特化的 JSON 渲染)

事件类型在 hooks/hooks.json 中注册,共 6 类:PreToolUse、PostToolUse、UserPromptSubmit、PreCompact、SessionStart、Stop。

入站载荷:宿主推送了哪些字段

事件载荷的常见字段

各平台推送的 JSON 字段名并不统一,context-mode 用一套"多候选"解析策略兼容它们:

字段用途备注
tool_name/tool_input/tool_response工具名、入参、输出PostToolUse的核心素材
cwd/workspace_roots项目目录优先级最高的定位来源
session_id/sessionId/conversation_id/transcript_path会话标识多候选,按优先级回退
agent_id/agent_type子代理上下文标记用于关闭 MCP 重定向
mcp_servers/model/permission_mode会话设置快照SessionStart信封字段

会话 ID 的五级回退链

不同宿主对"当前会话是谁"的表达方式五花八门。hooks/session-helpers.mjs 中的getSessionId定义了明确的回退优先级:

  1. 从transcript_path文件名里正则提取 UUID(Claude Code 的 transcript 文件名即会话 ID)
  2. conversation_id(Antigravity CLI)
  3. sessionId(camelCase 写法)
  4. session_id(snake_case 写法)
  5. 平台专属环境变量(如CURSOR_SESSION_ID)
  6. 最终兜底:pid-<父进程PID>

项目目录同理——getInputProjectDir按input.cwd→input.workspace_roots[0]→ 平台环境变量(CLAUDE_PROJECT_DIR/CURSOR_CWD/VSCODE_CWD等)→process.cwd()的顺序回退(见 hooks/session-helpers.mjs)。每个平台对应一组"平台选项"(CLAUDE_OPTS、GEMINI_OPTS、CODEX_OPTS……),集中定义在 hooks/session-helpers.mjs。

出站决策:一个路由决策,四种动作

PreToolUse是最核心的拦截点。hooks/core/routing.mjs 定义了一套与平台无关的归一化决策对象:

{ action: "deny", reason: "..." } // 拦截并给出理由 { action: "ask" } // 请求用户确认 { action: "modify", updatedInput: {...} } // 改写工具入参 { action: "context", additionalContext: "..." } // 向模型注入引导 null // 直通,不做任何事

典型流程见 hooks/pretooluse.mjs:读 stdin →routePreToolUse()产出决策 →formatDecision()翻译成平台 JSON →stdout 写入是最后一步,进程随即退出,保证 Hook 延迟最小化。

平台差异如何被"格式化器"抹平

同一个决策,不同宿主只认不同的 JSON 形状。hooks/core/formatters.mjs 为 9 个 Hook 平台各写了一套渲染器,几个代表性差异:

平台deny 的形状特殊行为
Claude CodehookSpecificOutput.permissionDecisionBash 改写被宿主忽略,降级为带引导文案的 deny
Gemini CLI顶层{decision, reason}没有 "ask" 概念,直接返回 null
Cursor{permission, user_message}用agent_message注入上下文
CodexhookSpecificOutput旧版本不支持改写命令时fail closed:把重定向转成可执行的 deny
Kimi仅识别 denyask / modify / context 一律返回 null(宿主解析器只认 deny)

这种"能力探测 + 降级"策略是线协议的关键设计:宁可收窄表达,也不发出宿主会拒绝或忽略的形状,避免字节洪水守卫被静默绕过(见 hooks/core/formatters.mjs 中 codex 与 kimi 的实现注释)。

健壮性细节:超时、BOM 与崩溃兜底

stdin 空闲超时:四种结局

读 stdin 看似简单,实则踩过一堆跨平台坑。hooks/core/stdin.mjs 采用事件驱动的 flowing 模式(规避for await在 macOS 管道下的挂起、readFileSync(0)在 Windows 上的 EOF/EISDIR),并定义了带空闲超时(默认 1500ms,可用CONTEXT_MODE_HOOK_STDIN_IDLE_MS调整)的四种结局:

场景结局
EOF 且无数据返回空串,Hook 正常 no-op
EOF 且有数据返回缓冲区,并剥离 BOM(Cursor on Windows 会发 U+FEFF 前缀)
空闲且 0 字节返回空串——覆盖"宿主一直开着管道却不关"的场景
空闲但有部分字节抛错退出——宁可显式失败,也不让截断的 JSON 污染下游JSON.parse

崩溃兜底:Hook 永不返回非零

hooks/run-hook.mjs 是统一的"防弹外壳":所有 Hook 用await runHook(async () => {...})包裹,动态 import 业务模块,任何异常都被写入<configDir>/context-mode/hook-errors.log并以exit 0结束——因为宿主会把非零退出当作"每次工具调用都报错"展示给用户,形成告警轰炸。

跨 Hook 协作:tmpdir 标记文件

同一次工具调用前后是两个独立进程,它们通过临时目录里的标记文件"接力":PreToolUse 写入context-mode-rejected-<sessionId>.txt(被拒原因)和context-mode-redirect-<sessionId>.txt(被拦截的字节数,格式tool:type:bytesAvoided:summary),PostToolUse 读取后落库并删除(见 hooks/posttooluse.mjs)。这样ctx stats才能准确统计"每次重定向帮你省了多少字节"。

一图看懂:协议支撑起 17 个平台

核心文件速查表

  • 线协议总入口(事件注册):hooks/hooks.json
  • stdin 读取器(超时/BOM 语义):hooks/core/stdin.mjs
  • 载荷解析与会话/项目定位:hooks/session-helpers.mjs
  • 归一化路由决策:hooks/core/routing.mjs
  • 平台特化输出格式化:hooks/core/formatters.mjs
  • 崩溃兜底外壳:hooks/run-hook.mjs
  • 三个典型 Hook 实现:hooks/pretooluse.mjs、hooks/posttooluse.mjs、hooks/sessionstart.mjs
  • 平台适配层源码:src/adapters/(17 个平台各自的路径、Hook 注册与用量解析)

小结:为什么这条"线"值得你关注

  • 入站:宿主 fork 子进程并把事件 JSON 写入 stdin;context-mode 用多级回退从tool_name、session_id、cwd等字段中稳定提取会话与项目身份。
  • 出站:路由层只产出 4 种归一化决策(deny/ask/modify/context),格式化器负责把决策"翻译"成每个宿主只认的 JSON 形状,并对不支持的能力优雅降级。
  • 健壮性:空闲超时防挂起、BOM 剥离防解析崩溃、exit-0 外壳防告警轰炸、标记文件实现跨 Hook 协作——每一个设计背后都是一个真实世界的平台怪癖。

理解了这条 stdin JSON 线协议,你就理解了 context-mode 为什么能在 17 个行为各异的平台上保持同一套上下文优化语义——协议是统一的,差异都被收敛在了格式化器里。

【免费下载链接】context-modeContext window optimization for AI coding agents. Sandboxes tool output (98% reduction), persists session memory, and enforces routing across 17 platforms via MCP + hooks.项目地址: https://gitcode.com/GitHub_Trending/cl/context-mode

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询