Claude Code 并没有套用流行的第三方状态管理库(如 Zustand、Jotai、Recoil 或 MobX),而是实现了一个自研的轻量级状态管理引擎。这是一个自定义的 Zustand 风格的状态管理方案,特别适合Claude Code 这种长会话、高吞吐、多代理协作的 CLI 应用。

Claude Code 的状态管理基于三个核心文件:

- [`src/state/store.ts`](src/state/store.ts) - 核心状态存储引擎

- [`src/state/AppStateStore.ts`](src/state/AppStateStore.ts) - 应用状态类型定义

- [`src/state/AppState.tsx`](src/state/AppState.tsx) - React 上下文提供者和 hooks

核心架构

概览

其余相关文件为

src/state/onChangeAppState.ts - 状态变更处理器

src/state/teammateViewHelpers.ts - 团队视图状态管理

src/state/selectors.ts - 状态选择器

Claude Code 只用 30 行代码就实现一个完整的状态管理系统,其内核 createStore(状态存储引擎)如下:

export type Store<T> = {
  getState: () => T
  setState: (updater: (prev: T) => T) => void
  subscribe: (listener: Listener) => () => void
}

export function createStore<T>(
  initialState: T,
  onChange?: OnChange<T>,
): Store<T> {
  let state = initialState           // ← 第1行:闭包状态
  const listeners = new Set<Listener>()  // ← 第2行:订阅者集合

  return {
    getState: () => state,            // ← 第3行:读取
    
    setState: (updater) => {          // ← 第4-12行:写入
      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) => {        // ← 第13-16行:订阅
      listeners.add(listener)
      return () => listeners.delete(listener)
    },
  }
}

没有中间件、没有 devtools、没有异步——只有状态、订阅、通知三个核心概念,

  • 状态是数据的存储中心,包含所有应用数据
  • 订阅是数据流向的控制机制,决定谁需要知道数据变化
  • 通知是数据变化的传播机制,确保所有相关方都能及时响应变化

先看src/state/store.ts核心状态存储引擎状态(State) 的作用

// src/state/store.ts
let state = initialState  // 内部可变状态

第 1 行 闭包状态的代码影响着的(src/state/AppStateStore.ts) - 应用状态类型定义中的400+字段,学过c++泛型的应该可以理解,let state = initialState 只是一个泛型变量,可以是任何类型 ,运行时:state 实际上等于 AppState 对象,包含所有字段 , 但代码层面:这里只看到 T,看不到具体字段而store.ts - 不知道也不关心 T 是什么。 

400+字段例如:

// src/state/AppStateStore.ts
export type AppState = DeepImmutable<{
  settings: SettingsJson                    // 应用设置
  tasks: { [taskId: string]: TaskState }    // 任务系统
  plugins: { enabled: LoadedPlugin[] }      // 插件系统
  mcp: { clients: MCPServerConnection[] }   // MCP 协议
  teamContext?: { teamName: string }        // 团队协作
  // ... 更多字段
}>

如何理解呢?let state = initialState容器(装水的瓶子),400+ 字段是内容物(水)。瓶子不知道里面装的是什么液体,只知道它能装东西;而类型定义描述了液体的具体成分,它们在内存中的关系如下:

内存中的实际状态对象(运行时):

state 变量指向的内存区域:
┌─────────────────────────────────────────────────────────┐
│  AppState 对象(由 getDefaultAppState() 创建)          │
├─────────────────────────────────────────────────────────┤
│  settings: ──────► { theme: 'dark', ... }              │
│  tasks: ─────────► { "task-1": TaskState, ... }        │
│  mcp: ───────────► { clients: [...], tools: [...] }    │
│  teamContext: ───► undefined(初始未启用)               │
│  // ... 其他 400+ 字段各自有值                          │
└─────────────────────────────────────────────────────────┘
        ▲
        │
   let state = initialState  // 这个变量指向上述对象

Claude Code中更为具体的状态变更触发流程如下:

在具体的代码层面,

为什么用 let 而不是 const

因为需要可变引用才能实现更新

let state = initialState   // ✅ 可以重新赋值
state = next              // 原子替换

const state = initialState // ❌ 无法替换
// 如果 state 是对象,只能 mutate:Object.assign(state, next)
// 这会破坏不可变性,导致 bug

┌────────────────────────────────
│           createStore 调用            
│  ┌─────────────────────────────┐     
│  │    闭包作用域 (Closure)          
│  │                        
│  │    let state = { count: 0 } │◄────┼── 私有变量,外部无法直接访问
│  │         ↑                 
│  │    ┌────┴────┐           
│  │    │ getState │───► 读取 state
│  │    │ setState │───► 修改 state
│  │    │subscribe │───► 监听变化 
│  │    └─────────┘          
│  │                          
│  └─────────────────────────────┘     
│              ↑                       
│         返回这三个函数                
└─────────────────────────────────

核心状态存储引擎第 2 行:const listeners = new Set<Listener>()

为什么用 Set 而不是 Array

