herdr 对比 tmux 与 Zellij——开到第三个智能体才会出现的终端问题

多路复用器能让终端活着,却没法告诉你哪一个正在等你回答。herdr 的全部理由就是这一个缺口,而这个缺口比宣传里说的更窄,也更有意思。

更新于 2026-09-10

暖白色背景上并排放着五个一模一样的哑光炭灰色器皿,其中恰好有一个内部亮着暖光。
三个智能体在跑。两个在干活。有一个已经等你敲 y 等了九分钟。从外面看,它们是同一个东西。

本站上一篇对比回答的是「选哪个终端智能体」。这一篇要谈的问题,在你选完之前不存在,它出现在你同时开起第二个、第三个之后。

只开一个的时候,终端根本不是个话题:你启动它、看着它、回答它。开到三个,本身就变成了工作。你面前三个 pane,不逐个读一遍,就无从知道哪个跑完了、哪个还在想、哪个从午饭前就卡在一个权限确认上。

顺理成章的答案是上多路复用器。这是个好答案,但它回答的是问题的另一半。

tmux 早就解决了什么,又没有解决什么

「保活」这件事,在编程智能体出现之前很久就已经是解决了的问题。tmux 跑一个服务端持有真正的 PTY,你 attach 一个客户端、再 detach 掉,底下的进程根本不会察觉。合上笔记本、SSH 断线、明天再回来,活儿还在你离开的地方。Zellij 用 Rust 做了同一件事,默认界面更友好。有它们在,「我的智能体跟着 Wi-Fi 一起死了」不是新问题;任何把「保活」当成新卖点的对比,卖给你的都是 2007 年。

