Bootstrap

Bootstrap 模块是 Claude Code 的全局状态中枢,通过 state.ts 这一超级单例管理会话 ID、项目路径、模型配置、Token 计量、成本追踪、遥测指标等上百个运行时状态。它不是传统意义上的"启动引导",而是整个应用的状态基座——所有子系统通过 getter/setter 函数对读写这个共享状态,实现跨模块的状态协调。

职责与设计理念

职责说明

全局状态容器与会话生命周期管理,维护运行时的单一真相源

设计理念

状态即基座——用模块级闭包变量替代类实例,用纯函数 getter/setter 替代 OOP 封装。全局状态不是反模式,而是分布式子系统的协调契约。

架构决策

为什么用闭包单例而不是 class 实例?

使用模块级 let 变量 + 纯函数 getter/setter

class 实例需要传递引用,闭包单例天然全局可达。100+ 个状态字段用 class 会产生巨大的 this 上下文,而纯函数无 this 绑定问题,tree-shaking 友好。

⚖️ 牺牲了可测试性(全局状态难以隔离),换取了零传参的便利性。测试时需要 resetStateForTests() 手动清理。

为什么一个文件 1700+ 行而不拆分?

所有状态集中在单一文件

状态之间存在隐式耦合(如 switchSession 需要 resetCostState),拆分会引入跨文件的循环依赖。单文件保证了状态变更的原子性可见——任何开发者打开这一个文件就能看到全部状态。

⚖️ 文件过长影响可读性,但状态的完整性比可读性更重要。

文件清单

文件名 用途
state.ts 全局状态单例,1700+ 行,管理会话、模型、成本、遥测等上百个状态变量 (1755 行)

使用场景

启动 Claude Code

getInitialState() 初始化所有状态字段为默认值,regenerateSessionId() 生成新会话 ID

CLI → Entrypoints → Bootstrap.getInitialState()

/resume 恢复会话

switchSession() 切换到历史会话 ID,同时重置成本计数器

Commands.resume → Bootstrap.switchSession()

每次 API 调用完成

addToTotalCostState() 累计 Token 用量和费用,按模型维度分片统计

依赖关系

  • Entrypoints — 多模式入口适配器,统一 CLI/SDK/MCP 三种调用方式的启动路径

关键代码片段

会话状态管理

function getSessionId(): SessionId { return state.sessionId }
function regenerateSessionId(opts) {
  state.sessionId = SessionId(uuidv7())
  state.parentSessionId = opts?.parentSessionId
}
function switchSession(sessionId: SessionId) {
  state.sessionId = sessionId
  resetCostState()
}

通过闭包变量 + 纯函数实现全局状态管理,避免类实例的复杂性

Token 计量与成本追踪

function addToTotalCostState(
  cost: number, inputTokens: number, outputTokens: number,
  cacheReadInputTokens: number, cacheCreationInputTokens: number,
  webSearchRequests: number, model: string, duration: number,
): void {
  state.totalCostUSD += cost
  state.totalInputTokens += inputTokens
  state.totalOutputTokens += outputTokens
  // ... 按模型维度累计
  const usage = state.modelUsage[model] ??= { /* 初始化 */ }
  usage.inputTokens += inputTokens
  usage.outputTokens += outputTokens
  usage.apiCalls++
}

多维度成本追踪:总量 + 按模型分片,支持 Token、费用、API 调用次数

Beta 特性锁存机制

// 锁存(Latch)模式:一旦设置,会话内不可回退
function getAfkModeHeaderLatched(): boolean | null {
  return state.afkModeHeaderLatched
}
function setAfkModeHeaderLatched(v: boolean): void {
  state.afkModeHeaderLatched = v
}
function clearBetaHeaderLatches(): void {
  state.afkModeHeaderLatched = null
  state.fastModeHeaderLatched = null
  state.cacheEditingHeaderLatched = null
  state.thinkingClearLatched = null
}

Beta 特性用锁存模式控制:AFK 模式、快速模式、缓存编辑、思考清除

技术笔记

performance

滚动活动节流

markScrollActivity() 使用 200ms 节流窗口,waitForScrollIdle() 等待滚动停止后再执行重渲染,避免滚动期间的 CPU 争抢。

edge-case

慢操作追踪

addSlowOperation() 记录超过阈值的操作(如 API 超时),最多保留最近 100 条,用于诊断性能瓶颈。

security

OAuth Token 隔离

getOauthTokenFromFd() 和 getApiKeyFromFd() 从文件描述符读取凭证,避免通过命令行参数暴露敏感信息。