UI / REPL Layer 模块对比分析
2026/4/27大约 4 分钟
UI / REPL Layer 模块对比分析
1. 模块边界
这里讨论的是终端交互层如何承载对话、工具进度、权限弹窗、模型切换、输入框、会话导航,以及它与底层 session / query / server 的耦合方式。
2. Claude Code:REPL 作为主产品形态
2.1 关键源码路径
claude-code-rev/src/entrypoints/cli.tsxclaude-code-rev/src/replLauncher.tsxclaude-code-rev/src/screens/REPL.tsxclaude-code-rev/src/components/App.jsclaude-code-rev/src/components/PromptInput/PromptInput.tsxclaude-code-rev/src/components/VirtualMessageList.tsxclaude-code-rev/src/components/permissions/*claude-code-rev/src/services/mcp/MCPConnectionManager.tsx
2.2 模块职责
entrypoints/cli.tsx负责 CLI 启动分流。它不仅进入 REPL,也处理 bridge、daemon、background session、headless print 等多种 fast path。replLauncher.tsx负责把App和REPL装载到 Ink root。screens/REPL.tsx是交互核心,管理消息渲染、hooks、权限请求、MCP 弹窗、session restore、background task、teammate view、IDE 集成、cost / compact / survey 等大量状态。PromptInput.tsx是另一大核心节点,承担输入缓冲、历史、slash command、模型切换、permission mode 切换、speculation、队列命令和多种键盘行为。
2.3 实现方式
Claude Code 的 UI 层是“主流程承载层”,而不是薄客户端:
- CLI 入口决定是否进入 REPL、print、bridge、daemon 等模式。
- 进入 REPL 后,
REPL.tsx直接持有大量会话态和运行时连接。 - 输入层和消息层都由 React/Ink 组件树承载,并与 permissions、MCP、agent、session storage、query loop 高度耦合。
- 因为 REPL 是主产品形态,所以许多系统能力都在这里有一等 UI:sandbox request、prompt dialog、elicitation、background task、teammate、survey、IDE onboarding 等。
2.4 设计特点
- UI 能力非常完整,几乎是终端里的“应用壳”。
- 与核心运行时耦合很深,很多业务能力通过组件和 hooks 直接接进 REPL。
- 既支持交互式富终端,也支持非交互/headless 路径,但 REPL 是中心。
3. Opencode:TUI 与非交互 CLI 并行的前端层
3.1 关键源码路径
opencode/packages/opencode/src/cli/bootstrap.tsopencode/packages/opencode/src/cli/ui.tsopencode/packages/opencode/src/cli/cmd/run.tsopencode/packages/opencode/src/cli/cmd/tui/app.tsxopencode/packages/opencode/src/cli/cmd/tui/routes/session/index.tsxopencode/packages/opencode/src/cli/cmd/tui/worker.tsopencode/packages/opencode/src/server/routes/tui.ts
3.2 模块职责
cli/ui.ts提供基础的命令行文本输出能力,服务于非交互run等命令。cli/cmd/run.ts是典型的非交互路径,会把不同工具结果格式化为 block / inline 输出。cli/cmd/tui/app.tsx则是交互式 TUI 壳,使用@opentui/solid、route、dialog、toast、theme、SDK provider 等上下文组织界面。routes/session/index.tsx是 session 主视图,负责 transcript、sidebar、permission、question、footer、prompt、timeline 等界面。tui/worker.ts和server/routes/tui.ts说明 TUI 不是纯本地组件树,还通过 worker、RPC、server route、event stream 接到底层 server。
3.3 实现方式
Opencode 的 UI 层分成两种正交路径:
- 非交互 CLI:
run.ts直接格式化输出,适合脚本与流水线。 - 交互式 TUI:
app.tsx+ route/session/dialog 组成更完整的终端前端,通过 SDK / server event 与后端同步状态。
这和 Claude Code 的差别在于,Opencode 没把所有形态都塞进单一 REPL 主屏,而是保持 TUI 与普通 CLI 两条并行产品线。
3.4 设计特点
- TUI 使用 Solid + OpenTUI,界面组织更像“前后端分离的终端前端”。
tui/worker.ts会订阅 server 事件并通过 RPC 转发,说明 TUI 和后端状态同步是显式设计目标。run.ts仍保留清晰的文本模式,因此自动化集成路径更直接。
4. 核心差异
| 维度 | Claude Code | Opencode |
|---|---|---|
| 主交互形态 | REPL 是主产品壳 | 非交互 CLI 与交互式 TUI 并存 |
| UI 技术栈 | React + Ink | Solid + OpenTUI |
| 状态耦合方式 | REPL 直接吃大量运行时状态与 hooks | TUI 经 SDK / worker / server route 同步状态 |
| 非交互支持 | 有,但 REPL 仍是中心 | run.ts 等非交互路径是一等能力 |
| 设计风格 | 富交互单体终端应用 | 分层更明显的 CLI + TUI 双路径 |
5. 设计取舍
5.1 Claude Code 的取舍
- 目标是让终端本身成为完整工作台。
- 因此 REPL 里聚合了权限、MCP、agent、session、IDE、background tasks 等大量能力。
- 好处是交互完整;代价是 REPL 本身极重。
5.2 Opencode 的取舍
- 目标是同时兼顾“脚本友好 CLI”和“现代终端 TUI”。
- 因此把简单输出留给
run.ts,把丰富交互交给 TUI 路由层和 worker。 - 好处是边界更清晰;代价是交互层分散在 CLI / TUI / server route 多个入口。
6. 结论
Claude Code 的 UI / REPL 层是核心产品外壳,本质上是一个终端应用平台;Opencode 的 UI / REPL 层则是双形态前端系统,一边保留脚本友好的 CLI,一边通过 TUI 提供更丰富交互。前者强在一体化体验,后者强在界面边界清晰与接入方式多样。