如果你在 Ubuntu 24.04、Ghostty、tmux、Warp、Docker Terminal 或其他终端里运行 Hermes Agent,遇到过这种体验:输入框底部边框跟着光标或 thinking 动画不断闪烁,甚至像整块 UI 在抖,那么你大概率会先怀疑终端配置、$TERM、tmux、字体、GPU 渲染,或者本地 llama.cpp 模型输出太慢。
但 Hermes Agent 的热门已关闭 Issue #464 给出了一个更准确的判断:这类问题不一定是你的终端坏了,也不一定是模型服务问题,而是 终端 TUI 渲染系统与 spinner / stdout 写入方式冲突。
这篇文章单独复盘 GitHub Issue #464:为什么一个“边框闪烁”的小问题能产生 31 条评论,为什么 HERMES_SPINNER_PAUSE=1 hermes 能成为关键定位手段,以及最终修复为什么不是“换个 emoji”,而是把 thinking spinner 移入 prompt_toolkit 的正式渲染系统。
先说结论:Issue #464 已关闭,结论很明确
Issue #464 的标题是:
> [Bug]: Blinking cursor or switching emojis causing prompt lines to flash repeatedly in terminal
关键信息如下:
| 项目 | 结论 |
| Issue | NousResearch/hermes-agent #464 |
| 状态 | closed |
| state_reason | completed |
| 评论数 | 31 |
| 触发环境 | Ubuntu 24.04、Ghostty、tmux、普通 terminal、本地 llama.cpp server |
| 影响组件 | CLI interactive chat |
| 相关修复 | PR #470:fix terminal border flashing from cursor blink and emoji spinners |
| 最终根因 | spinner 通过 \r 直接写 terminal,与 prompt_toolkit / patch_stdout 布局重绘冲突 |
一句话概括:Hermes CLI 的 thinking 动画原本在 prompt_toolkit 布局外直接写 stdout,导致每一帧 spinner 都触发 TUI 重新绘制边框,于是用户看到输入框线条反复闪。
这个 bug 为什么容易被误判?
终端 UI 闪烁有个麻烦点:它看起来不像“程序错误”,更像“环境玄学”。
用户最初描述的是:
- Ghostty + tmux 下会闪;
- 后来确认普通 terminal 也会闪;
- Ubuntu 24.04;
- Hermes 通过本地 llama.cpp server 跑;
- 光标闪烁时,prompt 输入框的下方边框也跟着闪;
- thinking 阶段切换 emoji / spinner 时更明显;
- 期望至少能关掉 blink cursor 或 emoji cycling,避免看着头疼。
如果只看现象,很多人会沿着错误方向排查:
- 是不是 Ghostty 的 GPU 渲染问题?
- 是不是 tmux 的
$TERM配错了? - 是不是
xterm-256color不兼容? - 是不是本地 llama.cpp 太慢,导致 Hermes streaming 卡顿?
- 是不是终端字体、emoji 宽度或 Nerd Font 问题?
这些方向不是完全没意义,但 Issue #464 的讨论把重点逐步缩小到了一个更具体的机制:闪烁与 Hermes thinking spinner 的写入方式强相关。
关键诊断命令:HERMES_SPINNER_PAUSE=1 hermes
维护者让用户做了一个非常有效的 A/B 测试:
HERMES_SPINNER_PAUSE=1 hermes
这个测试的价值在于,它不是泛泛地“换个终端试试”,而是直接隔离 spinner 变量。
测试结果是:关闭 spinner 后,边框闪烁停止了。虽然 thinking line / cursor 也一起不可见,但 agent 仍然在后台思考。这说明问题不是模型停止了,也不是 Hermes 整体卡死,而是 thinking 状态的可视化输出触发了 UI 闪烁。
这个结论很重要:
- 如果关 spinner 后闪烁消失,说明根因大概率在 TUI 渲染 / stdout 写入;
- 如果关 spinner 后仍闪,才更值得继续查终端、tmux、GPU、字体;
- 如果只是在 Docker / Warp / Ghostty 某一类终端发生,也要确认是否是同一种 TUI 重绘路径。
对普通用户来说,这个命令也可以作为临时 workaround:宁可少一个 thinking 动画,也比整块输入框闪烁要舒服。
根因拆解:为什么 \r spinner 会让 prompt 边框闪?
Hermes CLI 使用的是终端 TUI。此类程序通常需要一个统一的渲染系统来管理:
- 输入框;
- 边框;
- 光标;
- streaming 输出;
- thinking 状态;
- tool call 状态;
- stdout / stderr 的临时输出。
Issue #464 中,维护者最终确认:thinking spinner 使用 \r 直接写 terminal,并且处在 patch_stdout 相关上下文里。这样每一帧 spinner 刷新都会和 prompt_toolkit 的布局重绘发生冲突。
可以把它理解成:
- prompt_toolkit 以为自己掌控整个 TUI 布局;
- spinner 却绕过布局系统,直接向终端写一行并回车覆盖;
patch_stdout又尝试协调普通 stdout 与 TUI;- 结果是每一帧 spinner 都可能触发布局重画,边框也跟着被刷新;
- 用户看到的就是输入框线条像在闪。
所以,问题不只是“emoji spinner 太花哨”,而是 UI 的一部分不应该用 raw stdout 写法存在于布局系统之外。
PR #470 的修复思路:不是隐藏 spinner,而是放回 TUI 渲染系统
相关 PR #470 标题为:
> fix: stop terminal border flashing from cursor blink and emoji spinners
最初修复尝试包括:
- 在
Application()中加入CursorShape.STEADY_BLOCK,减少 blinking cursor 影响; - 将随机 emoji spinner 换成更稳定的
dotsspinner; - 增加 spinner frame interval,从
0.12s调整到0.25s,降低重绘频率。
这些改动能缓解一部分问题,但讨论过程中发现还不够。真正的长期解法是:把 spinner 移入 prompt_toolkit 的 render system,作为一个正式的 Window component,而不是继续用 \r 直接写 terminal。
后续维护者更新方案:
- thinking spinner 被移动到 prompt_toolkit 的 TUI 中;
- agent 通过
thinking_callback把 thinking 文本传给 CLI; - CLI 更新
FormattedTextControl; - 该控件作为
HSplitlayout 中的 Window 渲染; - 不再依赖 raw
\r写 stdout 来刷新 spinner。
用户最终测试反馈:
- 不再闪烁;
- thinking text 仍能看到;
- 体验恢复正常。
这也是 Issue #464 能被视为“已解决”的原因:它不只是有人说“关掉动画试试”,而是定位到了渲染架构层面的冲突,并给出了正确方向的修复。
如果你现在还遇到 Hermes 输入框闪烁,按这个顺序排查
1. 先确认 Hermes 版本和 issue 是否已包含修复
如果你使用的是较早版本,先升级 Hermes Agent。Issue #464 的修复发生在 2026 年 3 月相关分支和后续提交中,旧版本可能还保留 raw spinner 写法。
建议动作:
hermes --version
然后查看当前安装方式对应的升级命令,例如 pip、uv、Docker image 或源码拉取。
2. 用 HERMES_SPINNER_PAUSE=1 hermes 做隔离测试
HERMES_SPINNER_PAUSE=1 hermes
判断标准:
| 现象 | 更可能的方向 |
| 关闭 spinner 后不闪 | Hermes thinking spinner / TUI 渲染冲突 |
| 关闭 spinner 后仍闪 | 继续查终端、tmux、字体、GPU、TERM |
| 只在 tmux 里闪 | 查 tmux $TERM、terminal-overrides、truecolor |
| 只在 Docker terminal / Warp 闪 | 查宿主终端模拟器与伪终端兼容 |
3. 检查 $TERM,但不要把所有问题都甩给它
Issue #464 中,用户也检查了 $TERM。一开始怀疑 tmux,后来确认普通终端中 $TERM 为 xterm-256color,问题仍存在,因此 tmux 并不是唯一根因。
你仍然可以检查:
echo $TERM
但要记住:如果普通 terminal 也闪,且关闭 spinner 后不闪,那就别一直陷在 tmux 配置里。
4. 区分“模型慢”和“TUI 闪烁”
用户当时使用本地 llama.cpp server。本地模型慢、首 token 延迟高、tool call 慢,都可能让 thinking 状态持续更久,从而让闪烁更明显。
但模型慢不是边框闪烁的根因。它只是让 spinner 显示时间变长,让 UI 问题更容易被看见。
如果你用本地模型,可以同时记录:
- first token latency;
- tokens per second;
- thinking 状态持续时间;
- 是否只在 streaming / tool call 阶段闪。
5. 临时 workaround:关闭 spinner 或换更稳定终端组合
如果你暂时无法升级,可以先使用:
HERMES_SPINNER_PAUSE=1 hermes
或者尝试:
- 退出 tmux 直接运行;
- 换系统 terminal / iTerm2 / GNOME Terminal / Alacritty 测试;
- 暂时避免 emoji-heavy spinner;
- 降低终端动画和光标闪烁设置。
这些不是根治,但能帮助你继续工作。
对开发者的启发:终端 AI Agent 不该把状态动画写在布局系统外
Issue #464 看起来是一个很小的 bug,但对 AI Agent CLI 产品很有启发。
今天的 Agent CLI 已经不是传统命令行工具,它们同时承载:
- 多轮对话;
- streaming tokens;
- tool calls;
- 后台任务状态;
- 多模型 provider;
- 用户输入编辑;
- 文件 diff / patch 展示;
- 权限确认;
- 日志与普通 stdout。
这意味着 UI 状态必须有统一管理。否则,任何一个“直接 print / stdout write / carriage return”的小动画,都可能和主渲染系统打架。
经验总结:
- spinner、thinking text、tool state 应该是 TUI layout 的一部分;
- 不要在 prompt_toolkit / textual / curses 管理之外直接
\r刷新复杂状态; - stdout patching 只能作为兼容层,不应承担主 UI 状态同步;
- emoji spinner 要考虑终端宽度、字体和 redraw 成本;
- frame interval 过短会放大闪烁、耗电和远程终端延迟。
这类细节会直接影响用户对 Agent 的信任感。模型再强,如果输入框一直闪,用户也会觉得系统“不稳”。
DeepAI API 中转站在这个问题里的位置:别把 UI bug 误判成模型 API 故障
这篇 issue 的核心不是 DeepAI、OpenAI、Anthropic 或模型能力,而是 Hermes CLI 的终端渲染问题。所以不能说“换 DeepAI 就能修好边框闪烁”。这是错误归因。
但它对实际部署仍有一个重要提醒:稳定的 Agent 体验由两部分组成:模型链路稳定 + 客户端 UI 稳定。
如果你在 Hermes、Cherry Studio、Cline、Dify、Open WebUI 等工具里接入 OpenAI-compatible 模型服务,可以把 DeepAI API 中转站放在“模型链路稳定性”这一层:
- 统一 OpenAI-compatible API 接入方式;
- 减少不同 provider key 和 endpoint 来回切换;
- 便于在支持自定义 Base URL 的工具里集中管理模型调用;
- 遇到 401、429、timeout、model not found 时更容易定位是 provider 层问题,而不是 UI 层问题。
换句话说:
- 输入框闪烁、边框重绘、spinner 冲突:优先查 Hermes CLI / terminal / prompt_toolkit;
- API 报错、模型不可用、限流、响应慢:再查 provider、Base URL、API Key、模型名和中转站配置。
这种分层排查,反而能减少无效折腾。
FAQ:Hermes Agent 输入框闪烁常见问题
1. Hermes 输入框边框闪烁是不是 Ghostty 的 bug?
不一定。Issue #464 最初环境包含 Ghostty + tmux,但后来普通 terminal 也出现类似现象。最终定位是 Hermes thinking spinner 与 prompt_toolkit / patch_stdout 的重绘冲突。Ghostty 可能让现象更明显,但不是唯一根因。
2. HERMES_SPINNER_PAUSE=1 hermes 是修复还是临时绕过?
更像临时绕过和诊断手段。它能帮助确认 spinner 是否参与触发闪烁,也能让你暂时避免闪烁继续使用 Hermes。但长期修复应该是升级到包含 TUI spinner 重构的版本。
3. 为什么关闭 spinner 后 agent 还在思考?
因为 spinner 只是 thinking 状态的可视化,不是模型推理本身。关闭 spinner 后,后台请求和 agent 流程仍然可以继续,只是你看不到原本的 thinking 动画。
4. tmux 的 $TERM 还需要检查吗?
需要,但不要过度迷信。$TERM 错配确实会导致终端显示问题;但如果普通 terminal 也闪,且关闭 spinner 后不闪,就应该优先怀疑 TUI 重绘路径,而不是一直改 tmux 配置。
5. DeepAI API 中转站能解决 Hermes CLI 闪烁吗?
不能直接解决。DeepAI API 中转站主要解决 OpenAI-compatible 模型接入、provider 管理和 API 调用稳定性问题。Hermes CLI 闪烁属于客户端终端 UI 问题,应从 Hermes 版本、spinner、prompt_toolkit、terminal 配置方向排查。
结语:小闪烁背后,是 Agent CLI 工程成熟度问题
Hermes Issue #464 的价值在于,它把一个看似“终端玄学”的问题拆成了可验证、可修复的工程问题:先用 HERMES_SPINNER_PAUSE=1 缩小范围,再确认 raw \r spinner 与 prompt_toolkit layout 冲突,最后把 spinner 放回 TUI 渲染系统。
对用户来说,这篇 issue 的实用结论是:看到边框闪烁,不要马上怀疑模型或 API;先隔离 spinner,再升级 Hermes。
对开发者来说,结论更直接:Agent CLI 的状态动画、thinking 文本、tool call 提示,都应该由同一个 TUI 渲染系统管理。一个小小的 stdout spinner,就足以让整个交互体验看起来不可靠。