终端里的 Coding Agent 正从“打印几行文本”变成一套持续更新的工作台:模型在流式输出,工具在并发执行,审批框等待按键,diff、任务进度和输入区还要同时保持可见。这个界面没有浏览器 DOM,却承受着接近前端应用的状态复杂度。

Codex、grok-build,以及 CodeWhale(原 DeepSeek TUI)都选择了 Rust 框架 Ratatui。源码给出的答案更具体:它把终端最通用、最难反复造好的渲染问题收住,又把 Agent 最需要差异化的控制流留给应用。

打开网易新闻 查看精彩图片

先校正一个名字

用户熟悉的 DeepSeek TUI 已经更名为 CodeWhale,仓库归属 Hmbown,是社区项目。更名文档还说明旧命令兼容层已在 v0.9 移除,因此不能把它写成 DeepSeek 官方客户端。本文沿用“CodeWhale(原 DeepSeek TUI)”这个准确称呼。

另外,三者并没有使用完全相同的 Ratatui。Codex 依赖 0.29 API,却把 crates.io 版本 patch 到固定的定制 revision,并开启 scrolling regions、backend writer、rendered line info、WidgetRef 等 feature。grok-build 使用上游 0.29,同时维护自己的 inline 和 textarea crate。CodeWhale 当前使用 Ratatui 0.30 与 Crossterm 0.29。

所以,共同选择不等于同一种实现。

Ratatui 到底负责哪一层

Ratatui 是即时模式渲染框架。Agent 应用收到模型增量、工具结果、键盘输入或 resize 事件后,先更新自己的 App State,再调用 Terminal::draw。当前源码里,真实入口是 draw → trydraw,并没有一些旧资料提到的 drawwith。

try_draw 会创建本帧的 frame。Layout 把终端区域切成多个 Rect,Widget 直接把文字、样式和符号写入 current Buffer。Ratatui 随后比较 previous/current Buffer,只把变化的 Cell 交给 Backend,处理光标、交换 Buffer,再 flush 到终端。

打开网易新闻 查看精彩图片

这套模型对 Agent 很顺手。应用可以每次完整描述当前 UI,不用手工维护 ANSI 光标移动和局部擦除。真正写往终端的内容又是稀疏差量。需要留意的是,Diff 减少的主要是终端 I/O;每帧布局、Markdown 重排、字符串 clone 仍由应用承担。成熟产品通常还会把多个 token delta 合并后再刷新。

六项优势为什么贴合 Agent

我认为最关键的能力并非 Table 或 Gauge。更重要的是,Ratatui 没有抢走 Agent Runtime 的控制权。它不读取输入,不规定 Tokio、channel、reducer,也不关心模型和工具协议。团队已有的会话状态机可以原样保留,UI 只是状态的一次投影。

打开网易新闻 查看精彩图片

Inline Viewport 是另一个高价值设计。完成的工具日志可以插入动态区域上方,进入终端原生 scrollback;底部仍然显示输入框、进度与当前任务。它缓解了 fullscreen TUI 接管原生回滚与普通 CLI 无法持续更新局部区域之间的冲突。

打开网易新闻 查看精彩图片

约束布局负责另一类麻烦。状态栏可以固定一行,会话区占剩余空间,输入区按内容变化;宽屏展示工具详情,窄屏切成 overlay。窗口尺寸变化时,应用继续从 frame.area() 计算区域,不必在每个组件里手算坐标。

打开网易新闻 查看精彩图片

Unicode Cell 和 TestBackend 更容易被低估。Buffer Diff 专门处理宽字符、VS16 emoji,以及宽字符被窄字符替换后的尾格清理。中文和 emoji 混排不再由每个业务组件各写一套补丁。TestBackend 则把整屏、scrollback、cursor 都保存在内存里,审批弹窗、工具失败、窄终端和流式中间态都能进入普通 Rust 测试。本地快照运行 cargo test -p ratatui-core --lib,1439 项测试全部通过。

三个项目其实用得不一样

打开网易新闻 查看精彩图片

Codex 的固定 fork 说明,大型产品会为了 scrollback 与渲染细节锁定行为。grok-build 的两个自建 crate 说明,inline 和 textarea 已经进入产品差异化区域。CodeWhale 直接跟进 0.30,却仍要自己处理 transcript、composer、刷新合并和各种 picker。

我会把这种采用谱系概括成四个共享词:Rendering、Layout、Widget、Backend。共享层到这里就停止了。模型流怎么聚合,工具卡怎样折叠,权限如何审批,长历史如何虚拟化,仍由各产品决定。

共同选择不等于开箱即用

Ratatui 不提供完整 Event Loop、IME、多行输入、Markdown parser、语法高亮、长 transcript 虚拟化或 Agent Runtime。它的自由度很高,上层工程也确实很重。Codex 的公开 issue 里仍能看到 fullscreen 模式下复制和 scrollback 的体验冲突;Ratatui 自己的 inline 讨论也涉及 resize、换行、SSH 与终端模拟器差异。

这并不削弱它的价值,反倒说明选型边界很清楚。手写 Crossterm 适合一两行状态;Cursive 更适合表单和对话框;tui-realm 位于 Ratatui 上层,给出 Component、Msg 和 subscription;OpenTUI、Textual 分别服务 TypeScript 与 Python 团队。TUI 生态没有统一答案,主语言与控制流才是前提。

什么时候值得选

打开网易新闻 查看精彩图片

如果产品主栈是 Rust,已经有异步 Runtime 和领域状态机,还要持续流式更新、自定义交互、跨平台终端与 Buffer 级回归测试,Ratatui 很合适。我更看重它的薄边界:通用渲染问题由框架统一处理,产品不会被迫迁移自己的 Agent 架构。

如果只是一次性命令、简单表单,或团队期待现成的 DOM/React 式组件与完整生命周期,选择更轻或更高层的方案会更省力。

总结

Ratatui 成为这些 Rust Agent 的共同选择,不是因为它包办了 Agent 前端。它只把终端里最通用、最容易出错的部分做成稳定 contract:Layout、Widget、Unicode Cell、Buffer Diff、Backend 和 TestBackend。

这条边界带来了一个难得的平衡。应用可以按自己的节奏组织模型流、工具、审批和会话,渲染层仍有共同的工程基础。对 Coding Agent 来说,真正稀缺的并非更多现成控件,稀缺的是一块足够可靠、又不夺走控制权的终端渲染底座。

参考:Ratatui、OpenAI Codex、xAI grok-build、Hmbown/CodeWhale 当前仓库与固定提交,访问日期 2026-07-18。