特性 Set Array
去重 自动去重 需手动检查
删除 O(1) delete O(n) splice
查找 O(1) has O(n) indexOf
遍历 for...of for...of
// 取消订阅时 O(1) 删除
return () => listeners.delete(listener)  // Set: 直接删除引用

// 如果是 Array:
return () => {
  const idx = listeners.indexOf(listener)  // O(n) 查找
  if (idx > -1) listeners.splice(idx, 1)    // O(n) 移动元素
}

下面是订阅 (Subscribe)

const listeners = new Set<Listener>()  // 订阅者集合

subscribe: (listener: Listener) => () => void  // 订阅方法

第3 行:getState: () => state

getState: () => state

简单的读取接口

const store = createStore({ count: 0 })

// 直接访问闭包变量
console.log(store.getState())  // { count: 0 }

// 非 React 代码也能用
function logState() {
  console.log(store.getState())
}

第 4-12 行:setState —— 核心写入逻辑

setState: (updater) => {
  const prev = state        // 保存引用用于比较和回调
  const next = updater(prev) // 函数式更新:基于 prev 计算 next
  
  if (Object.is(next, prev)) return  // 性能优化:无变化短路
  
  state = next              // 原子替换引用
  
  onChange?.({ newState: next, oldState: prev })  // 副作用钩子
  
  for (const listener of listeners) listener()  // 通知所有订阅者
}

第 4-12 行代码的通知顺序

state = next                                    // 1. 先更新状态
onChange?.({ newState: next, oldState: prev })  // 2. 副作用(同步)
for (const listener of listeners) listener()    // 3. 通知 UI(同步)

为什么是同步而非异步?

// Redux 的异步通知(中间件/批处理)
dispatch(action) 
  → reducer 
  → 加入通知队列 
  → 微任务刷新 
  → 组件更新

// Zustand 风格同步通知
setState(updater)
  → 立即更新 state
  → 立即执行 onChange
  → 立即遍历 listeners
  → 同步触发 React 的 setState(在事件处理函数内)

优势:可预测、无 stale closure、支持同步读取最新值

第 13-16 行:subscribe —— 订阅系统

subscribe: (listener) => {
  listeners.add(listener)
  return () => listeners.delete(listener)  // 清理函数
}

使用模式:

// React 集成(useSyncExternalStore)
function useAppState<T>(selector: (state: AppState) => T): T {
  const store = useContext(AppStoreContext)
  
  return useSyncExternalStore(
    store.subscribe,                    // 直接传入
    () => selector(store.getState()),     // 获取快照
    () => selector(store.getState())      // SSR 快照
  )
}

// 非 React 代码
const unsub = store.subscribe(() => {
  console.log('State changed:', store.getState())
})
// 稍后...
unsub()  // 取消订阅

三者协同工作流程

1. 状态更新流程

// 1. 组件触发状态更新
setAppState(prev => ({
  ...prev,
  statusLineText: 'Processing...'
}))

// 2. store.setState 执行
setState: (updater: (prev: T) => T) => {
  const prev = state
  const next = updater(prev)
  
  // 3. 检查是否真的变化
  if (Object.is(next, prev)) return
  
  // 4. 更新内部状态
  state = next
  
  // 5. 触发 onChange 回调(通知外部系统)
  onChange?.({ newState: next, oldState: prev })
  
  // 6. 通知所有订阅者
  for (const listener of listeners) listener()
}

2. 订阅者响应流程

// React 组件接收到通知
function MyComponent() {
  const someValue = useAppState(s => s.someField)
  
  // 当 someField 变化时,useSyncExternalStore 会触发组件重新渲染
  useEffect(() => {
    // 处理状态变化
  }, [someValue])
}

3. 通知链式反应

// 状态变更 → 订阅者更新 → 外部系统同步
1. 用户切换权限模式
2. store.setState 更新状态
3. onChangeAppState 检测到变化
4. 通知 CCR/SDK 同步权限模式
5. 通知设置系统持久化变更
6. 所有订阅该字段的组件重新渲染
7. UI 立即反映最新状态

 

以上就是核心状态存储引擎的分析,可见有4个特点

┌─────────────────────────────────────────────────────────┐
│                    createStore 实现                       │
├─────────────────────────────────────────────────────────┤
│  特点1: 不可变数据更新                                     │
│  ├── 第4行: updater: (prev: T) => T  类型定义            │
│  └── 第18-19行: const next = updater(prev) 实现           │
├─────────────────────────────────────────────────────────┤
│  特点2: Object.is 深度相等性检查                           │
│  └── 第20行: if (Object.is(next, prev)) return           │
├─────────────────────────────────────────────────────────┤
│  特点3: 状态变更回调                                       │
│  ├── 第8行: onChange?: OnChange<T> 参数定义             │
│  └── 第22行: onChange?.({ newState, oldState }) 调用      │
├─────────────────────────────────────────────────────────┤
│  特点4: 内存管理优化(Set存储监听器)                       │
│  ├── 第11行: new Set<Listener>() 初始化                   │
│  ├── 第24行: listeners.add(listener) O(1)添加            │
│  └── 第26行: listeners.delete(listener) O(1)清理         │
└─────────────────────────────────────────────────────────┘

