跳转至

Data | 状态机图

Claude Code 里的所有"状态"都用 mermaid 状态图描述。 配合sequence-diagrams.md 看时序。


1. 会话生命周期状态机

stateDiagram-v2
    [*] --> Created: bun 启动

    Created --> Loading: launchRepl
    Loading: 加载 settings.json
    Loading: 加载 MCP 配置
    Loading: 初始化 telemetry
    Loading: 启动 prefetch
    Loading --> Ready: 初始化完成

    Ready --> WaitingInput: 空闲
    WaitingInput: 用户键入
    WaitingInput --> Thinking: 提交 prompt
    WaitingInput --> Command: 输入 /
    WaitingInput --> VimMode: Esc 进入 vim

    Command --> WaitingInput: 取消
    Command --> Running: 执行命令

    VimMode --> WaitingInput: Esc 退出

    Thinking: LLM 推理中
    Thinking --> Streaming: 收到首个 token
    Thinking --> Error: API error

    Streaming: 流式响应中
    Streaming --> ToolPending: 收到 tool_use
    Streaming --> Done: 收到 end_turn
    Streaming --> Compressing: token 接近上限

    ToolPending: 等待工具执行
    ToolPending --> PermissionRequest: 需要授权
    ToolPending --> Executing: 自动允许

    PermissionRequest: 弹 PermissionRequest
    PermissionRequest --> Executing: 用户批准
    PermissionRequest --> ToolDenied: 用户拒绝

    Executing: 工具执行中
    Executing --> Backgrounded: 用户后台化
    Backgrounded --> Executing: 用户恢复
    Executing --> ToolDone: 工具完成

    ToolDone: 工具结果
    ToolDone --> Thinking: 注入消息继续
    ToolDone --> Compressing: token 累积

    Compressing: 压缩中
    Compressing --> Thinking: 压缩完成

    Done: 等待下一轮
    Done --> WaitingInput: 用户继续

    Running: 命令执行中
    Running --> Ready: 完成

    Error: 错误状态
    Error --> WaitingInput: 重试
    Error --> [*]: 退出

    ToolDenied: 拒绝结果
    ToolDenied --> Thinking: 注入 denial 继续

    Ready --> Resuming: /resume
    Resuming: 加载历史
    Resuming --> WaitingInput: 加载完成

    Ready --> [*]: /exit
    Ready --> [*]: 用户 Ctrl+D

2. 工具权限状态机

stateDiagram-v2
    [*] --> Pending: 工具调用

    Pending --> Validating: validate(input)
    Validating --> DeniedByValidation: 校验失败
    Validating --> PermissionCheck: 校验通过

    DeniedByValidation: is_error: true
    DeniedByValidation --> [*]: 注入消息

    PermissionCheck: matchingRuleForInput
    PermissionCheck --> Allowed: 规则 allow
    PermissionCheck --> Denied: 规则 deny
    PermissionCheck --> Asking: 规则 ask 或无

    Allowed: 直接执行
    Allowed --> Executing

    Denied: 拒绝
    Denied --> [*]: 注入 denial

    Asking: 弹 PermissionRequest
    Asking --> UserDecision: 等待用户

    UserDecision --> Approved: 批准
    UserDecision --> Rejected: 拒绝
    UserDecision --> RuleUpdated: "always allow"
    UserDecision --> RejectedAndSkipped: 拒绝并跳过

    Approved: 继续
    Approved --> Executing
    RuleUpdated: 写 settings.json
    RuleUpdated --> Executing
    Rejected --> DeniedResult
    DeniedResult: 注入 denial
    DeniedResult --> [*]
    RejectedAndSkipped --> DeniedResult

    Executing: 工具运行
    Executing --> YieldingProgress: yield 中间状态
    YieldingProgress --> Executing
    Executing --> Completed: return ToolResult

    Completed --> [*]: 注入到 messages

3. Task 任务状态机

stateDiagram-v2
    [*] --> Created: 创建任务

    Created --> Pending: 排队
    Pending --> Running: 调度启动
    Pending --> Killed: 取消

    Running: 任务执行中
    Running --> Yielding: async generator yield
    Yielding --> Running
    Running --> Completed: 正常完成
    Running --> Failed: 异常
    Running --> Killed: 用户中断
    Running --> Backgrounded: 转入后台

    Backgrounded: 后台运行
    Backgrounded --> Running: 重新前台
    Backgrounded --> Killed: 用户取消
    Backgrounded --> Completed: 自然完成
    Backgrounded --> Failed: 后台异常

    Completed: 已完成
    Completed --> [*]: 清理

    Failed: 失败
    Failed --> [*]: 清理

    Killed: 已中断
    Killed --> [*]: 清理

    note right of Completed
        isTerminalTaskStatus() = true
    end note

    note right of Failed
        isTerminalTaskStatus() = true
    end note

    note right of Killed
        isTerminalTaskStatus() = true
    end note

4. 压缩生命周期

