一个反常点摆在这里:越“现代”的终端工具,越可能让盲人用户更难用。

最近一篇开发者博客批评 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 补丁不够。渲染架构如果继续默认高频重绘,读屏用户还是要替视觉顺滑买单。

文本不是免死金牌。把终端当画布的那一刻,开发者体验确实上去了;只是有人被留在光标乱跳的噪声里。