首先就是基于不可变数据更新模式

// 第4行:API设计强制不可变
setState: (updater: (prev: T) => T) => void

// 第18-19行:实现不可变更新
const prev = state           // 保存旧引用
const next = updater(prev)   // 基于旧状态计算新状态
state = next                 // 原子替换引用(不是mutate)

使用 `Object.is` 进行深度相等性检查

// 第20行:精确相等判断
if (Object.is(next, prev)) return

状态变更回调 

// 第8行:可选回调参数
onChange?: OnChange<T>

// 第22行:状态变更后同步触发
onChange?.({ newState: next, oldState: prev })

Claude Code中的实际使用:

createStore(initialState, ({ newState, oldState }) => {
  // 权限模式同步到服务端
  if (newState.toolPermissionContext.mode !== oldState.toolPermissionContext.mode) {
    notifySessionMetadataChanged({ permission_mode: newMode })
  }
  
  // 设置持久化到磁盘
  if (newState.settings !== oldState.settings) {
    saveSettings(newState.settings)
  }
})

内存管理优化(Set存储监听器) 

// 第11行:Set存储(自动去重)
const listeners = new Set<Listener>()

// 第24行:O(1)添加
listeners.add(listener)

// 第26行:O(1)删除(自动清理,防止内存泄漏)
return () => listeners.delete(listener)

完整数据流图解

┌─────────────┐     setState(updater)      ┌─────────────┐
│   用户交互   │ ──────────────────────────► │             │
│  (点击/输入) │                           │   闭包状态   │
└─────────────┘                           │   (state)    │
                                          │             │
┌─────────────┐     getState()            │             │
│   外部系统   │ ◄─────────────────────────│             │
│  (API/定时器)│                           └──────┬──────┘
└─────────────┘                                  │
                                                  │
                         ┌────────────────────────┘
                         │
                         ▼
              ┌─────────────────────┐
              │   const prev = state │
              │   const next = updater(prev) │
              │   if (Object.is(next, prev)) return │
              │   state = next ◄── 原子替换      │
              └─────────────────────┘
                         │
           ┌─────────────┼─────────────┐
           ▼             ▼             ▼
      ┌─────────┐   ┌─────────┐   ┌──────────┐
      │ onChange │   │listeners│   │ 其他逻辑  │
      │ (副作用) │   │  (Set)  │   │          │
      └────┬────┘   └───┬─────┘   └──────────┘
           │            │
           ▼            ▼
    ┌────────────┐  ┌────────────┐
    │持久化到磁盘 │  │ 遍历执行     │
    │同步到服务端 │  │ for...of    │
    │日志记录    │  │             │
    └────────────┘  └─────┬──────┘
                          │
              ┌───────────┼───────────┐
              ▼           ▼           ▼
          ┌───────┐   ┌───────┐   ┌───────┐
          │组件 A │   │组件 B │   │组件 C │
          │重渲染 │   │重渲染 │   │重渲染 │
          └───────┘   └───────┘   └───────┘

2. React 集成层详解

- [`src/state/AppState.tsx`](src/state/AppState.tsx) - React 上下文提供者和 hooks

  • 提供 AppStateProvider 上下文提供者
  • 三个核心 hooks:useAppState(选择性订阅)、useSetAppState(状态更新)、useAppStateStore(直接访问 store)
  • 使用 useSyncExternalStore 实现高效的订阅机制

用最直观的方式解释 AppState.tsx 中的 React 集成层。这个文件是连接"存储引擎"和"React 组件"的桥梁。

完整体架构图解

┌─────────────────────────────────────────────────────────────────┐
│                     React 应用层                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │  ComponentA  │  │  ComponentB │  │      ComponentC       │  │
│  │              │  │             │  │                       │  │
│  │ const text = │  │ const mode =│  │ const update =        │  │
│  │ useAppState( │  │ useAppState│  │ useSetAppState()       │  │
│  │  s=>s.text)  │  │(s=>s.mode) │  │                       │  │
│  │      ↓       │  │     ↓       │  │        ↓              │  │
│  │  自动重渲染   │  │  自动重渲染  │  │  获取更新函数,不监听  │  │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘  │
│           │              │                      │              │
│           └──────────────┼──────────────────────┘              │
│                          ▼                                     │
│  ╔═══════════════════════════════════════════════════════════╗  │
│  ║              AppState.tsx (本文件)                        ║  │
│  ║  ┌─────────────────────────────────────────────────────┐  ║  │
│  ║  │  1. AppStateProvider: 创建 store 并提供给子树        │  ║  │
│  ║  │  2. useAppState: 选择性订阅特定状态字段               │  ║  │
│  ║  │  3. useSetAppState: 只获取更新函数,不订阅           │  ║  │
│  ║  │  4. useAppStateStore: 直接获取 store 实例            │  ║  │
│  ║  └─────────────────────────────────────────────────────┘  ║  │
│  ╚═══════════════════════════════════════════════════════════╝  │
│                          │                                     │
│                          ▼ 使用 createStore()                  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │              store.ts (存储引擎)                          │  │
│  │         let state = initialState                           │  │
│  │         const listeners = new Set()                       │  │
│  │         getState / setState / subscribe                   │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