tmux 没有的,是对 pane 里面装着什么的任何概念。它知道 pane 的前台命令(#{pane_current_command}),也知道有没有字节在往外吐。第二个信号比听上去有用,你确实能拿它搭点东西出来:

# tmux:给 30 秒没有任何输出的窗口打个标记
set-option -w monitor-silence 30
set-hook  -w alert-silence 'run-shell "notify-send \"pane 安静了\""'

这是一个真能用的「智能体大概停下来了」的告警,而且只跑一个智能体时它常常就够了。

现在把三个智能体放到它后面。monitor-silence 会为顺利跑完的那个触发,会为崩掉的那个触发,也会为正显示着 Do you want to allow this edit? (y/n)、并且会一直那样杵着的那个触发。三者都是三十秒没输出。安静不是一种状态,它是状态的缺席;而你最需要分开的两种情况,doneblocked,恰恰就是安静会把它们糊在一起的那两种。

herdr 存在的全部理由,就是这个缺口。

跑编程智能体的四种形态。普通终端标签页:窗口一关智能体就没了。tmux 或 Zellij 这类多路复用器:服务端持有终端,detach 后智能体还在,但 pane 没有状态。cmux 或 Warp 这类终端应用:智能体住在一个替换掉你终端的应用里,只在它支持的机器上。herdr:服务端既持有终端,也把每个 pane 判为 working、blocked、done 或 idle,TUI、CLI 与一个普通 SSH 会话都只是接上来的客户端。
四种形态,按同一个问题排序:你正看着的那个东西消失时,智能体会怎么样。打开可交互版本可以逐个走完。

herdr 加了什么

herdr 出自 tmux 一脉,而且它并不掩饰:默认前缀键就是 ctrl+bctrl+b q 用来 detach。后台服务端持有所有 pane;你看着的那个 TUI 只是它的一个客户端,CLI 是另一个,一个普通 SSH 会话是第三个。把所有客户端都断掉,智能体照样在跑。

在这份继承之上,它加了一件事:它知道哪些 pane 里是智能体,并且给每一个一个状态。

状态 含义
blocked 智能体需要输入、批准或一个决定
working 智能体正在跑
done 已经跑完,而你还没去看
idle 跑完或在等待,并且你已经看过了
unknown herdr 无法有把握地判定

这些状态会向上汇总。一个 blocked 的智能体会让它所在的 pane、tab 以至整个工作区在侧边栏里都显示为 blocked。于是四个仓库里的九个智能体,你看的是一列,而不是九个 pane。这就是产品本身。

比侧边栏更有意思的是二阶效果。状态一旦是个真值,它就成了程序可以去等的东西:

herdr agent wait w1:p1 --until blocked
herdr agent wait w1:p1 --until done

这是多路复用器给不了的原语。tmux 的 wait-for 等的是一个得由别人来发信号的通道,或者一个钩子事件:你能等到「安静」,等不到「含义」。herdr 这个等待由服务端持有、事件驱动,而且它会把 pane 当前的占用者钉住,免得一个替换进程稀里糊涂地把等待满足掉。

herdr 为此发了一个 skill 文件 skills/herdr/SKILL.md(用 npx skills add herdrdev/herdr --skill herdr -g 装),教智能体自己去调那套 CLI:开一个 pane、在里面跑命令而不抢焦点、读另一个 pane 的输出、一直等到旁边那个智能体真的卡住为止。它的第一条规则是一个值得注意的护栏:如果 HERDR_ENV=1 没有被设置,智能体必须停下来并说明自己不在 herdr 的 pane 里,这样 herdr 之外的智能体就不会去驱动一个不属于它的会话。

那个状态到底是从哪来的

这是宣传页会跳过的部分,也是真正该决定你装不装它的部分。

herdr 判定一个 pane 的状态走两条路径之一,而文档明确列了哪个智能体走哪条。

生命周期钩子或插件。 智能体自己上报它在干什么。这条是权威的:herdr 用这些上报来定 idleworkingblocked 与会话标识,并且刻意不再对同一个 pane 跑屏幕匹配,以免出现两个互相打架的事实来源。截至 v0.9.0,这条路径覆盖 PiOpenCode、OMP、Kilo Code CLI、Kimi Code CLI 与 MastraCode,前提是装了对应集成。

屏幕清单(screen manifest)。 其余一切,herdr 先识别前台进程,再拿一组 TOML 规则去匹配 pane 缓冲区活动底部的一份快照,也就是 TUI 画提示的那块区域;必要时还会把终端标题与 OSC 进度序列当作附加证据。这条路径覆盖 Claude CodeCodex、Cursor Agent CLI、GitHub Copilot CLI、Grok CLI、Devin CLI、Droid、Qwen Code、Qoder CLI、Amp、Antigravity CLI、Hermes Agent 等等。Gemini CLI 与 Cline 能被识别,但用项目自己的话说,测试得没那么充分。

带着你自己的配置再读一遍这两份名单。对这个品类里用得最多的两个智能体来说,这个招牌功能是在对渲染出来的文字做模式匹配。 这不是对实现的批评:对一个不暴露任何钩子的智能体,本来也没有别的做法。但它带来的代价你得先算进去:

  • 一个 herdr 没见过的权限提示,会显示成 idle 而不是 blocked。文档写得很直白,这个兜底在诊断输出里甚至有名字:default_known_agent_idle_fallback。blocked 的判定是故意从严的,所以失效方式是漏报,而不是替你点同意。
  • 于是检测必须追着别人家的 UI 变更跑。herdr 的答案是在后台从 herdr.dev 拉取更新后的清单,并热加载进正在跑的服务端。如果「一台机器会悄悄下载行为规则」在你的环境里是个问题,[update] manifest_check = false 可以关掉它,~/.config/herdr/agent-detection/ 下的文件可以在本地覆盖任何清单。
  • 当某个 pane 显示错了,herdr agent explain <target> 会打印命中的规则、清单来源与版本,以及证据。给一个启发式配上这个,是对的做法。

老实的总结是:对多数智能体,这个状态是一份工程上做得不错的推断;对少数几个,它是一份真正的上报。它比「安静」好太多。它和「智能体亲口告诉你」不是一回事。

回答「这个 pane 卡住了吗」的三种方式。tmux 盯着字节流、报出「安静」,而安静分不开 done 与 blocked。herdr 的屏幕清单路径对 pane 缓冲区底部取快照并匹配 TOML 规则,得到真正的状态,没有规则命中时回落到 idle。herdr 的生命周期钩子路径直接从智能体本身取状态,是权威的。
同一个问题的三种回答方式,按「这个答案能信到什么程度」递增排列。打开可交互版本看逐步讲解。

重启之后,到底什么活了下来

流传着一种说法:机器重启一下,herdr 会把你的智能体带回来。文档比这个说法精确得多,而这份精确很要紧。

进程继续跑 布局回来 回滚内容回来 会话续上
detach 后重新 attach 是,那本来就是活的终端 是,它压根没停过
服务端或机器重启 只有开了 pane history 才有 只有支持原生会话恢复的智能体才有

detach 是强路径,也正是 tmux 那份继承:什么都没停,所以什么都不用重建。服务端重启是另一回事——原来的 pane 进程没了。herdr 恢复的是形状:工作区、tab、pane、工作目录、焦点;做不到更多的 pane,会以新 shell 的形式回到它保存的目录里。

有两个机制能缓解这一点,而且各带一个附加条件:

pane 屏幕历史(pane screen history) 会在重启后重放最近的终端内容。它默认关闭,理由是对的:pane 输出里有密钥、token 和命令输出,打开它就意味着要把 herdr 的会话目录当成 shell 历史来对待。Zellij 出于同样的理由做了同样的选择——它的会话复活默认只序列化布局与每个 pane 的命令,视口与回滚内容要你自己开。

原生智能体会话恢复 才是真正新的那部分。通过当前集成上报了会话引用的智能体,会用它自己的恢复参数重新起来——claude --resume <id>codex resume <id>opencode --session <id>pi --session <path-or-id> 以及另外十几个。这个默认开启。回来的是对话;旁边那个跑到一半的 cargo build 不会回来。

顺带一提,Zellij 的会话复活其实已经覆盖了「布局」那一半,每秒序列化成一份人类可读的 KDL 布局,而且它做了一件 herdr 的恢复没做的事:给每条被恢复的命令前面加一道「Press ENTER to run…」的确认横幅——理由是当那个 pane 里可能装的是 rm -rf 时,默默重跑不是个好主意。两种默认,各有各的道理。

隔壁那个品类:把你终端替掉的应用

cmux(26,970 星,Swift,macOS,基于 Ghostty)和 Warp 用另一种方式回答同一个「哪个智能体在等我」的问题:它们成为你的终端。这买到的是一块它们完全控制的渲染面——真正的系统通知、纵向标签页、一套不必挤在字符网格里的界面;付出的是你的终端、你的配置,以及那个应用没有发布版本的那些机器。

herdr 的取舍正好相反:它不改变你的终端里的任何东西,只拥有跑在里面的东西——所以它同样能通过一个普通 SSH 会话,工作在一台永远不会跑桌面应用的机器上。如果你要套娃,有个细节值得知道:herdr 跑在 tmux 里面没问题,但如果你的 shell 配置会在 herdr 的 pane 里自动进 tmux,herdr 看到的 pane 进程就是 tmux,它背后的智能体会从检测里消失。

数字

以下为 2026-09-10 通过 GitHub API 核对:

herdr tmux Zellij cmux
仓库 herdrdev/herdr tmux/tmux zellij-org/zellij manaflow-ai/cmux
Star 37,215 49,164 35,352 26,970
语言 Rust C Rust Swift
协议 Apache-2.0 ISC MIT Other
仓库创建 2026-03-27 2015 年起的镜像 2020-09-01 2026-01-28
最新发布 v0.9.0,2026-09-07

有一行值得多说一句。herdr 在不到六个月里拿到 37,215 星,这说明这个问题被广泛感受到,但完全不说明这个工具已经成熟。它还在 1.0 之前,文档里挂着二十来个已发布版本,live handoff 被明确标为实验性,pane history 挂在 [experimental] 下面。这是一个快速推进的年轻项目的正常样子,不是警告——但如果你是在给一个团队定标准,「配置文件这个季度改了两次」是实打实的成本,而天平另一头放着的,正是 tmux 那份 ISC 协议的稳定性。

怎么选

继续用 tmux 或 Zellij,如果你一次只跑一个智能体;如果一个 monitor-silence 告警就覆盖了你的需要;如果你不打算再加一个持有你全部终端的后台守护进程;或者长期配置稳定性对你比一个更好的侧边栏更重要。

加上 herdr,如果你经常同时有三个以上智能体在飞;如果你已经吃过「某个智能体在权限确认上杵了半小时」的亏;如果你的智能体跑在一台你 SSH 上去又会断开的远程机器上;或者你希望智能体之间用 agent wait 自己协调,而不是每一次交接都由你来居中转达。

改看 cmux 或 Warp,如果你乐意搬进一个受支持平台上的新终端,并且宁愿要一个真正的图形界面而不是 TUI 侧边栏。

不管你倾向哪一边,先去看那张支持列表。 如果你的智能体在生命周期钩子那一列,你拿到的是上报的状态;如果它在屏幕清单那一列——Claude Code 与 Codex 都在——你拿到的是一份失效方式有文档的推断。两者都有用,但它们不是同一笔买卖。

这篇是怎么写出来的

本文关于行为的每一条陈述,都取自 herdr 自己的仓库与文档——README,以及 herdr.dev/docs 在 v0.9.0 下的 concepts、agents、session-state、agent-skill、socket-api 五个页面;用于对比的部分取自 tmux 手册页与 Zellij 的 session resurrection 文档。Star 数、协议与仓库创建日期来自 2026-09-10 的 GitHub API,之后会漂移。

有一处订正值得记下来,因为这个夸大很常见:不少文章说 herdr 能扛住机器重启并把智能体恢复回来。herdr 自己的文档写得更窄也更清楚——服务端重启之后,原来的进程不会存活;回来的是布局,受支持的智能体可以通过它自己的恢复参数续上对话。这是个有用的功能,但它是另一个说法。

作者尚未对 herdr 做过长期实际试用。本文凡是给判断而非陈述事实的地方,依据的是有文档支撑的设计决策,并且已经标明。

两张插图都是生成的,不是照片。两张图表由上文那些事实的结构化规范编译而来,因此不会多出正文没有的主张;开篇那张只是一个比喻,本身不承载任何主张。

本文涉及的工具