stateDiagram-v2
    [*] --> Healthy: 启动

    Healthy: token < 70%
    Healthy --> Warning: 70% < token < 85%

    Warning: token 在 70-85%
    Warning --> Healthy: 压缩后回落
    Warning --> Critical: 继续增长

    Critical: token 在 85-95%
    Critical --> Warning: microCompact 后回落
    Critical --> AutoCompacting: 达到 95%

    AutoCompacting: autoCompact 触发
    AutoCompacting --> Grouping: 分组
    Grouping --> Summarizing: 摘要
    Summarizing --> Rebuilding: 重建 messages
    Rebuilding --> Cleanup: postCompactCleanup
    Cleanup --> Healthy: 回到健康

    Healthy --> [*]: /exit

5. MCP 连接状态机

stateDiagram-v2
    [*] --> Disconnected: 启动

    Disconnected --> Connecting: addServer
    Connecting: spawn process / fetch
    Connecting --> Handshaking: TCP/stdio 建立
    Connecting --> Failed: 网络错误
    Failed --> Connecting: 重试

    Handshaking: initialize 协议
    Handshaking --> Ready: 成功
    Handshaking --> Failed: 协议错误

    Ready: 已连接
    Ready --> Calling: 调 tool
    Calling --> Ready: 收到 result
    Calling --> Error: 错误

    Error: 单次错误
    Error --> Ready: 继续
    Error --> Disconnected: 持续错误

    Ready --> Disconnected: 关闭
    Ready --> Reconnecting: 网络断开

    Reconnecting: 重连
    Reconnecting --> Connecting: 成功
    Reconnecting --> Failed: 重试失败

    Disconnected --> [*]: 移除 server

6. 键位 chord 状态机

stateDiagram-v2
    [*] --> Idle

    Idle: 等按键
    Idle --> WaitingNext: 收到 Ctrl+K
    Idle --> Triggered: 收到单键(直接触发)
    Idle --> Idle: 普通字符透传

    WaitingNext: chord buffer 中
    WaitingNext --> Triggered: 收到预期第二键
    WaitingNext --> Idle: 超时(>1.5s)
    WaitingNext --> Idle: 收到其他键(重置)

    Triggered: 触发回调
    Triggered --> Idle: 回调完成

7. 主题切换状态机

stateDiagram-v2
    [*] --> NoSetting: 启动

    NoSetting: 没设置过
    NoSetting --> AutoDetected: 读取系统主题
    AutoDetected --> Resolved: 解析为 light/dark

    Resolved: 当前主题
    Resolved --> Previewing: 用户选主题

    Previewing: preview 模式
    Previewing --> Previewing: 选其他主题
    Previewing --> Confirmed: 用户确认
    Previewing --> Cancelled: 用户取消

    Confirmed: 写入 settings
    Confirmed --> Resolved

    Cancelled: 撤销 preview
    Cancelled --> Resolved

8. Stream 事件状态机

stateDiagram-v2
    [*] --> Idle: 流开始

    Idle --> MessageStart: 收到 message_start
    MessageStart: message 初始化

    MessageStart --> BlockStart: 收到 content_block_start
    BlockStart: 文本/tool_use/thinking block

    BlockStart --> BlockDelta: 收到 content_block_delta
    BlockDelta: 增量数据(token)
    BlockDelta --> BlockDelta: 继续
    BlockDelta --> BlockStop: 收到 content_block_stop

    BlockStop --> BlockStart: 下一个 block
    BlockStop --> MessageDelta: 最后一个 block 结束

    MessageDelta: message_delta
    MessageDelta --> MessageStop: 收到 message_stop

    MessageStop: 完成
    MessageStop --> [*]: 流结束

9. 命令执行状态机

stateDiagram-v2
    [*] --> Typed: 用户输入 /xxx

    Typed: 完整 / 命令
    Typed --> Parsing: 解析

    Parsing: 解析参数
    Parsing --> Validated: 成功
    Parsing --> Invalid: 参数错误

    Invalid: 显示错误
    Invalid --> Typed: 重新输入
    Invalid --> [*]: 取消

    Validated: 命令识别
    Validated --> PermissionCheck: 检查权限

    PermissionCheck --> Allowed: 允许
    PermissionCheck --> Denied: 拒绝

    Allowed: 执行命令
    Allowed --> Running
    Running: 命令运行中
    Running --> Completed: 完成
    Running --> Failed: 失败

    Completed: 命令成功
    Completed --> [*]

    Failed: 命令失败
    Failed --> [*]

    Denied: 拒绝
    Denied --> [*]

10. 关键洞察

10.1 Claude Code 几乎所有"长流程"都是状态机

  • 会话生命周期
  • 工具调用
  • 任务执行
  • 压缩
  • MCP 连接
  • 键位
  • 主题
  • Stream 事件
  • 命令

10.2 状态机的价值

  • 明确所有可能状态(防止"未定义状态")
  • 明确状态转换条件(防止"非法转换")
  • 便于测试(每个状态可独立测)
  • 便于排错("现在卡在哪个状态")

10.3 状态机 + 类型系统

TypeScript 的 discriminated union + 类型守卫 = 状态机的类型安全
isTerminalTaskStatus(status): status is 'completed' | 'failed' | 'killed'状态机的类型化

10.4 异步生成器 + 状态机 = 天作之合

每个 async function* 都是一个状态机。
yield = 状态转换触发点。
return = 进入终态。