三个核心 Hook 详解

1. useAppState —— 选择性订阅(最常用)

// 使用方式
const statusLineText = useAppState(s => s.statusLineText)
const permissionMode = useAppState(s => s.toolPermissionContext.mode)

内部实现原理:

export function useAppState<T>(selector: (state: AppState) => T): T {
  const store = useAppStore()  // 从 Context 获取 store 实例
  
  // 创建 getSnapshot 函数:获取当前选中的状态片段
  const get = () => {
    const state = store.getState()      // 获取完整状态
    const selected = selector(state)    // 执行选择器,提取需要的字段
    return selected
  }
  
  // 🔑 核心:useSyncExternalStore 处理订阅和优化
  return useSyncExternalStore(
    store.subscribe,  // 订阅函数:状态变化时通知 React
    get,              // 客户端获取快照
    get               // SSR 获取快照(这里相同)
  )
}

useSyncExternalStore 的作用:

传统 useState + useEffect 的问题:
┌─────────────────────────────────────────┐
│ useEffect(() => {                       │
│   const unsub = store.subscribe(() => {   │
│     setState(store.getState())  // ❌ 获取完整状态,不精准 │
│   })                                    │
│   return unsub                          │
│ }, [])                                  │
│                                         │
│ 问题1: 任何字段变化都触发重渲染          │
│ 问题2: 订阅建立有延迟(useEffect 在渲染后)│
│ 问题3: 并发渲染可能出现 tearing(状态不一致)│
└─────────────────────────────────────────┘

useSyncExternalStore 的优势:
┌─────────────────────────────────────────┐
│ return useSyncExternalStore(            │
│   store.subscribe,                      │
│   () => selector(store.getState())      │
│ )                                       │
│                                         │
│ 解决1: React 自动对比 selector 返回值     │
│        Object.is(prev, next) 不同才重渲染  │
│                                         │
│ 解决2: 订阅在渲染阶段同步建立               │
│        无延迟,立即可用                    │
│                                         │
│ 解决3: 内置 tearing 保护                   │
│        并发渲染时保证状态一致性              │
└─────────────────────────────────────────┘

精准订阅的工作流程:

状态对象:
{
  statusLineText: "Ready",    // ← ComponentA 订阅
  toolPermissionContext: {
    mode: "default"            // ← ComponentB 订阅
  },
  tasks: {...}                 // ← 无人订阅
}

状态变化:tasks 更新了
        │
        ▼
store.setState(prev => ({...prev, tasks: newTasks}))
        │
        ▼
触发所有 listeners(包括 A 和 B 的)
        │
        ├─────────────────┬─────────────────┐
        ▼                 ▼                 ▼
   ComponentA         ComponentB       ComponentC
   (订阅 statusLine)   (订阅 mode)       (无订阅)
        │                 │                 │
        ▼                 ▼                 ▼
   get() 执行          get() 执行         不执行
   selector(s=>s.      selector(s=>s.      
   statusLineText)     toolPermissionContext.mode)
        │                 │
        ▼                 ▼
   返回 "Ready"        返回 "default"
   (和上次相同)         (和上次相同)
        │                 │
        ▼                 ▼
   Object.is("Ready",   Object.is("default",
   "Ready") === true    "default") === true
        │                 │
        ▼                 ▼
   React 跳过重渲染    React 跳过重渲染
   
   ✅ 只有真正使用 tasks 的组件会重渲染(如果有的话)

2. useSetAppState —— 只更新,不订阅

// 使用方式
const setAppState = useSetAppState()

// 在事件处理中使用
const handleClick = () => {
  setAppState(prev => ({...prev, count: prev.count + 1}))
}

为什么需要这个 Hook?

export function useSetAppState() {
  return useAppStore().setState  // 直接返回 setState 函数
}

// 关键特性:不调用 useSyncExternalStore
// 所以这个组件不会因为状态变化而重渲染!

使用场景对比:

❌ 错误:用 useAppState 获取更新函数
const setAppState = useAppState(s => s.setState)  // 不存在!
// 而且这会订阅整个状态树,任何变化都重渲染

✅ 正确:useSetAppState
const setAppState = useSetAppState()
// 只获取函数,不建立订阅
// 组件永远不因状态变化重渲染

典型应用场景:

// 按钮组件:只需要发送命令,不需要显示状态
function IncrementButton() {
  const setAppState = useSetAppState()  // 稳定引用,永不变化
  
  return (
    <button onClick={() => setAppState(prev => ({
      ...prev,
      count: prev.count + 1
    }))}>
      +1
    </button>
  )
}
// 这个组件只渲染一次,之后永远不重渲染(因为没订阅任何状态)

3. useAppStateStore —— 直接访问 store

// 使用方式
const store = useAppStateStore()

// 可以在非 React 代码中使用
useEffect(() => {
  const timer = setInterval(() => {
    const currentState = store.getState()  // 直接读取
    console.log(currentState.statusLineText)
  }, 1000)
  
  return () => clearInterval(timer)
}, [store])

