Claude Code 采用三层状态管理:进程级全局 → Store → React Hooks。
一、状态分层架构
┌─────────────────────────────────────────┐ │ Layer 3: React Hooks (组件级) │ │ useState, useEffect, custom hooks │ │ ↕ 单向数据流 │ │ │ │ Layer 2: AppState Store (应用级) │ │ createStore<AppState>() │ │ ↕ 发布/订阅 │ │ │ │ Layer 1: bootstrap/state.ts (进程级) │ │ 模块闭包中的全局单例 │ │ getter/setter 函数 │ └─────────────────────────────────────────┘
|
二、Layer 1: 进程级全局状态 (bootstrap/state.ts)
2.1 为什么需要进程级状态?
多个场景需要在 React 组件树 外部 访问状态:
- SDK 模式(无 React)
- 子 Agent 进程
- API 调用层
- 工具执行层
- OpenTelemetry 遥测
2.2 核心字段
type State = { sessionId: SessionId; originalCwd: string; projectRoot: string;
totalCostUSD: number; totalAPIDuration: number; totalInputTokens: number; totalOutputTokens: number; modelUsage: { [modelName: string]: ModelUsage };
mainLoopModelOverride: ModelSetting | undefined; initialMainLoopModel: ModelSetting;
isInteractive: boolean; kairosActive: boolean; clientType: string; sessionSource: string;
meter: Meter | null; sessionCounter: AttributedCounter | null; costCounter: AttributedCounter | null;
sdkBetas: string[]; allowedChannels: ChannelEntry[];
registeredHooks: Map<string, RegisteredHookMatcher[]>; }
|
2.3 访问模式
export function getSessionId(): SessionId { return state.sessionId; } export function getTotalCostUSD(): number { return state.totalCostUSD; }
export function addToTotalCostState(amount: number): void { state.totalCostUSD += amount; }
export function switchSession(newSessionId: SessionId): void { state.sessionId = newSessionId; resetSettingsCache(); }
|
三、Layer 2: AppState Store
3.1 Store 实现
export function createStore<T>( initialState: T, onChange?: OnChange<T>, ): Store<T> { let state = initialState; const listeners = new Set<Listener>();
return { getState: () => state,
setState: (updater: (prev: T) => T) => { const prev = state; const next = updater(prev); if (Object.is(next, prev)) return; state = next; onChange?.({ newState: next, oldState: prev }); for (const listener of listeners) listener(); },
subscribe: (listener: Listener) => { listeners.add(listener); return () => listeners.delete(listener); }, }; }
|
3.2 状态变更监听
export function onChangeAppState({ newState, oldState, }: { newState: AppState; oldState: AppState }): void {
if (newState.toolPermissionContext.mode !== oldState.toolPermissionContext.mode) { updatePermissionModeInConfig(newState.toolPermissionContext.mode); }
if (newState.mainLoopModel !== oldState.mainLoopModel) { updateTelemetryModel(newState.mainLoopModel); }
if (newState.tasks !== oldState.tasks) { checkForCompletedTasks(newState.tasks, oldState.tasks); } }
|
3.3 选择器 (Selectors)
export function getActiveAgentCount(state: AppState): number { return Array.from(state.tasks.values()) .filter(t => t.type === 'local_agent' && t.status === 'running') .length; }
export function getTotalRunningTasks(state: AppState): number { return Array.from(state.tasks.values()) .filter(t => t.status === 'running') .length; }
|
四、Layer 3: React Hooks
4.1 常用 hooks 分类
数据获取类:
useSettings() useMainLoopModel() useCostSummary() useTerminalSize() useIdeConnectionStatus()
|
交互类:
useTextInput() useVimInput() useSearchInput() useArrowKeyHistory() useCopyOnSelect() usePasteHandler()
|
生命周期类:
useExitOnCtrlCD() useCancelRequest() useAfterFirstRender() useMinDisplayTime()
|
集成类:
useReplBridge() useIDEIntegration() useMergedClients() useMergedTools() useManagePlugins()
|
export default function useCanUseTool( toolPermissionContext: ToolPermissionContext, setToolPermissionContext: (updater) => void, ): CanUseToolFn { return useCallback(async (tool, input, assistantMessage) => { const ruleMatch = matchPermissionRules(tool, input, toolPermissionContext); if (ruleMatch) return ruleMatch;
switch (toolPermissionContext.mode) { case 'bypass': return { behavior: 'allow' }; case 'plan': return tool.isReadOnly() ? { behavior: 'allow' } : { behavior: 'deny' }; case 'auto': return await classifierDecision(tool, input); case 'default': return { behavior: 'ask' }; } }, [toolPermissionContext]); }
|
五、数据流图
用户操作 (键盘/鼠标) │ ▼ React Event Handler (REPL.tsx) │ ├─→ setAppState(prev => ...) → Store 更新 │ │ │ ├─→ onChange() → 副作用 │ └─→ listeners → React 重渲染 │ ├─→ setMessages(prev => ...) → 消息列表更新 │ └─→ query() → Agentic Loop │ ├─→ 更新 bootstrap/state (成本/token) ├─→ yield events → 更新 messages └─→ 工具执行 → 可能修改 AppState
|
六、信号系统 (utils/signal.ts)
export function createSignal<T>(initialValue: T) { let value = initialValue; const subscribers = new Set<(value: T) => void>();
return { get: () => value, set: (newValue: T) => { value = newValue; for (const sub of subscribers) sub(newValue); }, subscribe: (fn: (value: T) => void) => { subscribers.add(fn); return () => subscribers.delete(fn); }, }; }
|
用于不需要 React 重渲染的简单状态(如内部计数器、标志位)。
七、配置系统 (utils/config.ts)
配置来源 (优先级从高到低): ├─ 1. CLI 参数 (--model, --permission-mode, ...) ├─ 2. 环境变量 (ANTHROPIC_API_KEY, CLAUDE_CODE_*) ├─ 3. 项目配置 (.claude/settings.json) ├─ 4. 用户配置 (~/.claude/settings.json) ├─ 5. 企业策略 (MDM / 远程管理) └─ 6. 默认值
|
export function getGlobalConfig(): GlobalConfig { return readJsonSync(GLOBAL_CONFIG_PATH); }
export function getCurrentProjectConfig(): ProjectConfig { return readJsonSync(join(cwd, '.claude/settings.json')); }
export function saveGlobalConfig(config: GlobalConfig): void { writeJsonSync(GLOBAL_CONFIG_PATH, config); }
|
八、文件状态缓存
type FileStateCache = Map<string, { content: string; modifiedTime: number; encoding: string; }>;
export function createFileStateCacheWithSizeLimit( maxSize: number = READ_FILE_STATE_CACHE_SIZE ): FileStateCache { }
export function mergeFileStateCaches( parent: FileStateCache, child: FileStateCache, ): FileStateCache { }
|