启动链路极限优化
51 万行的程序怎么做到「秒开」?答案不是「机器快」,是四个字:能不加载的,一个字节都不加载。
claude --version 的模块加载量是 零入口文件 cli.tsx 的所有 import 都是动态的——先看命令行参数再决定加载什么。最极端的路径 --version 连一个模块都不加载,直接输出编译期内联的版本号字符串。
| 优先级 | 匹配条件 | 加载量 |
|---|---|---|
| 1 | --version / -v | 零直接 return |
| 2 | --dump-system-prompt | 最小 |
| 3 | --claude-in-chrome-mcp | 专用模块 |
| 4 | --daemon-worker | 精简 |
| 5 | remote-control / bridge | 含 auth + policy |
| 6 | daemon | 含 configs + sinks |
| 7 | ps / logs / attach / kill | 含 configs |
| 8 | new / list / reply | 专用模块 |
| 9-10 | environment-runner / self-hosted-runner | 专用模块 |
| 默认 | 无特殊标志(正常使用) | 完整 main.tsx785KB |
源码注释原话:Fast-path for --version: zero module loading needed
正常思路是「加载完模块 → 再执行逻辑」。main.tsx 反着来:在模块顶层(import 评估期间)就把两个最慢的 I/O 启动出去——读 macOS 钥匙串、起 MDM 子进程。它们与后续约 135ms 的模块加载并行,等主流程需要结果时早就绪了。
用 lodash memoize 包裹保证只跑一次;挂在 Commander 的 preAction 钩子上——所以 --help 会完全跳过初始化。
亮点是 preconnectAnthropicApi():正式请求前先完成 TCP + TLS 握手,把连接建立的成本从「第一次对话」里挪走。
先检查 Node.js ≥ 18,然后按序铺开整个会话要用的基础设施。
最后一步是 --dangerously-skip-permissions 的多重安全检查——危险参数也要走完安检。
Bun bundler 提供的 feature() 在构建时求值,返回 false 的分支被死代码消除(DCE)物理删除——不是运行时开关,是产物里根本没有:
import { feature } from 'bun:bundle';
if (feature('KAIROS')) {
// 内部专用代码 —— 外部构建产物中此块不存在
} 同一份代码库,构建出「内部版 / 外部版」两种产物。常见 flag:KAIROS(后台守护)、COORDINATOR_MODE、ABLATION_BASELINE(A/B 基线:关掉所有高级功能)、DUMP_SYSTEM_PROMPT 等。