Skip to content

特性门控系统

编译时特性门控不是什么新概念,C/C++ 的条件编译用了几十年了。但在 TypeScript 项目里做到这个程度的,Claude Code 算是头一个让我觉得做得漂亮的。

核心机制

一个 feature() 函数,编译时求值:

typescript
if (feature('BRIDGE_MODE')) {
  // 这段代码只在 Bridge 构建产物中存在
  // 其他构建产物里,整个 if 块被删掉
  await import('./bridge/handler')
}

不是运行时判断,是编译时死代码消除。构建产物里根本不包含未启用功能的代码。

为什么需要这个

Claude Code 有多个部署目标:

  • 公开版:普通用户下载的 npm 包
  • 内部版:Anthropic 内部构建,功能更多
  • 企业版:特定企业功能

同一套代码,通过 feature gate 编译出不同的产物。不需要维护多个分支,也不用在运行时浪费资源判断一堆用不到的功能。

特性标志分类

核心功能

标志用途
BRIDGE_MODEWeb 端通信(claude.ai 桥接)
DAEMON守护进程模式
VOICE_MODE语音输入
TEMPLATES项目模板系统
BG_SESSIONS后台会话管理

工具与功能

大约 47 个编译时标志,控制各种工具和功能的启用:

  • AGENT_TRIGGERS — Agent 触发器
  • WEB_BROWSER_TOOL — 网页浏览工具
  • WORKFLOW_SCRIPTS — 工作流编排
  • TOKEN_BUDGET — Token 预算管理
  • COMPUTER_USE — 计算机操作
  • CHICAGO_MCP — Computer Use MCP 服务器

企业级

  • COORDINATOR_MODE — 多 Agent 协调器
  • ULTRAPLAN — 高级规划功能
  • BYOC_ENVIRONMENT_RUNNER — 自带环境运行器
  • SELF_HOSTED_RUNNER — 自托管运行器

运行时门控

除了编译时的 feature(),还有 GrowthBook 做运行时门控:

typescript
// 运行时判断,不影响构建产物
if (growthbook.isOn('new_model_default')) {
  setModel('claude-sonnet-4-6')
}

两层门控各有用途:

编译时运行时
机制feature()GrowthBook
生效方式构建时删代码远程配置刷新
适用场景不同部署目标A/B 测试、灰度
更新成本需要重新构建即时生效

在代码中的体现

feature gate 遍布关键路径:

  • cli.tsx:约 30 个 feature-gated 路由路径
  • tools.ts:控制工具注册——某些工具只在特定构建中存在
  • keybindings:部分快捷键绑定依赖特定标志

这意味着公开版和内部版的 Claude Code,代码路径可能差异很大,但维护的是同一套源码。

注意

源站原文档列出的一些标志(如 REPL_TOOL、SLEEP_TOOL 等)在实际代码中并不存在。本文已做修正,以实际源码为准。