用途:

1. 传递给非 React 代码(工具函数、类实例)
   const api = new ApiClient(store)

2. 在 useEffect 中读取最新状态(不订阅)
   useEffect(() => {
     const state = store.getState()
     // 基于当前状态执行副作用
   }, [dependency])

3. 手动控制订阅(高级场景)
   useEffect(() => {
     return store.subscribe(() => {
       // 自定义逻辑,不触发 React 重渲染
     })
   }, [store])

AppStateProvider 详解

export function AppStateProvider({ 
  children, 
  initialState, 
  onChangeAppState 
}) {
  // 🔒 防止嵌套(一个应用只能有一个 store)
  const hasAppStateContext = useContext(HasAppStateContext)
  if (hasAppStateContext) {
    throw new Error("AppStateProvider can not be nested...")
  }

  // 🏭 创建 store(只执行一次)
  const [store] = useState(() => 
    createStore(initialState ?? getDefaultAppState(), onChangeAppState)
  )

  // 🎧 设置变更监听(文件监视器等)
  useEffect(() => {
    const { toolPermissionContext } = store.getState()
    if (shouldDisableBypassMode(toolPermissionContext)) {
      store.setState(prev => /* 禁用 bypass 模式 */)
    }
  }, [])

  // 🌳 提供上下文
  return (
    <HasAppStateContext.Provider value={true}>
      <AppStoreContext.Provider value={store}>
        <MailboxProvider>
          <VoiceProvider>{children}</VoiceProvider>
        </MailboxProvider>
      </AppStoreContext.Provider>
    </HasAppStateContext.Provider>
  )
}

Context 嵌套结构:

<HasAppStateContext.Provider value={true}>  ← 标记"已有 Provider"
  <AppStoreContext.Provider value={store}>   ← 实际 store 实例
    <MailboxProvider>                         ← 邮件上下文
      <VoiceProvider>                         ← 语音上下文(可选)
        {children}                            ← 你的应用组件
      </VoiceProvider>
    </MailboxProvider>
  </AppStoreContext.Provider>
</HasAppStateContext.Provider>

完整使用示例

// 1. 在应用入口包裹 Provider
function App() {
  return (
    <AppStateProvider>
      <MainLayout />
    </AppStateProvider>
  )
}

// 2. 在组件中订阅状态
function StatusBar() {
  // ✅ 精准订阅:只监听这两个字段
  const statusText = useAppState(s => s.statusLineText)
  const isConnected = useAppState(s => s.replBridgeConnected)
  
  return (
    <div className={isConnected ? 'green' : 'red'}>
      {statusText}
    </div>
  )
}

// 3. 只更新不订阅的组件
function RefreshButton() {
  // ✅ 稳定引用,不触发重渲染
  const setAppState = useSetAppState()
  
  return (
    <button onClick={() => setAppState(prev => ({
      ...prev,
      lastRefresh: Date.now()
    }))}>
      Refresh
    </button>
  )
}

// 4. 直接操作 store(高级)
function AutoSave() {
  const store = useAppStateStore()
  
  useEffect(() => {
    const interval = setInterval(() => {
      const state = store.getState()
      localStorage.setItem('draft', JSON.stringify(state.draft))
    }, 5000)
    
    return () => clearInterval(interval)
  }, [store])
  
  return null
}

总结:三个 Hook 的选择指南

Hook 用途 订阅状态? 重渲染?
useAppState(selector) 读取并订阅特定字段 ✅ 是 仅当 selector 返回值变化时
useSetAppState() 获取更新函数 ❌ 否 从不(稳定引用)
useAppStateStore() 直接访问 store 实例 ❌ 否 从不(稳定引用)

核心设计原则:

精准订阅 = 性能
  useAppState(s => s.specificField)  // 只关心这个字段
  
避免过度订阅 = 性能  
  ❌ useAppState(s => s)  // 订阅整个状态树
  ✅ 用 useSetAppState 获取更新函数
  
useSyncExternalStore = 安全
  处理并发渲染、SSR、状态一致性


参考相关资料阅读1

- [`src/state/AppStateStore.ts`](src/state/AppStateStore.ts) - 应用状态类型定义

Claude Code 的状态类型非常复杂,包含400+字段:

┌─────────────────────────────────────────────────────────────────────────┐
│                         AppState 核心架构                                │
├─────────────────────────────────────────────────────────────────────────┤
│  1. 模型与设置 (Model & Settings)                                       │
│     ├── settings: SettingsJson           # 用户配置                      │
│     ├── mainLoopModel: ModelSetting      # 当前主模型                    │
│     ├── mainLoopModelForSession: ModelSetting  # 会话级模型覆盖          │
│     ├── thinkingEnabled: boolean         # 深度思考模式                  │
│     ├── effortValue: EffortValue         # 工作量/复杂度设置             │
│     └── kairosEnabled: boolean           # AI助手模式开关                │
├─────────────────────────────────────────────────────────────────────────┤
│  2. 任务系统 (Task System)                                              │
│     ├── tasks: { [taskId: string]: TaskState }  # 所有任务字典         │
│     ├── foregroundedTaskId: string       # 前台显示的任务                │
│     ├── viewingAgentTaskId: string       # 正在查看的队友任务            │
│     ├── coordinatorTaskIndex: number     # 协调器面板选择索引            │
│     ├── agentNameRegistry: Map<string, AgentId>  # 代理名称映射          │
│     └── agentDefinitions: AgentDefinitionsResult  # 代理定义列表          │
├─────────────────────────────────────────────────────────────────────────┤
│  3. 权限与安全 (Permissions & Security)                                 │
│     ├── toolPermissionContext: ToolPermissionContext  # 工具权限上下文   │
│     ├── denialTracking: DenialTrackingState  # 拒绝追踪(YOLO模式)      │
│     ├── workerSandboxPermissions.queue   # 沙箱权限请求队列              │
│     ├── pendingWorkerRequest             # 待处理的工具权限请求          │
│     └── pendingSandboxRequest            # 待处理的沙箱权限请求          │
├─────────────────────────────────────────────────────────────────────────┤
│  4. 远程与会话 (Remote & Session)                                       │
│     ├── remoteSessionUrl: string         # 远程会话URL                   │
│     ├── remoteConnectionStatus           # 连接状态                     │
│     ├── remoteBackgroundTaskCount: number # 远程后台任务数               │
│     ├── replBridgeEnabled: boolean       # 桥接模式开关                  │
│     ├── replBridgeConnected: boolean     # 桥接连接状态                  │
│     ├── replBridgeSessionActive: boolean # 会话激活状态                  │
│     ├── replBridgeSessionUrl: string     # claude.ai 会话URL             │
│     ├── ultraplanSessionUrl: string      # Ultraplan 会话URL             │
│     ├── ultraplanLaunching: boolean      # 是否正在启动                  │
│     └── isUltraplanMode: boolean         # 是否处于Ultraplan模式         │
├─────────────────────────────────────────────────────────────────────────┤
│  5. MCP/插件系统 (MCP & Plugins)                                        │
│     ├── mcp.clients: MCPServerConnection[] # MCP服务器连接                 │
│     ├── mcp.tools: Tool[]                # 可用工具列表                  │
│     ├── mcp.commands: Command[]            # MCP命令                       │
│     ├── mcp.resources                    # 服务器资源                    │
│     ├── plugins.enabled: LoadedPlugin[]  # 已启用插件                    │
│     ├── plugins.disabled: LoadedPlugin[] # 已禁用插件                    │
│     ├── plugins.errors: PluginError[]    # 插件错误                      │
│     └── plugins.needsRefresh: boolean    # 需要刷新标记                  │
├─────────────────────────────────────────────────────────────────────────┤
│  6. UI/视图状态 (UI & View State)                                       │
│     ├── expandedView                     # 展开视图(tasks/teammates)   │
│     ├── viewSelectionMode                # 视图选择模式                 │
│     ├── footerSelection                    # 底部栏选中项                │
│     ├── isBriefOnly: boolean             # 简洁模式                       │
│     ├── statusLineText: string           # 状态栏文本                    │
│     ├── spinnerTip: string               # 加载提示                       │
│     ├── activeOverlays                   # 活跃弹窗集合(Esc键协调)      │
│     ├── verbose: boolean                 # 详细日志模式                   │
│     └── showTeammateMessagePreview       # 队友消息预览                  │
├─────────────────────────────────────────────────────────────────────────┤
│  7. 团队/多代理 (Team & Multi-Agent)                                    │
│     ├── teamContext                      # 团队上下文(swarm模式)       │
│     │   ├── teamName                     # 团队名称                     │
│     │   ├── leadAgentId                  # 队长ID                       │
│     │   ├── selfAgentId                  # 自身ID(队员)              │
│     │   ├── isLeader: boolean            # 是否为队长                  │
│     │   └── teammates                    # 队友列表                     │
│     └── standaloneAgentContext           # 独立代理上下文(非swarm)     │
├─────────────────────────────────────────────────────────────────────────┤
│  8. 终端/Tmux集成 (Terminal Integration)                                │
│     ├── tungstenActiveSession            # 当前tmux会话                  │
│     ├── tungstenLastCapturedTime         # 最后截图时间                  │
│     ├── tungstenLastCommand              # 最后发送的命令                │
│     ├── tungstenPanelVisible             # 面板可见性                    │
│     └── tungstenPanelAutoHidden          # 自动隐藏标记                  │
├─────────────────────────────────────────────────────────────────────────┤
│  9. 浏览器工具 (WebBrowser Tool - "Bagel")                              │
│     ├── bagelActive: boolean             # 浏览器是否活跃                 │
│     ├── bagelUrl: string                 # 当前页面URL                   │
│     └── bagelPanelVisible: boolean       # 浏览器面板可见性                │
├─────────────────────────────────────────────────────────────────────────┤
│ 10. 计算机使用MCP (Computer Use MCP - "Chicago")                        │
│     └── computerUseMcpState              # 屏幕控制状态                  │
│         ├── allowedApps                  # 允许的应用列表                 │
│         ├── grantFlags                   # 剪贴板/系统键权限              │
│         ├── lastScreenshotDims           # 最后截图尺寸                   │
│         └── selectedDisplayId            # 选中的显示器                   │
├─────────────────────────────────────────────────────────────────────────┤
│ 11. 输入与建议 (Input & Suggestions)                                      │
│     ├── promptSuggestion                 # 输入建议状态                  │
│     │   ├── text                         # 建议文本                     │
│     │   ├── promptId                     # 建议类型                     │
│     │   ├── shownAt                      # 显示时间戳                   │
│     │   └── acceptedAt                   # 接受时间戳                   │
│     ├── speculation                      # 推测执行状态                  │
│     │   ├── status                       # idle/active                  │
│     │   ├── messagesRef                  # 消息引用(可变优化)           │
│     │   └── abort                        # 取消函数                    │
│     └── speculationSessionTimeSavedMs    # 节省时间统计                   │
├─────────────────────────────────────────────────────────────────────────┤
│ 12. 通知与消息 (Notifications & Messaging)                                │
│     ├── notifications.current            # 当前通知                      │
│     ├── notifications.queue              # 通知队列                      │
│     ├── inbox.messages                   # 收件箱消息                   │
│     └── elicitation.queue                # 请求澄清队列                   │
├─────────────────────────────────────────────────────────────────────────┤
│ 13. 文件与历史 (File & History)                                         │
│     ├── fileHistory                      # 文件历史快照                  │
│     └── attribution                      # 代码归属状态                  │
├─────────────────────────────────────────────────────────────────────────┤
│ 14. 待办事项 (Todos)                                                    │
│     └── todos: { [agentId: string]: TodoList }  # 各代理的待办列表       │
├─────────────────────────────────────────────────────────────────────────┤
│ 15. 会话生命周期 (Session Lifecycle)                                      │
│     ├── initialMessage                   # 初始消息(CLI参数)            │
│     ├── pendingPlanVerification          # 待验证的计划                   │
│     ├── sessionHooks                     # 会话钩子                      │
│     ├── authVersion: number              # 认证版本(触发重取)          │
│     ├── fastMode: boolean                # 快速模式                       │
│     └── advisorModel: string             # 顾问模型                       │
├─────────────────────────────────────────────────────────────────────────┤
│ 16. 其他/辅助 (Misc)                                                    │
│     ├── agent: string                    # CLI指定的代理名称             │
│     ├── companionReaction                # 伙伴表情反应                   │
│     ├── companionPetAt                   # 最后互动时间                   │
│     ├── skillImprovement                 # 技能改进建议                   │
│     └── remoteAgentTaskSuggestions       # 远程任务建议                   │
└─────────────────────────────────────────────────────────────────────────┘

