Herdr:agent 复用器,不只是另一个 tmux
我之前写过一个系列:tmux 快速上手、Zellij 快速上手、Zellij 和 tmux 的对比,以及 Zellij 配合 AI coding agent 做会话持久化。这些文章有一个共同结论:AI coding agent 跑在终端里,但终端不是一个可靠的运行时。用 tmux 或 Zellij 把 agent 包起来,detach / reattach,是一种省事的基础设施。
然后 herdr 出现了。它不是另一个终端复用器——它直接把自己叫 agent multiplexer。我用了两周,判断是:herdr 把终端复用和 agent 感知做成了同一层,解决了 tmux/Zellij 不知道面板里跑的是什么的问题。
它比 tmux 多了什么
tmux 和 Zellij 都是优秀的终端复用器。它们的核心能力是:
- 分面板、分标签、分工作区
- 断开客户端后进程继续跑
- SSH 远程 attach
但这套模型假设每个面板里跑的是一个"终端进程"——shell、vim、htop,一条指令一个功能。AI coding agent 不一样:它有自己的生命周期。
| 状态 | 含义 |
|---|---|
working | agent 正在执行任务 |
blocked | 需要你确认、输入或干预 |
done | 任务完成,你还没看 |
idle | 已完成的已被查看,等待下一条指令 |
tmux 不会告诉你 3 号面板卡在权限确认弹窗,Zellij 也不会提醒你 2 号面板的 20 分钟构建已经跑完了。你需要一个个面板切过去,看一眼,再判断。
herdr 做的事情:读每个面板里的 agent 输出,识别状态,汇总到侧栏。左边是 workspace 列表(每个 workspace 显示最紧急的 agent 状态),右边是当前 workspace 的 agent 列表和各自状态。一眼扫过去就知道哪个项目需要关注。
定位:站在 tmux 和桌面 agent 管理器之间
herdr 的官方对比页面把自家定位说得很清楚:
| tmux / Zellij | 桌面 agent 管理器 | herdr | |
|---|---|---|---|
| 跑在你的终端里 | ✓ | — | ✓ |
| 持久 PTY 会话 | ✓ | 部分 | ✓ |
| 远程 SSH attach | ✓ | 有限 | ✓ |
| agent 状态感知 | — | ✓ | ✓ |
| 鼠标原生操作 | 需配置 | ✓ | ✓ |
| agent 可编程驱动 | 脚本级 | 部分 | ✓(Socket API) |
herdr 不是要取代谁。它站在终端复用器和 agent 管理器之间的空白地带——要持久化,也要 agent 感知;要留在终端里,也要鼠标点。
安装和首屏体验
curl -fsSL https://herdr.dev/install.sh | sh
# 或者
brew install herdr
安装完在任意项目目录输入 herdr:
herdr
首次启动自动创建一个 workspace(以当前目录或 git 仓库名为名),一个 tab,一个面板。你在面板里输入 claude 或 opencode 启动 agent,herdr 自动识别。侧栏立即出现该 agent 的状态。
键盘绑定和 tmux 相似——默认为 Ctrl+B 前缀:
| 操作 | 快捷键 |
|---|---|
| 横切面板 | Ctrl+B v |
| 竖切面板 | Ctrl+B - |
| 新建标签 | Ctrl+B c |
| 切换标签 | Ctrl+B n / Ctrl+B p |
| 工作区导航 | Ctrl+B w |
| 新建工作区 | Ctrl+B Shift+N |
| 分离客户端 | Ctrl+B q |
鼠标操作是全覆盖的:点击面板切换焦点、拖拽边框调整大小、右键弹出菜单。习惯鼠标操作后,前缀键反而用得少。
配置文件在 ~/.config/herdr/config.toml,支持 18 套内置主题(catppuccin、tokyo night、gruvbox、solarized 等),可通过界面 Ctrl+B 后选设置或在配置文件直接改。
支持的 agent
herdr 能自动检测以下 agent(部分通过屏幕输出,部分通过原生集成):
| agent | 状态检测 | 会话恢复 |
|---|---|---|
| Claude Code | working / blocked / done | ✓ |
| Codex | working / blocked / done | ✓ |
| OpenCode | working / blocked / done | ✓ |
| Pi | working / done / idle | ✓ |
| Grok CLI | working / blocked / done | — |
| GitHub Copilot CLI | working / blocked / done | ✓ |
| Kimi Code CLI | working / blocked / done | ✓ |
| Cursor Agent | working / blocked / done | ✓ |
| Qoder CLI | working / blocked / done | ✓ |
| Kiro CLI | working / done | — |
| Droid | working / blocked / done | ✓ |
| AMP | working / blocked / done | ✓ |
原生集成走 herdr integration install <name> 安装,提供更精准的状态上报和会话恢复。
实际工作流
以下是我用 herdr 之后的日常场景。
多项目并行
workspace: lls_blog (master) → opencode: idle
workspace: api-server (feat/xyz) → claude: working
workspace: dns-tools (main) → codex: blocked
三个项目各一个 workspace,各自跑一个 agent。切到 dns-tools 发现 codex 处于 blocked,切进去看是个权限确认弹窗——点一下继续,切回 api-server 继续改代码。
远程跑 agent,本地看
服务器上跑着几个长时间任务,herdr 保持 session:
ssh myserver
herdr # attach 回去,三个工作区里的 agent 全在跑
Zellij 也能做这件事,但 herdr 多了一层:你能在侧栏看到每个 agent 是 working 还是 blocked,而不是一个个面板翻过去检查。
agent 自己操作 herdr
herdr 的 Socket API 允许 agent 自己创建面板、切分窗口、读其他面板的输出:
# agent 可以这样自己操作 herdr
herdr pane split 1-1 --direction right
herdr pane run 1-2 "just test"
herdr wait agent-status 1-1 --status done
herdr pane read 1-2 --source recent-unwrapped
这层能力让我想到一个场景:主 agent 在处理任务,让 herdr 开一个副面板跑测试,跑完自动读结果。不需要人来切窗口。
live handoff:更新不杀面板
herdr 有一个 tmux 和 Zellij 都没有的能力:更新 server 二进制时保留所有面板进程。
作者在技术博客里详细解释了实现:不是移动进程,而是通过 Unix SCM_RIGHTS(文件描述符传递)把 PTY master FD 从旧 server 传给新 server。旧 server 暂停读线程、序列化状态、把 FD 打包发给新 server,新 server 重建运行时、恢复读写——面板里的进程不需要知道 server 换了。
我在更新 0.6.8 → 0.6.9 时试了一次 herdr update --handoff,面板里的 opencode、一个 Python HTTP server、以及 btop 都在更新后继续跑。btop 因为用了 alternate screen,重连后画面需要等一次刷新才恢复对齐,但进程没断。
和现有工具的共存关系
我仍然用 tmux 做服务器端的终端持久化——很多服务器没有 herdr,tmux 是标配。Zellij 在我的工作机上继续留着,它的浮动面板和 WASM 插件生态是目前独有的。
herdr 在 AI coding agent 这个场景下替代了 Zellij 的角色:不止是让 agent 不因为终端断连而挂掉,而是让我同时管好几个 agent 的时候不用记住"3 号项目在 5 号面板里刚刚弹了一个确认窗"。
参考