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 = 进入终态。