一个反常点摆在这里:越“现代”的终端工具,越可能让盲人用户更难用。
最近一篇开发者博客批评 gemini-cli,以及它背后的 Ink 这类 React 式终端渲染框架。表面上,它们还是文字界面。实际运行时,它们把终端当成二维画布:移动光标、刷新状态、重算历史、再把界面画回来。
视觉用户看到的是顺滑。屏幕阅读器用户听到的,可能是一锅噪音。
这事最值得盯的,不是某个 spinner 好不好看,而是一个被行业默认吞掉的前提:文本界面不自动等于无障碍。
CLI 是流水账,TUI 是格子屏
CLI 和 TUI 都在终端里,但它们不是一回事。
| 类型 | 输出方式 | 对读屏器的影响 |
|---|---|---|
| CLI stream | 按时间追加,一行接一行往下走 | 更线性,朗读顺序更稳定 |
| TUI grid | 按空间坐标重绘,光标来回跳 | 容易打断朗读和输入 |
传统命令行的相对友好,不是因为它“有文字”。而是因为它像流水账。你输入命令,结果追加在下面。Speakup 这类读屏工具可以按时间顺序读。
现代 TUI 换了一套模型。状态栏、spinner、计时器、聊天历史,都可能触发局部或全屏重绘。gemini-cli 使用 Ink/React 式终端渲染,AI “thinking” 时的 timer 和 spinner 会频繁更新。
每次更新,都可能移动硬件光标,写入字符,再跳回输入区。
对看屏幕的人,这只是界面活着。对用读屏器的人,它可能变成:“Responding… 1s… 历史片段… Responding… 2s……”
更麻烦的是输入稳定性。原文作者提到,在 Speakup、NVDA 等特定组合下,粘贴大段文本、继续长会话输入时,框架可能因为状态变化去 diff 和重绘大量历史内容,带来朗读混乱、输入延迟,甚至读屏器崩溃或系统不稳定的风险。
这里要克制说法:这不是所有环境必然复现的事故。但它足够说明一个问题——默认渲染模型没有把读屏器当成一等用户。
老 TUI 不是更道德,只是更克制
有人会说:nano、vim、menuconfig、Irssi 不也是 TUI 吗?盲人用户为什么还能用?
答案不是“老工具天然高尚”。它们也有坑。nano 如果持续报光标位置,vim 如果配置不当,同样会让读屏器不停念列号,盖过真正输入的字符。
差别在于,很多老工具至少给用户留了退路。
| 工具 | 相对可取之处 | 真正关键 |
|---|---|---|
| nano / vim | 可关闭部分光标、状态噪音 | 让输入重新占上风 |
| menuconfig | 焦点基本限制在单列列表 | 空间复杂度低 |
| Irssi | 利用 VT100 scrolling regions | 少重写屏幕,少打扰输入行 |
Irssi 这个例子很能说明问题。它不是动不动 diff 整个屏幕,而是利用终端原有的滚动区域能力:定义区域、滚动、在底部写新行。
它更像顺着终端的骨架工作。现代声明式 TUI 更像把终端改造成一个廉价浏览器画布。
这就是分水岭。
现代 TUI 框架的问题,不是“用了框架就错”。问题在默认激励:开发者写起来像 React,组件树、状态更新、声明式渲染,都很顺手。代价落到看不见屏幕的人身上。
“天下熙熙,皆为利来。”这里的利,不只是钱。还有开发便利、视觉顺滑、项目指标、维护成本。它们都真实存在。只是读屏用户常常不在默认优先级里。
真问题在激励:谁省事,谁受罪
原文还提到,gemini-cli 仓库里一些 accessibility issue 长期没有推进,其中有 issue 被 stale bot 以清理旧报告、保持 backlog 可管理为由自动关闭。
这不能直接写成维护者有恶意。证据不够。
但它至少表明一种常见的开源维护现实:没人有时间处理的问题,会先从列表上消失。backlog 干净了,用户的障碍还在。
我不太买账的是那句老话:“它跑在终端里,所以天然可访问。”
终端只是容器。真正决定可访问性的,是输出是否线性、光标是否稳定、重绘是否克制、动态内容能不能关。一个笨一点的 CLI,可能比一个漂亮的 TUI 更尊重用户。因为前者至少不抢读屏器的注意力。
对终端工具和开发者工具作者,这不是道德作文,而是产品约束。接下来该做的事很具体:
- spinner、timer、实时状态刷新,应提供关闭选项;
- 长历史不要在每次输入时重新参与布局和 diff;
- 输入行要稳定,光标不要频繁跳出再跳回;
- 提供线性输出模式,至少给读屏器用户一条退路;
- 用 Speakup、NVDA 这类读屏器做基本测试,而不是只看视觉截图。
对关心 CLI/TUI 设计的技术读者,也有一个现实判断:别再把“文本界面”当安全词。评估一个工具,不只看它是否运行在终端里,还要看它怎么写屏幕、怎么处理焦点、怎么对待动态状态。
采购或引入内部开发者工具时,也可以多问一句:有没有无动画模式?有没有纯流式输出?粘贴大段文本时输入是否稳定?如果答案都没有,就别急着把它推给所有人。
接下来最该观察的,不是 gemini-cli 会不会把某个 issue 重新打开,而是这类现代 TUI 框架能不能把可访问性变成默认约束。只给一个 --accessible 补丁不够。渲染架构如果继续默认高频重绘,读屏用户还是要替视觉顺滑买单。
文本不是免死金牌。把终端当画布的那一刻,开发者体验确实上去了;只是有人被留在光标乱跳的噪声里。
