终端里的 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。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.