入口与引导
三层引导架构
Claude Code 的启动采用三层架构,核心理念是尽量延迟加载重型模块:
Layer 1: cli.tsx — 真正的入口
Source:
src/entrypoints/cli.tsx
Polyfill 注入
文件顶部(行 1-17)注入运行时 polyfill:
typescript
// Source: src/entrypoints/cli.tsx:2
const feature = (_name: string) => false;
// Source: src/entrypoints/cli.tsx:3-13
globalThis.MACRO = {
VERSION: "2.1.888",
BUILD_TIME: new Date().toISOString(),
FEEDBACK_CHANNEL: "",
// ...
};
// Source: src/entrypoints/cli.tsx:15-17
globalThis.BUILD_TARGET = "external";
globalThis.BUILD_ENV = "production";
globalThis.INTERFACE_TYPE = "stdio";环境变量配置
行 19-32 设置进程环境:
typescript
// 修复 yarn auto-pinning bug
process.env.COREPACK_ENABLE_AUTO_PIN = "0";
// 远程容器环境 (CCR) 的内存限制
if (process.env.CLAUDE_CODE_REMOTE === "true") {
process.env.NODE_OPTIONS = "--max-old-space-size=8192";
}快速路径分发
关键设计:main() 函数在行 54-320 实现了约 15 个快速路径,避免加载 4700 行的 main.tsx:
绿色 = 零导入快速返回;灰色 = 受 feature() 门控(始终禁用);蓝色 = 完整路径。
--version 快速路径
typescript
// Source: src/entrypoints/cli.tsx:63-71
if (args.includes('--version') || args.includes('-v') || args.includes('-V')) {
console.log(`${MACRO.VERSION} (Claude Code)`);
process.exit(0);
// 不导入任何模块,毫秒级返回
}完整路径
typescript
// Source: src/entrypoints/cli.tsx:308-315
const { startCapturingEarlyInput } = await import("../utils/earlyInput.js");
startCapturingEarlyInput();
profileCheckpoint("cli_before_main_import");
const { main: cliMain } = await import("../main.jsx");
profileCheckpoint("cli_after_main_import");
await cliMain();
profileCheckpoint("cli_after_main_complete");注意 main.tsx 是动态导入(await import()),这意味着快速路径从不支付它的模块加载成本。
同时,在导入 main.tsx 之前就开始了 startCapturingEarlyInput() — 这样在等待模块加载时就能捕获用户的键盘输入。
Layer 2: init.ts — 一次性初始化
Source:
src/entrypoints/init.ts
init() 函数通过 memoize() 包装,确保只运行一次。它在 Commander.js 的 preAction hook 中被调用。
初始化序列
黄色 = fire-and-forget 异步操作(不等待完成)
关键步骤详解
安全环境变量 (行 73-84)
typescript
applySafeConfigEnvironmentVariables();
applyExtraCACertsFromConfig();
// 必须在第一次 TLS 握手前完成
// Bun 通过 BoringSSL 缓存 TLS 配置API 预连接 (行 159)
typescript
preconnectAnthropicApi();
// Fire-and-forget TCP+TLS 握手
// 与后续初始化步骤并行执行
// 代理/mTLS/云供应商模式下跳过错误处理
typescript
// Source: src/entrypoints/init.ts:215-237
catch (error) {
if (error instanceof ConfigParseError) {
if (getIsNonInteractiveSession()) {
// 非交互模式:写 stderr 并退出
} else {
// 交互模式:显示 InvalidConfigDialog
return import('../components/InvalidConfigDialog.js')
.then(m => m.showInvalidConfigDialog({ error }));
}
}
}完整启动时间线
从 bun run dev 到 REPL 就绪的完整序列:
性能优化策略
Claude Code 启动流程中的性能优化值得学习:
1. 快速路径分离
简单命令(--version)在加载 main.tsx 之前就返回,节省 ~500ms。
2. 异步预取
typescript
// main.tsx 顶层 — 在导入完成前就开始
startMdmRawRead(); // macOS/Windows 注册表查询
startKeychainPrefetch(); // Keychain OAuth + API key 读取3. 并行初始化
setup()、命令加载、Agent 定义加载三者并行执行。
4. 延迟导入
OpenTelemetry(~400KB)、打印模块等重型依赖只在需要时才 import()。
5. 早期输入捕获
在等待 main.tsx 加载时就开始捕获键盘输入,提升体感响应速度。