herdr 的安装及 cooperative multi-CLI agent 配置
herdr 官文档首页有个「或者让你的智能体来介绍」的入口,挺有意思,我就顺着它把 herdr 装上了:目标是想让多个 CLI agent 在一个终端里搭伙干活。这篇按我的实际路径走——先装起来,再接上我的 hermes profile,最后让一个 agent 去指挥另一个 agent。所有命令都是这台机器 2026-10-25 的真实跑法。
herdr 是什么
herdr 是一个面向 AI 编码智能体的终端工作区管理器。先给结论:它是一个 multiplexer(复用器),和 tmux 同类——后台 server 持有真实的终端进程,客户端 attach 上来渲染;detach、关掉终端、断开 SSH,pane 里的东西照常跑。
和 tmux 的差异只有两条,但都是本质性的:
- mouse-first:整个 UI 可点击——pane、tab、workspace、分割边框、右键菜单、拖选复制。不需要学任何快捷键就能用(想用键盘时,prefix 默认是
ctrl+b,prefix+?现场列出所有生效绑定)。 - agent-aware:herdr 会识别 pane 里跑的编码智能体(claude、codex、opencode 等),在侧边栏显示每个 agent 的生命周期状态。跨项目扫一眼就知道哪个 agent 在
working、哪个blocked卡在审批、哪个done。
概念模型,按这个顺序理解:
| 概念 | 是什么 |
|---|---|
| Session | 常驻后台 server 的命名空间。跑 herdr 即 attach 默认 session,多数人只需要默认的 |
| Workspace | 项目级容器,一个 repo/任务一个;sidebar 按它汇总 agent 状态 |
| Tab | workspace 内的布局,比如分 agents / logs / server 几个视图 |
| Pane | 一个真实终端,可右/down 分割,detach 后存活 |
| Agent | herdr 识别出的 pane 内进程,状态五种:working / blocked / done / idle / unknown |
| Modes | terminal 模式把按键发给焦点 pane;prefix 模式(ctrl+b 后一个动作键)发命令给 herdr |
安装:让 agent 自己带我装
我的路径很简单——不自己读文档,把官方给 agent 的引导页喂给 agent,让它带人走完:
1 | Help me understand and set up Herdr. Read https://herdr.dev/agent-guide.md first, |
agent-guide.md 是官方专门写给「教人类装 herdr 的 agent」看的。下面这张表是我贴的 prompt 和 agent 实际会做的事的映射,等于把粗暴路径展开了一遍:
| agent-guide 让 agent 做的事 | 对应的动作 |
|---|---|
先查环境变量 HERDR_ENV=1 |
已经在 herdr pane 里就跳过启动(herdr 禁止嵌套启动) |
| 引导安装 | Linux/macOS:curl -fsSL https://herdr.dev/install.sh | sh;stable 渠道,升级用 herdr update;验证 herdr --version |
| 首次运行 | cd 进项目跑 herdr——启动或 attach 默认后台 session,自动建 workspace,首跑有 onboarding 流程 |
| 在 pane 里启动编码 agent | 直接跑 claude / codex 等,herdr 自动检测并显示状态;有集成就装:herdr integration install claude(提供原生会话恢复,状态仍来自屏幕检测) |
| 鼠标优先教学 | 点击聚焦、拖分割边框、右键菜单、拖选复制,全程不碰键盘 |
| 键盘进阶(可选) | prefix+v 右分割 / prefix+minus 下分割;prefix+c 新 tab;prefix+q(ctrl+b 松开后按 q)detach |
| detach 与回收 | prefix+q 或直接关终端,一切继续跑;重连 herdr;真正全停 herdr server stop |
不想让 agent 带路的,走官方安装页(Homebrew / mise / Nix 都有):https://herdr.dev/docs/install/。配置文件在 ~/.config/herdr/config.toml(Linux/macOS),不配也能用:herdr --default-config 打印全量默认值,改完 herdr server reload-config 热加载,主要区块是 [keys] [theme] [ui] [terminal] [update]。
在终端中输入herdr验证安装成功与否:

