Context Mode 的平台检测是一个多级优先级解析系统,核心目标是确定当前运行环境属于 15 个支持平台中的哪一个,从而将 MCP 会话数据(如 FTS5 索引)写入正确的存储路径(如 ~/.claude/ 或 ~/.pi/)。该机制严格遵循 MCP clientInfo > CONTEXT_MODE_PLATFORM 环境变量覆盖 > 特定平台环境变量 > 配置目录存在性 > 默认回退 的优先级链,并通过精确的排序策略处理了平台 fork(如 Kilo 之于 OpenCode)和共存场景(如 Cursor 终端中运行 Claude Code)的检测冲突。
Context Mode 平台检测机制:从环境变量到 MCP clientInfo 的多级优先级解析
当 Context Mode 作为 MCP 服务器插件启动时,它需要立即回答一个根本问题:当前是由哪个 AI 编码平台(如 Claude Code、Cursor、Gemini CLI)驱动的?这个判断至关重要,因为它决定了会话数据、FTS5 知识库和配置文件的存储位置。错误的识别会导致会话数据错乱,例如,一个为 Pi 平台设计的会话被错误地写入了 ~/.claude/ 目录。
detect.ts 文件实现了一个鲁棒的多级检测系统,确保在各种复杂环境下都能做出正确判断。
三级优先级解析架构
检测逻辑(detectPlatform 函数)严格按照以下顺序执行,每层成功匹配后立即返回,不再向下查找:
- 最高优先级:MCP clientInfo(高置信度)
- 高优先级:显式环境变量(高置信度)
- 中优先级:配置目录存在性(中置信度)
- 最低优先级:默认回退(低置信度,回退到 Claude Code)
1. 最高优先级:MCP clientInfo
在 MCP 的 initialize 握手阶段,客户端(即 AI 编码平台)会发送 clientInfo,其中包含 name 字段。这是最准确、零配置的识别信号。
client-map.ts 文件定义了从客户端名称到平台 ID 的静态映射表:
export const CLIENT_NAME_TO_PLATFORM: Record<string, PlatformId> = {
"claude-code": "claude-code",
"gemini-cli-mcp-client": "gemini-cli",
"cursor-vscode": "cursor",
"Visual-Studio-Code": "vscode-copilot",
"JetBrains Client": "jetbrains-copilot",
"Pi CLI": "pi",
"omp-coding-agent": "omp", // Pi 重命名为 OMP 后的规范名称
// ... 其他平台映射
};
检测函数首先检查 clientInfo.name 是否存在于此映射表中。对于动态名称模式(如 Qwen Code 使用 qwen-cli-mcp-client-<serverName>),则采用前缀匹配。此层级的优先级最高,因为它直接来源于平台自身的声明。
2. 高优先级:特定平台环境变量
如果 MCP clientInfo 不可用或未匹配,则检测系统会扫描 PLATFORM_ENV_VARS 这一核心注册表。该注册表为每个平台定义了其官方运行时会设置的一系列环境变量。
关键设计:类型化注册表与 fork 优先排序
PLATFORM_ENV_VARS 不是一个简单的字符串列表,而是一个 Map<PlatformId, PlatformEnvEntry[]>。每个条目不仅包含变量名,还标注了其 role:
workspace: 变量指向项目工作目录(如CLAUDE_PROJECT_DIR)。identification: 变量仅用于标识平台身份(如CLAUDE_CODE_ENTRYPOINT)。
更重要的是,注册表中的平台顺序是经过精心设计的。代码注释明确指出:“forks listed BEFORE the fork's parent so collision detection works”。这意味着,对于一个平台(如 Kilo)是另一个平台(如 OpenCode)的 fork 的情况,fork 的条目必须排在前面。
以 Kilo 和 OpenCode 为例:
["kilo", [
{ name: "KILO", role: "identification" },
{ name: "KILO_PID", role: "identification" },
]],
["opencode", [
{ name: "OPENCODE_PROJECT_DIR", role: "workspace" },
// ...
]],
当 Kilo 运行时,它会同时设置 KILO 和 OPENCODE 环境变量(因为它是 OpenCode 的 fork)。由于 kilo 在注册表中排在 opencode 之前,检测算法会首先命中 kilo 的 KILO 变量,从而正确识别为 Kilo,避免了被误判为 OpenCode。测试文件 detect-ambiguity-matrix.test.ts 中的用例 "KILO beats OPENCODE when both envs are set (fork-collision)" 正是这一设计的回归保障。
环境变量的置信度与消歧
环境变量检测是“高置信度”的,但必须处理一个特殊情况:Microsoft 的 VS Code 会将 VSCODE_PID 和 VSCODE_CWD 导出到每一个子进程中,包括从其集成终端启动的 Claude Code。这会导致本应识别为 claude-code 的环境被误判为 vscode-copilot。
为了解决此问题(Issue #539),检测逻辑在即将命中 vscode-copilot 时,会执行一个额外的“皮带加背带”检查:调用 claudeCodeHasContextModePlugin() 函数。该函数会读取并缓存 ~/.claude/plugins/installed_plugins.json 文件,检查其中是否包含 context-mode 插件。如果存在,则证明当前运行时是安装了 Context Mode 插件的 Claude Code,应优先识别为 claude-code。detect-claude-code-in-vscode.test.ts 测试文件专门验证了这一复杂场景。
3. 中优先级:配置目录存在性
当环境变量也无法确定平台时(例如在没有设置任何环境变量的纯 CLI 工具中),检测系统会转向检查用户主目录(~)下是否存在特定的配置目录。
关键设计:Agents-first 排序策略
配置目录的检查顺序并非按字母或平台流行度,而是遵循 “CLI agents BEFORE host IDEs” 的原则(Issue #542)。这是因为像 Cursor 这样拥有大量安装量的编辑器,如果其目录 ~/.cursor/ 被优先检查,那么所有在 Cursor 终端中运行的 CLI 工具(如 Pi、Kiro、OMP)都会被错误地识别为 Cursor。
因此,配置目录的检查顺序是:首先检查所有 CLI agent 类平台的目录(如 ~/.kiro/, ~/.omp/, ~/.pi/, ~/.qwen/, ~/.gemini/),然后才检查宿主 IDE 的目录(如 ~/.cursor/, ~/.vscode/, ~/.config/JetBrains/)。detect-ambiguity-matrix.test.ts 文件中的 16 组全配对测试,系统地验证了当两个配置目录同时存在时,该优先级顺序是否能做出正确选择,例如 "cursor + pi → pi"。
4. 最低优先级:默认回退
如果以上所有检查都未命中,检测系统将回退到 claude-code 平台,并标记为低置信度。这是因为 Claude Code 是该生态中最常见的运行时,此默认值能保证 MCP 服务器在未知环境下仍能提供基础功能。
环境变量注册表的算法化设计
PLATFORM_ENV_VARS 注册表不仅服务于检测,其设计还支持了项目中的其他算法化需求,如项目目录解析和环境变量清理。
workspaceEnvVarsFor(platform):仅返回指定平台的role: "workspace"变量,用于构建项目目录的解析级联。foreignWorkspaceEnv(platform)/foreignIdentificationEnv(platform):返回除指定平台外,所有其他平台的 workspace 或 identification 变量集合。这对于需要清理子进程环境的场景(如 Pi 桥接器需要清除 Claude Code 的CLAUDE_CODE_ENTRYPOINT以防子进程误检测)至关重要,且遵循单一注册表原则,添加新平台无需修改清理逻辑。
总结
Context Mode 的平台检测机制是一个精巧的多级状态机。它通过 MCP clientInfo 的直接声明、环境变量的细致分类与优先级排序、以及配置目录的智能检查,构建了一套高可用、可扩展的识别系统。这套设计不仅确保了 15 个平台的准确识别,也为处理平台 fork、环境变量污染和复杂工具链共存等边界情况提供了坚实保障。
FAQ
Q: 如何覆盖 Context Mode 的自动平台检测?
A: 可以设置环境变量 CONTEXT_MODE_PLATFORM 为有效的平台 ID(如 cursor, pi)。该变量的优先级高于环境变量检测和配置目录检测,但低于 MCP clientInfo。
Q: Pi 和 OMP (Oh My Pi) 在检测上有什么区别?
A: OMP 是 Pi 的一个分支。检测系统通过两个关键点区分它们:1)在环境变量注册表中,OMP 的 PI_CODING_AGENT_DIR 排在 Pi 的变量之前;2)在 MCP clientInfo 中,OMP 的规范名称是 omp-coding-agent。当两者共存时,OMP 的目录 ~/.omp/ 和特定环境变量会被优先识别。
Q: 如果没有任何 AI 编码平台被识别,Context Mode 会如何工作?
A: 检测函数会回退到 claude-code 平台,置信度为“低”。这意味着它会尝试使用 Claude Code 适配器的行为模式。虽然 MCP 核心服务(如工具调用)仍可工作,但一些平台特定的 Hook 路由和会话存储路径可能不会完全符合预期。