Herdr 面向 AI Agent 的终端工作区管理器
Herdr 是一个终端多路复用器(terminal workspace manager),定位和 tmux 类似,但它是为「同时跑多个 AI coding agent」这个场景设计的。
核心差别在于:tmux 只知道某个 pane 里有个进程在跑;Herdr 能识别出 pane 里跑的是 claude / codex / pi / cursor 这类 agent,并把它的生命周期状态(idle / working / blocked / done / unknown)暴露出来。这样 agent 之间就能互相编排——一个 agent 可以开一个新 pane,在里面拉起另一个 agent,发 prompt,等它跑完,再读结果。
安装
macOS 上用 Homebrew:
brew install herdr
herdr status
herdr status 会分别打印客户端和服务端信息:
client:
version: 0.8.0
channel: stable
protocol: 19
server:
status: running
version: 0.8.0
compatible: yes
socket: /Users/elon/.config/herdr/herdr.sock
protocol 要求客户端和服务端一致,升级后如果 restart_needed: yes 就得重连会话。
会话管理
Herdr 是 server / client 架构,服务端常驻,客户端只是 attach 上去的 UI。
herdr # 启动或接入默认会话(TUI)
herdr --session work # 用/创建一个命名会话
herdr session list # 列出所有会话及状态
herdr session attach work # 接入已有会话
herdr session stop work # 停掉某会话的服务端
herdr session delete work # 删除会话数据(不可逆)
herdr --remote user@host # 通过 SSH 接远端 Herdr
stop 只是关掉服务端进程,会话目录还在,之后 attach 能重新起来;delete 才会清掉数据。停默认会话用 herdr session stop default,等价于 herdr server stop。
注意别在活跃会话里随手 herdr server stop——它会连带杀掉所有 pane 里的进程。
配置
配置文件在 ~/.config/herdr/config.toml。
herdr --default-config # 打印默认配置作为模板
herdr config check # 校验配置并打印诊断
herdr server reload-config # 热加载,不用重启会话
herdr config reset-keys # 备份配置并清掉自定义快捷键
herdr completion zsh # 生成 zsh 补全
更新渠道分 stable 和 preview:
herdr channel show
herdr channel set preview
herdr update
三层结构:workspace / tab / pane
Herdr 的终端拓扑是三层的,ID 是稳定且不复用的句柄:
| 层级 | ID 形式 | 说明 |
|---|---|---|
| workspace | w1 | 最外层,通常对应一个项目或一个 worktree |
| tab | w1:t1 | workspace 内的标签页 |
| pane | w1:p1 | tab 内的分屏,实际跑进程的地方 |
pane ID 是 workspace 限定的,所以 pane move 到另一个 workspace 后会拿到新 ID,旧 ID 不能再当通用目标用。
查看和创建:
herdr workspace list
herdr workspace create --cwd ~/code-space/myproj --label myproj
herdr tab list --workspace w1
herdr tab create --workspace w1 --cwd "$PWD" --label build
herdr pane list --workspace w1
herdr pane split --current --direction right --cwd "$PWD" --no-focus
创建类命令的返回值里带着后续要用的 ID:workspace create 返回 .result.workspace、.result.tab、.result.root_pane;tab create 返回 .result.tab 和 .result.root_pane;pane split 返回 .result.pane。要从 JSON 里解析 ID,不要靠猜或者靠侧边栏顺序推。
pane 还有一整套布局操作:
herdr pane layout --current # 看当前 pane 几何
herdr pane neighbor --direction right --current # 找邻居 pane
herdr pane focus --direction left --current
herdr pane resize --direction right --amount 0.1 --current
herdr pane zoom --current --toggle
herdr pane swap --direction down --current
herdr pane rename w1:p2 tests
herdr pane close w1:p2
分屏方向有个经验规则:宽的 pane 往右切,窄的或高的往下切,避免同方向反复切出没法用的细长条。
在别的 pane 里跑命令
这是最常用的场景——把测试、构建、日志丢到旁边的 pane,自己这边继续干活。
# 1. 开一个兄弟 pane,保持调用者的 cwd 和焦点
herdr pane split --current --direction right --cwd "$PWD" --no-focus
# 从 .result.pane.pane_id 拿到新 pane ID
# 2. 跑命令(send text + Enter 是原子的)
herdr pane run w1:p2 "npm test"
# 3. 等输出
herdr pane wait-output w1:p2 --match "Tests:" --timeout 120000
herdr pane wait-output w1:p2 --regex "FAIL|PASS" --timeout 120000
# 4. 读输出
herdr pane read w1:p2 --source recent-unwrapped --lines 120
pane read 的 --source 有四种,选对了很重要:
visible:当前渲染的视口。recent:最近的渲染输出,保留软换行。recent-unwrapped:最近输出但把软换行拼回去,读日志和长文本首选。detection:Herdr 用来做 agent 识别的底部纯文本快照。
需要颜色作为判断依据时用 --format ansi,否则用默认的 text。
如果 --lines 加大了也读不到更多内容,大概率是 pane 里的程序跑在终端的 alternate screen 上——滚出去的行不会进 Herdr 的 scrollback,加行数救不回来。这时候的兜底办法是让 agent 把完整回答写成 Markdown 落到临时目录,只回一个路径,然后直接读文件。
控制另一个 agent
pane 和 agent 是两套接口。pane 管原始终端,agent 管被识别出来的 coding agent —— 后者才有生命周期状态语义。
agent start 要求目标 pane 已经存在、处于交互提示符、前台没有别的命令在跑。它自己不会去创建或分屏。
herdr agent start reviewer --kind codex --pane w1:p2
herdr agent start reviewer --kind codex --pane w1:p2 -- <原生参数>
支持的 kind 相当全:pi / claude / codex / gemini / cursor / devin / cline / opencode / copilot / kimi / kiro / droid / amp / grok 等。原生参数必须放在 -- 之后。
agent 名字要匹配 [a-z][a-z0-9_-]{0,31} 且在活跃 agent 中唯一。名字跟着 pane 的当前占用者走,agent 退出或被替换时自动清空。
agent start 会一直阻塞到 Herdr 确认同一个 pane 里出现了预期的 agent 并且能接受输入为止,默认 30 秒超时。
发 prompt 并等结果:
herdr agent prompt reviewer "Review the current diff, report only actionable findings." --wait --timeout 120000
agent prompt 会原子地提交文本和 Enter,并且尊重 pane 当前的 bracketed-paste 模式。--wait 等的是第一个稳定下来的 idle / done / blocked 状态,一般够用,不用再叠 --until。
--until 留给状态特定的流程,比如等一个已经在跑的 agent 主动要输入:
herdr agent wait reviewer --until blocked --timeout 120000
其他检查和交互:
herdr agent list
herdr agent get reviewer
herdr agent read reviewer --source recent-unwrapped --lines 120
herdr agent send-keys reviewer esc
herdr agent send-keys reviewer ctrl+c
herdr agent focus reviewer
herdr agent attach reviewer --takeover
herdr agent explain reviewer --verbose
send-keys 用的是逻辑键名,Herdr 会在写入任何字节之前先校验全部按键。
状态语义
这几个状态的含义有点微妙,值得单独说:
working:正在干活。idle:准备好接受输入,并且它所在的 tab 已经在焦点 UI 里被看到过。done:底层和idle是同一个状态,区别是这次后台工作还没被人看到。聚焦 tab、或者用 focus 命令指向它,就会标记为已看到;纯 CLI 读取不会。blocked:Herdr 识别出了一个审批或提问界面,在等人回答。unknown:pane 里有 agent,但 Herdr 没法可靠分类。这不等于跑完了。
另外,从非 working 状态发出的 prompt 必须在 5 秒内产生可观测的状态变化,否则 Herdr 直接返回 agent_prompt_stalled,不会无限等下去。这个 wait 跟踪的是生命周期状态而不是单个 turn——如果 agent 本来就在 working,当前 turn 结束就能满足条件。
Git worktree 集成
Herdr 把 worktree 当一等公民,适合让多个 agent 在不同分支上并行改同一个仓库而不互相踩:
herdr worktree list --cwd "$PWD"
herdr worktree create --cwd "$PWD" --branch feat/foo --base main --label foo
herdr worktree open --cwd "$PWD" --branch feat/foo
herdr worktree remove --workspace w2
其他
agent 集成(往各个 agent 的配置里装 Herdr 的状态上报钩子):
herdr integration status --outdated-only
herdr integration install claude
herdr integration install codex
桌面通知,跑完长任务提醒一下:
herdr notification show "构建完成" --body "耗时 3m12s" --sound done
调试和自省:
herdr api snapshot # 当前完整运行时状态
herdr api schema --output /tmp/herdr-schema.json
herdr pane process-info --current
给 agent 用的注意事项
herdr --skill 会输出一份完整的 agent skill 文档,比 --help 详细得多。里面几条规则值得摘出来:
- 先确认自己在 Herdr 里。 控制命令只在 Herdr 管理的 pane 内有意义,判断条件是
test "${HERDR_ENV:-}" = 1。不满足就别去动焦点会话。 - 用
--current或显式 ID。 省略目标可能命中 UI 焦点 pane,而那个 pane 可能属于用户或另一个客户端。 - Herdr 会把调用方上下文注入每个受管 pane:
$HERDR_WORKSPACE_ID、$HERDR_TAB_ID、$HERDR_PANE_ID。 - 不要跑裸
herdr去探索命令,那会拉起 TUI。想看某个命令组就直接跑组名,比如herdr pane、herdr agent。但也别对会改状态的嵌套命令省参数试探——herdr workspace create是带默认值合法的,真会执行。 - 后台任务默认加
--no-focus,别抢用户的焦点。 - 不要关掉不是自己创建的 workspace / tab / pane / session。
- 做实验用独立的命名会话,别碰主进程。
- 服务端错误是 stderr 上的 JSON,退出码 1;CLI 语法错误退出码 2。
小结
如果只是想要个多路复用器,tmux 够用。Herdr 的价值在于它把「agent 的状态」变成了可查询、可等待的一等概念——agent prompt --wait、agent wait --until blocked、pane wait-output --regex 这几个原语加起来,就能写出真正可靠的多 agent 编排脚本,而不是靠 sleep 和抓屏猜。