让 agent 学会操作 herdr:skill 赋能
herdr 自带一份可复用的智能体技能文件 skills/herdr/SKILL.md,教 agent 在 herdr 窗格内直接操作 herdr:分 pane 不抢焦点、跑命令、读输出、等另一个 agent 干完活。安装到任何支持 skill 或自定义指令的编码 agent 里:
1 | npx skills add herdrdev/herdr --skill herdr -g |
-g全局安装到所有受支持的 agent;去掉-g只装当前项目。- 如果是从旧版仓库布局装的,重新跑一次
add(不要用skills update),它会替换过大的旧副本。 - 没有 skill 系统的 agent:把 GitHub 上的 SKILL.md 内容直接粘进它的项目/用户指令。仓库副本是事实来源:https://github.com/herdrdev/herdr/blob/v0.9.5/skills/herdr/SKILL.md。
- 已装 herdr 的话,
herdr --skill直接输出与当前二进制版本匹配的内置副本。
关键安全护栏:skill 的第一条规则是——如果 HERDR_ENV=1 没设置,agent 必须停下并声明自己不在 herdr 管理的窗格内。这防止 herdr 外部的 agent 去控制一个不属于它的会话。所以装完 skill 后,agent 进程必须在 herdr 内启动(herdr 然后 claude),环境变量才有值。
对默认位置的 agent,这一行就够了。我的主力 agent 是 hermes 的命名 profile(general_researcher_create),npx 这条路根本不认识它——下一节。
hermes 命名 profile 的接入:一个根因,两个落点
两条通用装法在我这儿都不成立:npx skills 只往默认 profile 的 skills 目录写,herdr integration install hermes 只往 ~/.hermes/config.yaml 写。根因是同一个——herdr 和 npx skills 都不认识 profile;而每个 profile 目录本身就是一套完整的 Hermes home(自己的 config.yaml 和 plugins/),所以两个落点各有各的指法:skill 用 -p 参数,integration 用 HERMES_HOME 环境变量。
skill:走 hermes 原生安装
格式不是问题:hermes 的 skill 本来就是「目录 + SKILL.md frontmatter(name/description)」,herdr 那份恰好就是这套格式,hermes skills inspect 能完整解析它(识别出 name: herdr、description,trust 记 community)。问题在安装器:npx skills add … -g 对 hermes 的落点是字面解析的 ~/.hermes/skills/——默认 profile 的目录,而 npx skills 不认识 HERMES_HOME,命名 profile 永远不会读它。hermes 有原生命令 hermes skills install(接受 hub id 或 SKILL.md 直链),-p 直接指定 profile,自动过守卫扫描、进 lock 跟踪、之后可统一 check / update / uninstall。
1 | hermes -p general_researcher_create skills install \ |
URL 钉 master 而不是版本 tag。 hermes 对 URL 型技能没有廉价 revision 探针(基类 current_revision 固定返回 "",tools/skills_hub_install.py:264),每次 skills check 就是重新 GET 那个 URL、拿内容和安装时记录的 content_hash 比,不一致就报 update_available。于是钉 tag(如 v0.9.5)内容冻结、check 永远 up_to_date 永不更新;钉 master 才能在上游一改就被检出。update 内部是重装目录、重过扫描,本地改过的 skill 默认跳过(--force 才覆盖)——skill 后来做了 Hermes 适配(见 §4.3),这个「默认跳过」正好护住定制段不被误覆盖。顺带证伪一条捷径:herdr.dev 上的 skills/herdr/SKILL.md 等路径返回 200,但内容是 SPA 兜底 html——官方没有「latest」指针 URL,raw.githubusercontent 的 master/tag 是唯二选择。代价也明说:master 跟仓库 HEAD 走,skill 可能短暂领先本机 herdr 二进制(出现二进制还没有的 flag),herdr update 后即对齐。
--force 的来历:首次 install 被守卫扫描(skills-guard-v10)拦下,报 1 处 leak_system_prompt(high / injection)——误报。定位(tools/skills_guard.py:256):规则正则 output\s+(?:\w+\s+)*(system|initial)\s+prompt 想拦的是「输出系统提示词」那类注入话术,实际命中的是 herdr SKILL.md 第 202 行 “do not request file output in the initial prompt”——那里 output 是名词(「文件输出」),整句是「不要在初始 prompt 里就要文件输出」的良性操作提示,与泄露系统提示词毫无关系。核实后强装,扫描 provenance 记下这次人工核实决定(hash sha256:75a2770… 可追溯)。
验证:
1 | hermes -p general_researcher_create skills list | grep herdr # herdr / url / community / enabled |
回退:hermes -p general_researcher_create skills uninstall herdr。
生效:skill 索引在会话启动时快照,新 skill 要新会话才出现在技能清单(或 /reload-skills 重扫);其它 profile(cyber / industrial / robot)换 -p 重复即可,四个 profile 现已全部装上并完成 Hermes 适配(见 §4.3)。注意:早先「配每周 skills update herdr 定时器自动跟上游」的思路已作废——skill 适配后不能裸跑 update(源码行为是 rmtree 重装,master 原版会抹掉适配段),上游更新必须走 §4.3 的合并流程。
integration:把 HERMES_HOME 指向 profile 目录
官方集成文档的「Hermes Agent」节给了落点规则:herdr 写入 Hermes 主目录下的 plugins/herdr-agent-state/,并在该主目录 config.yaml 的 plugins.enabled 里启用 herdr-agent-state;HERMES_HOME 在 Unix 上默认为 ~/.hermes。会落到 ~/.hermes,就是因为普通终端里跑 install 时没有这个变量——Hermes 运行时会向子进程导出 HERMES_HOME=~/.hermes/profiles/<当前profile>,所以 herdr integration status 在 herdr 里指向的是「当前会话所属的 profile」。在哪个 shell 里跑 install,落点就跟着那个 shell 的 HERMES_HOME 走,显式传参最稳。
前提:目标 profile 目录已存在(~/.hermes/profiles/general_researcher_create/config.yaml 在)。
命令(改前先备份):
1 | cp ~/.hermes/profiles/general_researcher_create/config.yaml \ |
实际输出:
1 | installed hermes integration plugin to /home/poincare/.hermes/profiles/general_researcher_create/plugins/herdr-agent-state |
验证:
1 | # 1) 插件文件就位(__init__.py + plugin.yaml,与默认 profile 装的逐字节一致) |
实测输出:hermes: current (v5) (/home/poincare/.hermes/profiles/general_researcher_create/plugins/herdr-agent-state/__init__.py)。
回退:HERMES_HOME=~/.hermes/profiles/general_researcher_create herdr integration uninstall hermes(或备份覆盖回 config.yaml,再删掉 plugins/herdr-agent-state/ 目录)。
收尾提醒(官方原话):安装后需重启 Hermes 以加载插件——下次在 herdr 里以该 profile 启动 hermes 时生效。其它 profile 同理:把 HERMES_HOME 换成对应目录,重复同一命令。在hermes的 general_researcher_create 检查 herdr 是否真的集成进来了:

