Skip to content

入口与引导

三层引导架构

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 加载时就开始捕获键盘输入,提升体感响应速度。

下一步