Simon Willison 的博客总像一把铲子——他随便翻翻别人的代码仓库,就能挖出让你忍不住挑眉毛的东西。这次他盯上了 xAI 开源的 Grok CLI 编码智能体项目,不是冲着大模型架构去的,而是捡出了一个藏在 markdown 渲染模块里的小玩意:一个用 Rust 写的 Mermaid 图表终端渲染器。它本分地待在 `xai-grok-markdown/src/mermaid.rs` 里,职责就是在命令行里把 Mermaid 描述转成 Unicode 字符画。Simon 觉得这太酷了,几口咖啡的工夫,他通过 Claude Code for web(代号 Fable 5)把这东西编译成了 WebAssembly,丢进浏览器跑了起来,于是终端专属的朴素流程图,在网页上活了过来。
一个藏在 Grok 仓库里的终端绘图器
文件位置比你想象的更靠里
如果你克隆 xAI 的 Grok CLI 仓库,顺着依赖树往下摸,会在 markdown 渲染相关的 crate 里看到 `mermaid.rs`。它的大小并不夸张,代码写得极度克制,没有扯进庞大的 JavaScript 图表库,也不依赖 DOM——它的全部本事就是吃进一串 Mermaid 语法,吐出一行行由盒绘图字符拼成的文本。没错,就是那些你当年在 DOS 界面或者 telnet BBS 里见过的线条与方框:`┌─┐│└┘`。这种输出天生为等宽字体终端设计,不产生任何图片文件。
它想解决的问题很窄,但很准
Grok CLI 作为一个编码智能体,需要在终端里展示各种信息,包括架构草图、流程逻辑。常规做法是输出一个图片链接或者干脆忽略图表,而这个渲染器让命令行本身就能呈现可读的流程图。当你问 Grok “帮我画一个用户登录时序图”,它不仅给出代码,还能在终端里直接绘出 `参与者→服务→数据库` 的交互,不需要切换窗口打开浏览器或图片查看器。这种即时性,恰好是终端工作流的核心爽点。
一纸 Unicode 胜过千行像素
这个渲染器的输出精度当然比不上矢量图,节点位置可能会被字符格子限制得略微变形,箭头也只能用 `→` 或 `──▶` 代替。但它在信息传递上毫不含糊:顺序、分支、循环,一眼能看出来。而且因为全是纯文本,你可以把它复制粘贴到 Markdown 文档、工单评论甚至邮件正文里,接收方无需任何插件就能看懂。这种可移植性,让图片格式相形见绌。
Rust 遇上了 Wasm,终端工具溜进浏览器
编译过程只有三步,但每一拳都打在实处
把 Rust 程序编译成 WebAssembly 不是什么新鲜事,但 Simon 的操作路径值得细看。他没有在本地折腾工具链,而是打开 Claude Code for web——一个运行在浏览器里的编码环境,代号 Fable 5,底层由 Claude 模型驱动。他在对话里告诉 Claude:“把这个 crate 编译成 Wasm,并提供一个可以从 JavaScript 调用的接口”。几分钟后,一个 `.wasm` 文件和一层薄薄的 JS 胶水代码就生成了。这种交互式编译体验省去了本地 wasm-pack 配置、目标平台切换的繁琐,直接把思路变成了可用的网页组件。
Fable 5 在背后做了什么
Fable 5 并非单纯的在线编辑器,它能直接操作文件系统、执行编译命令。当 Simon 提出需求,Claude 自动编写了必要的 `wasm-bindgen` 声明、调整了 Cargo.toml,把渲染函数暴露出来,并处理了字符串在 Rust 与 JavaScript 之间的传递。结果是一个函数:输入 Mermaid 代码字符串,返回纯文本的 Unicode 图表。浏览器端无需任何 Mermaid.js 库,不需要解析 DOM,甚至 Canvas 标签都不用,就是一个 `
` 标签加上一段自动生成的文本。这对性能几乎零要求的渲染方式,在某些嵌入式文档页面里简直是天降礼物。从终端到网页,语言之间的缝隙被抹平了一截
很多人以为这类移植需要重写大量逻辑,实际上因为 Rust 代码本身就没有假设运行环境——它既不去 `/dev/tty` 写像素,也不调用 ncurses,只是纯粹的字符串处理——跨平台迁移一点不疼。WebAssembly 给这个渲染器披了一层浏览器外壳,内核仍旧是那个在 Grok CLI 里安分的绘图引擎。这种“一次编写,多端渲染”的模式,值得每个写跨环境工具的开发者琢磨:你的核心逻辑是否也能剥离掉环境依赖,只靠字符串和数学打天下?
这件事不只是在说一个渲染器
轻量级图表工具又解锁了一个分支
开发者画流程图的选项已经多到让人烦躁:Mermaid.js、PlantUML、Graphviz、D2,以及各种拖拽式绘图应用。但这些方案无一例外都要求一个运行时——要么是 JavaScript 引擎,要么是本地二进制,要么是远程渲染服务。而将 Grok 的终端渲染器搬上浏览器后,画图变成了纯粹的字符串变换,库的体积可以压到几十 KB,甚至能塞进 Service Worker。对于那些只需要快速展示简单逻辑的场景,这种“无图模式”反而更干净:不会触发图片加载,不会被广告拦截器误伤,也不会在暗黑模式下格格不入。
开源项目的“虾滑”部分往往最可口
Grok CLI 的核心价值当然在智能体引擎,但 Simon 翻出来尝鲜的却是这个毫不起眼的 markdown 子模块。这很像进了高档寿司店却对虾滑小菜赞不绝口——但不得不承认,这种小菜往往最见火候。一个终端 Mermaid 渲染器,代码行数不多,却覆盖了语法解析、布局计算、字符映射多个领域,写得干净利落,本身就是 Rust 设计模式的好教材。xAI 把这个组件开源出来,即便未来 Grok CLI 本身不再维护,这个渲染器也可能在社区里独立演化,成为某个文档生成器或终端日记工具的核心插件。
终端思维正在渗透 Web 开发
近几年一个悄悄发酵的趋势是:终端工具的设计哲学开始反哺网页应用。从 Tuist 的把终端组件搬到 Electron,到 Glamorous Toolkit 的可视化探索,再到这个纯文本 Mermaid 渲染器的网页化,都在传递同一个信号——开发者对“即时可得、不需加载”的交互越来越没耐心。一张 Unicode 图表,比任何加载中的 spinner 都诚实。Simon 的这次移植实验,或许顺便给那些苦于图表渲染慢的前端团队提了个醒:下次开会汇报架构时,不如先丢一个终端风格的状态图到 Slack 里,所有人立刻看懂。