skill 的 Hermes 适配与更新纪律:合并,不是覆盖
装完只是底座。master 原版的 SKILL.md 是 agent 无关的通用写法,hermes 会话实测会踩到它没写的坑,所以这份 skill 在本地做了 Hermes 适配;而且四个 profile 的副本必须逐字节一致——一份改了,三份跟着同步,同步完 sha256sum 必须四行同一个哈希。当前统一版 sha256 ef31dd16…(18466 B,上游 master 15171 B)。
先立纪律:永远不要裸跑 hermes skills update herdr。 源码级验证过(skills_hub.py:1042 / skills_hub_install.py:264):update 对 URL 型 skill 是 rmtree 整目录、从钉的 URL 重装——等于拿 master 原版把适配段整个抹掉。上游更新必须走下面的合并流程。
当前适配 delta(上游 master → 统一版,共 7 处;更新时必须原样带走的段):
| # | 位置 | 适配内容 |
|---|---|---|
| 1 | frontmatter description |
触发措辞:用户要求分 pane / 指挥其它 agent(Cursor、Codex…)的意图即触发,不必显式点名 Herdr |
| 2 | 开头 HERDR_ENV 检查段 |
agent 工具 shell(terminal / execute_code 内核)spawn 在 pane 之外时 $HERDR_ENV 可能为空——不能据此断定「不在 Herdr」;查 /proc/<TUI pid>/environ 或用 herdr agent list(cwd + 终端标题)匹配会话确认,然后按显式 pane ID 操作 |
| 3 | --current 兜底段 |
报 --current requires HERDR_PANE_ID 时用 herdr pane current --current 解析出 pane ID 后显式传 --pane,不要从 layout 输出里猜 |
| 4 | 首 prompt 前读屏段 | 先 agent read <name> --source visible:首跑 onboarding(如 workspace-trust)对话框会吞掉第一次提交、报 agent_prompt_stalled;等 idle 后重发一次 |
| 5 | wait / blocked 段 | blocked 状态可能滞后于屏面,且下一个审批可能已在原位等待——判断前用 --source visible 看真实对话框 |
| 6 | 审批纪律两条 | 良性命令给最小权限 Run (once)(allowlist / Run Everything 越过本任务持续生效,破坏性/超范围先问用户);asdf local 写 .tool-versions 的命令按 n 跳过、改用工具绝对安装路径 |
| 7 | 文末自维护段 | 「Maintain this Hermes-adapted skill」——本节这套合并流程的英文自述,随 skill 本体携带,让任何会话读 skill 就知道更新纪律 |
从上游更新(合并式,五步)。前提:四份副本当前一致;有差异先同步再动。
1 | # 1) 拉上游最新版到临时文件 |
若合并后需要重建 lock 记录而重跑 skills install,会再撞守卫对那句 benign 提示的 leak_system_prompt 误报——照 §4.1 的核实结论用 --force,provenance 已有先例。
适配段本身也会演进:下次协同再踩到新坑,先改进当前最全的那份(它就是事实来源),随即 cp 同步另外三个——skill 文末自维护段写的就是这条。
回退:四份互为备份,任一份坏了从另外三份 cp 回来;全部丢失则重跑 §4.1 的 install(拿回 master 原版)再按 delta 表逐段重套适配。
实录(2026-10-25):为 cyber / industrial / robot 三个 profile 补装(grc 先前已装):
1 | for p in cyber_hacker_destory industrial_boss_cheat robot_engineer_stable; do |
随后两次对齐:第一次用 grc 的适配版覆盖三个新装的(四份 3d080568… 一致);当天晚些 cyber 那份又沉淀进「工具 shell 环境变量陷阱」(delta #2)与「文末自维护段」(delta #7)两段,再以它为准同步四份(ef31dd16…),skills check herdr 四个 profile 均 up_to_date。这个「谁最全谁当基准」的漂移正是维护约定要盯的对象——每次同步后 sha256sum 必须四行同哈希,发现不一致就以最全的一份为准同步。
多 CLI agent 协同的基本原理
脚本可以控制 agent,一个 agent 也可以给别的 agent 派活、查状态、收结果。核心是给任务选对原语:
| 原语 | 职责 |
|---|---|
| 布局(workspace / tab / pane 拓扑) | 创建和组织终端位置 |
| Pane | 控制原始终端:运行命令、发送输入、读取输出、等待输出 |
| Agent | 按名称或 pane + 生命周期状态,控制已识别的编码 agent |
两条边界要记牢:
- pane 可以没有 agent。agent 只是 herdr 在 pane 里识别出的当前进程,所以
agent start需要一个现有的 shell pane,绝不创建、拆分或移动布局。 - 建东西读 JSON,别猜 ID。创建命令都返回 JSON,从响应里取 pane_id:
1 | created=$(herdr workspace create --cwd ~/project --label api --no-focus) |
返回结构:workspace create 给 .result.workspace / .result.tab / .result.root_pane;tab create 给 .result.tab / .result.root_pane;pane split 把新 pane 放在 .result.pane。
agent 身份与启动
- pane ID(如
w1:p2)标识终端位置;agent 名称(如reviewer)是「该 pane 里当前 agent」的别名,规则[a-z][a-z0-9_-]{0,31}、全局唯一。agent 退出或被替换时别名清除——它不是永久改名。 - agent 命令既接受唯一的活跃名称,也接受 pane ID。手动启动的 agent 会被自动检测,用
herdr agent rename w1:p2 reviewer补个稳定名字。 --kind选支持的智能体:claude、codex、gemini、cursor、opencode、copilot、kimi、qwen、grok、hermes等二十余种;--后面的参数原样传给该可执行文件。- 前置条件:目标 pane 必须停在交互式 shell 提示符——shell 占着前台,没有前台命令/编辑器/agent。
- 成功的
agent start只有在 herdr 于同一终端检测到预期 agent 且可接受输入后才返回;若启动期间检测到blocked,立即返回agent_not_ready(名字仍可用于agent read/agent send-keys,等到idle就能发 prompt)。默认等 30 秒,--timeout取值 3000–300000 ms。
1 | herdr agent start reviewer --kind codex --pane "$review_pane" -- -m gpt-5.4 |
控制界面怎么选
| 目标 | 命令 |
|---|---|
| 运行并提交 shell 命令 | pane run |
| 发送不带 Enter 的纯文本 | pane send-text |
| 发送终端按键/修饰键 | pane send-keys |
| 等待文本或正则 | pane wait-output |
| 在现有 pane 启动 agent | agent start |
| 提交 prompt,可选等待 | agent prompt |
| 向 agent 交互界面发按键 | agent send-keys |
| 等待 agent 生命周期状态 | agent wait |
分界线:shell、测试、服务器、CI watcher 这类普通终端进程走 pane 命令;需要 herdr 理解「跑的是哪个 agent、处于什么状态」时走 agent 命令。pane 输入直接指定终端、不管前台是什么进程;agent 输入会解析活跃 agent,agent 不再控制该 pane 时拒绝操作。
实战配方
起一个 reviewer,派活,收结果
1 | # 在当前 pane 右侧分一个新 pane |
agent 卡在审批界面的处理
blocked = herdr 识别到了审批/提问界面。agent prompt --wait 遇到 blocked 时不会发送任何输入,直接返回 agent_blocked——先读屏看它问什么,再明确应答:
1 | herdr agent wait reviewer --until blocked --timeout 120000 |
跑普通进程并等输出(不当成 agent)
1 | herdr pane run w1:p3 "just test --watch" |
用自然语言指挥其它 CLI agent 干活(hermes 当编排者)
现在前提齐了:herdr 在跑,hermes -p general_researcher_create 在 herdr 里启动(§4 的 integration 与 skill 都已就位),而 skill 教的就是 §5 这套原语。能不能直接对它说人话,让 cursor 的 agent 去编程?
能。 前提在 §3、§4 都兑现了,剩下唯一没验的是被指挥方:cursor-agent 在 PATH,cursor 集成 v2 已装。
原理是两层翻译。herdr 本身不懂自然语言,也刻意不提供「多 agent 怎么分工同一任务」的编排逻辑(官方立场:只给协调原语,任务分解/冲突协调/结果合并由用户自己搭)。所谓「用自然语言指挥」,实际是:
- 你 → hermes:在 herdr 里跑的
hermes -p general_researcher_create会话里直接说人话——「在右边开个 pane,让 cursor 给 X 补测试,干完告诉我」; - hermes → herdr CLI:hermes 装了 herdr skill 且
HERDR_ENV=1(所以在 herdr 内启动是硬前提),skill 教它全套原语命令,它自己执行并汇报。

hermes 不写代码,它是翻译官 + 监工:把你的意图翻成 pane split / agent start / agent prompt --wait / agent read 序列,盯着状态、收结果;真正干活的才是 cursor。
它实际跑的就是 §6.1 那四步,只换两处:--kind cursor(cursor-agent 在 PATH)、超时给到 300000 ms 而不是 120000——补测试比 review 一个 diff 慢得多:
1 | herdr agent start coder --kind cursor --pane "$pane_id" |
卡在审批怎么办(闭环的关键一跳):--wait 返回时若是 blocked——cursor 在等权限审批——hermes 不该瞎按。正确动作是 agent read 读屏,把「它在请求什么权限」转述给你,等你拍板后再 agent send-keys coder enter(同意)或 esc(拒绝)。这就是「自然语言指挥」的完整含义:连审批问答都会被翻译成人话,而不是 hermes 替你放权。
结果验收的分寸:hermes 收到的只是终端文本,不等于工作质量。产出物验收(测试真跑通没、diff 长什么样)由 hermes 用普通工具复核——读文件、跑测试。编排逻辑在这一层,herdr 只负责让两个 agent 够得着对方。
当前实测状态:herdr 里 agent 数为 0——把 hermes -p general_researcher_create 在 herdr 里跑起来、新会话加载 herdr skill 后,对它说一句话即可触发整条链。经验上可先用 §6.3 的 pane run 拿一个无害进程试链路(echo + wait-output),再上真 agent。
状态语义与坑
idle 与 done 的区别是「看没看过」:两者都表示可以接受输入。done 是「尚未被标记已查看的 idle」;显式 pane focus / agent focus 会标记目标,读取不会。每个 TUI 客户端各自记录自己展示过的 done,所以 TUI 里的 done 标记可能和 CLI 的不同。语义敏感时用 --until 指定精确状态(可重复:--until idle --until done;要 unknown 必须显式写)。
unknown = agent 存在但 herdr 判不了生命周期——不代表工作成功完成。
等不到不代表没提交。超时或 agent_prompt_stalled 都不意味着输入没发出去,重试前先 agent read,避免重复提交同一 prompt。
启动/切对话不算完成:一个立即开干的 agent 可能在 herdr 首次看到空闲提示前就完成了第一轮任务。部分 agent 响应带 completion_seq,把这次 idle 转换独立标记为「完成的工作」,该值与同次转换的 state_change_seq 相同;旧 server 可能没有这个字段。
全屏 agent 的历史读取:claude code / opencode 这类全屏 agent 把对话画在备用屏幕里,不进 herdr 的主机回滚缓冲。当已识别 agent 处于 idle、对话在底部、且 --lines 超过可见屏幕时,recent / recent-unwrapped 读取会自动走 agent 的鼠标滚动界面翻页收集。但若 agent 处于 working/blocked/unknown,显式的 agent read --lines N 会返回 agent_not_idle——先等 idle,或用 --source visible。实在读不全的兜底:让 agent 把回复写成 markdown 文件、只回路径,直接读文件。
等待命令没有默认超时,可能无限等:agent wait / pane wait-output 不给 --timeout 就一直挂。超时/服务器错误把 JSON 错误写 stderr 并以状态码 1 退出(语法错误是 2),脚本里按退出码分支。
pane move 会改 pane ID:带 workspace 前缀的 ID 在移动后变化,pane move 之后要接着用 .result.move_result.pane.pane_id,旧值保留在 .result.move_result.previous_pane_id。运行中的进程保留启动时的 herdr 环境,旧 HERDR_PANE_ID 继续作别名,--current 仍安全;但已经在途的等待会以 agent_not_running 结束。
参考链接
- 中文文档首页(含「或者让你的智能体来介绍」入口):https://herdr.dev/zh-cn/docs/
- agent guide(写给教人装 herdr 的 agent):https://herdr.dev/agent-guide.md
- 智能体自动化(协同原理):https://herdr.dev/zh-cn/docs/agent-automation/
- 智能体技能文件:https://herdr.dev/zh-cn/docs/agent-skill/
- 集成页(「Hermes Agent」小节的落点规则、各 agent 的 install/uninstall 命令):https://herdr.dev/zh-cn/docs/integrations/
- CLI 参考:https://herdr.dev/docs/cli-reference/;socket API:https://herdr.dev/docs/socket-api/
- 键盘页(prefix 与免冲突组合键):https://herdr.dev/docs/keyboard/