主要字段统计

总字段数: ~400+
核心类别: 16个
主要字段: ~60个(上表列出)
关键状态对象: 8个(tasks, mcp, plugins, teamContext, notifications, 
                  speculation, promptSuggestion, computerUseMcpState)

这个设计支持:

  • 单用户会话:所有状态集中管理

  • 多代理协作teamContext + tasks 字典

  • 远程控制replBridge* + remote* 字段群

  • 工具生态mcp + plugins 双系统

  • AI功能speculation + thinkingEnabled + promptSuggestion

参考阅读2

核心架构全

┌─────────────────────────────────────────────────────────┐
│                    createStore<T>                        │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │   state     │  │  listeners  │  │    onChange     │  │
│  │  (mutable)  │  │   (Set)     │  │   (callback)    │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
│                                                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │  getState() │  │  setState()  │  │   subscribe()   │  │
│  │   (read)    │  │  (write)    │  │  (subscribe)    │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
└─────────────────────────────────────────────────────────┘
                              │
                              ▼
                    ┌─────────────────┐
                    │   AppStateStore   │
                    │   (全局单例)      │
                    └─────────────────┘
                              │
                              ▼
        ┌─────────────────────────────────────┐
        │        React 集成层 (AppState.tsx)    │
        │  ┌─────────────┐  ┌─────────────┐    │
        │  │useAppState  │  │useSetAppState│   │
        │  │  (订阅)     │  │  (仅写入)    │    │
        │  └─────────────┘  └─────────────┘    │
        │  ┌─────────────┐  ┌─────────────┐    │
        │  │useAppStateStore│ │useAppStateMaybe│ │
        │  │  (原始store) │  │  (安全访问)   │    │
        │  └─────────────┘  └─────────────┘    │
        └─────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────┐
