状态管理
没用 Redux,没用 MobX,自己写了一个 Zustand 风格的 closure-based store。80+ 字段的全局状态,靠这套简单的机制管得服服帖帖。
设计选择
Claude Code 的状态管理不依赖任何第三方库,用闭包实现了类似 Zustand 的 store:
typescript
function createStore(initialState) {
let state = initialState
const listeners = new Set()
return {
getState: () => state,
setState: (partial) => {
state = { ...state, ...partial }
listeners.forEach(l => l(state))
},
subscribe: (listener) => {
listeners.add(listener)
return () => listeners.delete(listener)
}
}
}为什么不用 Zustand?大概是不想引入依赖。这种 store 的实现就几十行代码,自己写的好处是完全可控。
AppState 结构
80+ 个字段,覆盖应用的所有状态:
- 配置:设置、verbose 模式、模型选择
- UI 状态:展开/收起、overlay、选中项
- 连接:远程/Bridge 连接状态
- 权限:工具权限规则、Agent 定义
- 任务:任务列表、文件历史
- MCP:MCP 客户端连接
- 通知:消息队列、todo 列表
所有状态都包裹在 DeepImmutable<T> 中——编译时防止意外修改。
React 集成
两个 Hook 完成状态消费:
typescript
// 选择性订阅,只在关心的字段变化时重渲染
const model = useAppState(s => s.model)
// 获取 setState 函数
const setState = useSetAppState()底层用 useSyncExternalStore 而不是 Context。原因:Context 变化时所有消费者都重渲染,而 useSyncExternalStore 可以做选择性订阅,只有 selector 返回值变化时才触发重渲染。
对 80+ 字段的大状态来说,这个优化至关重要。
投机执行
一个有意思的设计——Speculation System:
系统会预测用户的下一步操作,提前执行。状态机有两个状态:
- idle:等待中
- active:正在执行投机操作,带 abort 能力
如果预测错了,abort 掉重来。如果猜对了,用户体验就是"瞬间响应"。