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 行) |
使用场景
getInitialState() 初始化所有状态字段为默认值,regenerateSessionId() 生成新会话 ID
CLI → Entrypoints → Bootstrap.getInitialState()
switchSession() 切换到历史会话 ID,同时重置成本计数器
Commands.resume → Bootstrap.switchSession()
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 模式、快速模式、缓存编辑、思考清除
技术笔记
滚动活动节流
markScrollActivity() 使用 200ms 节流窗口,waitForScrollIdle() 等待滚动停止后再执行重渲染,避免滚动期间的 CPU 争抢。
慢操作追踪
addSlowOperation() 记录超过阈值的操作(如 API 超时),最多保留最近 100 条,用于诊断性能瓶颈。
OAuth Token 隔离
getOauthTokenFromFd() 和 getApiKeyFromFd() 从文件描述符读取凭证,避免通过命令行参数暴露敏感信息。