│                    AppState                         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │  核心设置   │  │  任务系统   │  │  插件系统   │    │
│  │  (settings) │  │  (tasks)    │  │  (plugins)  │    │
│  └─────────────┘  └─────────────┘  └─────────────┘    │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │  MCP系统    │  │  团队协作   │  │  桥接系统   │    │
│  │  (mcp)      │  │  (team)     │  │  (bridge)   │    │
│  └─────────────┘  └─────────────┘  └─────────────┘    │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │  UI状态     │  │  权限系统   │  │  超级计划   │    │
│  │  (ui)       │  │  (perms)    │  │  (ultra)    │    │
│  └─────────────┘  └─────────────┘  └─────────────┘    │
└─────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────┐
│                状态变更处理器                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │onChangeAppState││团队视图助手  │  │  状态选择器 │    │
│  │(全局变更)    │  │(teammateView)│ │(selectors)  │    │
│  └─────────────┘  └─────────────┘  └─────────────┘    │
└─────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────┐
│                   组件层 (React)                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │UI组件       │  │权限组件     │  │任务组件     │    │
│  │(Messages)   │  │(Permissions)│ │(Tasks)      │    │
│  └─────────────┘  └─────────────┘  └─────────────┘    │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │设置组件     │  │MCP组件      │  │桥接组件     │    │
│  │(Settings)   │  │(MCP)        │ │(Bridge)     │    │
│  └─────────────┘  └─────────────┘  └─────────────┘    │
└─────────────────────────────────────────────────────────┘

参考阅读3

订阅在Claude Code React 中的具体实现

const listeners = new Set<Listener>()  // 订阅者集合

subscribe: (listener: Listener) => () => void  // 订阅方法

React 上下文订阅
// src/state/AppState.tsx
export function useAppState<T>(selector: (state: AppState) => T): T {
  const store = useAppStore()
  const get = React.useMemo(() => () => {
    const state = store.getState()
    const selected = selector(state)
    return selected
  }, [selector, store])
  
  // 关键:使用 store.subscribe 实现订阅
  return useSyncExternalStore(store.subscribe, get, get)
}
组件订阅示例
// src/components/StatusLine.tsx
function StatusLine() {
  // 订阅特定状态字段
  const statusLineText = useAppState(s => s.statusLineText)
  const permissionMode = useAppState(s => s.toolPermissionContext.mode)
  const isConnected = useAppState(s => s.replBridgeConnected)
  
  // 只有当这些字段变化时组件才会重新渲染
  return (
    <div>Status: {statusLineText} | Mode: {permissionMode} | Connected: {isConnected}</div>
  )
}
团队视图订阅
// src/state/teammateViewHelpers.ts
export function enterTeammateView(taskId: string, setAppState: any): void {
  setAppState(prev => {
    // 更新状态会触发所有订阅者的重新渲染
    return {
      ...prev,
      viewingAgentTaskId: taskId,
      viewSelectionMode: 'viewing-agent'
    }
  })
}

参考阅读4

通知 (Notification) 的作用

核心概念

onChange?: OnChange<T>  // 状态变更回调
for (const listener of listeners) listener()  // 通知所有订阅者

全局状态变更通知

权限模式变更通知
// src/state/onChangeAppState.ts
export function onChangeAppState({ newState, oldState }: {
  newState: AppState
  oldState: AppState
}) {
  // 检测权限模式变化
  const prevMode = oldState.toolPermissionContext.mode
  const newMode = newState.toolPermissionContext.mode
  
  if (prevMode !== newMode) {
    // 通知外部系统(CCR/SDK)
    notifySessionMetadataChanged({
      permission_mode: newExternal,
      is_ultraplan_mode: isUltraplan ? true : null,
    })
    
    // 通知内部监听器
    notifyPermissionModeChanged(newMode)
  }
}
模型设置变更通知
// 模型变更时通知设置系统
if (newState.mainLoopModel !== oldState.mainLoopModel) {
  if (newState.mainLoopModel === null) {
    updateSettingsForSource('userSettings', { model: undefined })
    setMainLoopModelOverride(null)
  } else {
    updateSettingsForSource('userSettings', { model: newState.mainLoopModel })
    setMainLoopModelOverride(newState.mainLoopModel)
  }
}
UI 设置持久化通知
// UI 状态变更时持久化到磁盘
if (newState.expandedView !== oldState.expandedView) {
  const showExpandedTodos = newState.expandedView === 'tasks'
  const showSpinnerTree = newState.expandedView === 'teammates'
  
  saveGlobalConfig(current => ({
    ...current,
    showExpandedTodos,
    showSpinnerTree,
  }))
}

参考阅读5

实际应用场景

实时协作场景

// 多个组件订阅同一个状态
const TeammateView = () => {
  const viewingAgent = useAppState(s => s.viewingAgentTaskId)
  // 当 viewingAgent 变化时,团队视图组件会立即更新
}

const TaskList = () => {
  const tasks = useAppState(s => s.tasks)
  // 当 tasks 变化时,任务列表会立即更新
}

const StatusIndicator = () => {
  const connectionStatus = useAppState(s => s.replBridgeConnected)
  // 当连接状态变化时,状态指示器会立即更新
}

性能优化

// 选择性订阅避免不必要的重渲染
const MyComponent = () => {
  // 只订阅需要的字段,其他状态变化不会触发重渲染
  const isBrief = useAppState(s => s.isBriefOnly)
  const model = useAppState(s => s.mainLoopModel)
  
  // 这两个字段的变化才会触发组件重渲染
  return <div>{isBrief ? 'Brief mode' : 'Normal mode'} - {model}</div>
}

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