@muzi3/herdr
Herdr for pi: three independent extensions (agent + blocked state reporting, /pi-hot-restart, and the herdr_overview / herdr_read / herdr_wait / herdr_prompt / herdr_run / herdr_create / herdr_agent_start / herdr_close manager tools aligned with dsh's her
Package details
Install @muzi3/herdr from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@muzi3/herdr- Package
@muzi3/herdr- Version
0.3.0- Published
- Nov 4, 2026
- Downloads
- 310/mo · 202/wk
- Author
- muzi3
- License
- Apache-2.0 AND MIT
- Types
- extension, skill
- Size
- 106.8 KB
- Dependencies
- 0 dependencies · 0 peers
Pi manifest JSON
{
"skills": [
"./skills"
],
"extensions": [
"./extensions/herdr-agent-state/index.ts",
"./extensions/pane-agent-tools/index.ts",
"./extensions/pi-hot-restart/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@muzi3/herdr
Herdr 相关的官方 guide skill、pane/agent 控制工具与本地补充扩展打包为一个 pi package。
| 资源 | 类型 | 说明 |
|---|---|---|
herdr_overview / herdr_read / herdr_wait / herdr_prompt / herdr_run / herdr_create / herdr_agent_start / herdr_close |
扩展 | 管理工具面(8 个动词):一次盘点全机 agent、读屏、等落定、下发 prompt、跑命令、开新位置、启动 agent、关 pane。与 dsh 的 @muzi3/dsh-plugin-herdr-tools manager 面逐个对齐 |
herdr-guide |
user-invoked 向导 | 引导用户理解、安装、配置与排查 Herdr(herdr.dev/agent-guide.md) |
herdr-agent-state |
扩展 | 通过 Herdr 的 pane socket 上报 agent 状态(working / blocked / idle)及会话引用,供 Herdr 面板展示;并把 pi 的阻塞式交互弹窗(ui_prompt_start / ui_prompt_end,含 ask_user_question)转发为 herdr 的 herdr:blocked 事件,使 pane 变为 blocked(label 带问题摘要);桌面通知交给 herdr 自己发 |
pi-hot-restart |
扩展 | 提供 /pi-hot-restart 命令:批量重启当前 herdr 里的所有 pi 窗口(跳过 working),并恢复到原 session |
三个扩展互相独立:每个扩展独占 extensions/ 下的一个目录、以 index.ts 为入口,互不 import,package.json 的 pi.extensions 逐条列出入口。一个扩展注册失败不会连带拖垮另外两个,日后给某个扩展加内部模块也不会影响另外两个。
扩展结构
extensions/
├── herdr-agent-state/index.ts agent 状态 + blocked 状态上报
├── pane-agent-tools/index.ts herdr_overview · read · wait · prompt · run · create · agent_start · close
└── pi-hot-restart/index.ts /pi-hot-restart
| 入口 | 内容 | 加载门槛 |
|---|---|---|
herdr-agent-state/index.ts |
agent 状态 + blocked 状态上报(herdr 官方集成正文 + 本包并入的 blocked 段落) | HERDR_ENV=1 且 HERDR_SOCKET_PATH / HERDR_PANE_ID 非空 |
pi-hot-restart/index.ts |
/pi-hot-restart 命令(本包自研补充) |
无,走 PATH 调 herdr CLI |
pane-agent-tools/index.ts |
manager 8 动词面(herdr_overview / herdr_read / herdr_wait / herdr_prompt / herdr_run / herdr_create / herdr_agent_start / herdr_close) |
HERDR_ENV=1 且 HERDR_PANE_ID 非空 |
门槛由各扩展自己判断(没有统一 gate),所以在 herdr 之外 /pi-hot-restart 仍可用(它只控制本机进程,不需要 pane socket),依赖 pane 的两个扩展则静默跳过。
每个扩展目录的入口都叫 index.ts,与 pi 自己的目录式扩展约定一致:扩展目录内可以再放内部模块,pi.extensions 只指向入口,不会误加载旁支文件。
herdr-agent-state/index.ts 的目录名与 herdr 集成注入的文件同名,对齐上游时可以直接对比。内容分两段:官方集成正文(一直到文件末尾之前)与之后的「本包新增」段落。本包对官方正文只有一处改动:官方 export default 开头插入一行 registerBlockedReporting(pi); —— 该 default export 就是本扩展的唯一入口,blocked 上报只能挂在那里。重新同步上游时(HERDR_INTEGRATION_VERSION 从 8 往上升)重取注入文件替换官方正文并补回那一行;diff 应只有三处新增、零删除,漏帖那一行会被 tests/herdr-agent-state.test.ts 拦下。
来源与许可
两者内容均来自 Herdr 官方,上游仓库为 herdrdev/herdr:
herdr-guide引导 skill —— 官方herdr.dev/agent-guide.md,教 agent 引导用户理解/配置/排障 Herdrherdr-agent-state扩展 —— Herdr 官方pi集成的 bundled 扩展,本包保留其正文,只做一处改动(在官方export default开头插入一行 blocked 上报),其余新增都在文件末尾的段落里。herdr integration install pi会把官方版本写入~/.pi/agent/extensions/herdr-agent-state.ts(若设置PI_CODING_AGENT_DIR则写入$PI_CODING_AGENT_DIR/extensions/)
Herdr 以 Apache-2.0 许可发布,本包保留其许可声明,详见 LICENSE。
⚠️ 本包这份与集成写入的那份目录名相同、位置不同(本包
extensions/herdr-agent-state/index.ts,集成写~/.pi/agent/extensions/herdr-agent-state.ts)。若已执行过herdr integration install pi,agent 目录里的副本会被 pi 自动加载,与本包同时上报状态(herdr 的blockedCount会短暂变成 2,然后一起归零)。本包已自带该功能,用本包时不必安装集成;已安装的话请删掉~/.pi/agent/extensions/herdr-agent-state.ts。无论装不装集成,agent 目录里那份都由集成管理,重装或更新集成会覆盖它;自定义 hooks 请写成旁边的独立文件而非编辑它(本包这份是 vendored 副本,由本包自己维护)。
extensions/pane-agent-tools/index.ts(manager 8 动词面)来源与许可是这样分的:
- 面结构与判据语义移植自 dsh 侧同源实现的 manager 面:
@muzi3/dsh-plugin-herdr-tools(MIT,Copyright (c) 2026 muzi)的src/manager.js。pi 早期版本的herdr_layout/herdr_pane/herdr_agentaction 面已整体移除,两套不共存。 - 两者共用的 herdr 调用与摘要 helper(
execHerdr/summarize*/chooseSplitDirection等)血缘上来自@ogulcancelik/pi-herdr0.4.0(MIT,Copyright (c) 2026 Can Celik),许可全文见本包LICENSE.MIT。 - 因此本包整体仍按
Apache-2.0 AND MIT双许可表述:LICENSE(Apache-2.0)覆盖 Herdr 官方内容与pi-hot-restart.ts,LICENSE.MIT覆盖pane-agent-tools.ts的 helper 血缘。
相对 dsh manager 面的差异
工具名、参数、信封与判据逐条对齐,差异只有三处,都是 pi 侧刻意保留的加固:
agent_blocked与agent_prompt_stalled反向处理:前者是 herdr 在发送任何输入之前就拒绝,确定没下发,返回 exitCode 2 并指向先看清阻塞界面;后者是 submission accepted 之后没观测到 working/blocked,prompt 已下发,返回ok: true并劝阻重发。dsh manager 面把两者都当普通 herdr 错误。agent start --kind用枚举约束,等于herdr agent start --help的 possible values(0.9.5 共 24 个,含qwen/letta/muse)。herdr_agent_start保留agentArgs(放在--之后的原生参数):dsh manager 面漏了这个能力。
环境变量用 PI_ 前缀(PI_HERDR_PROMPT_GUARD / PI_HERDR_READ_MODE / PI_HERDR_READ_TAIL_LINES),语义与 dsh 的 DSH_HERDR_* 一致。
与 herdr 版本的对账(当前基线 0.9.5)
工具面是照着 herdr CLI 写死的,herdr 升级后会有静默缺口。已固化的两处:
agent start --kind的枚举必须等于herdr agent start --help的 possible values(0.9.5 共 24 个)。0.2.2 漏了qwen/letta/muse,这三个 kind 当时根本起不来;tests/里有对账用例,加新 kind 时同步改。agent_blocked必须与agent_prompt_stalled反向处理:目标卡在审批/提问弹窗时,herdr 在发送任何输入之前就拒绝 prompt,所以这不是「已下发」,重试也不会好 ——herdr_prompt返回 exitCode 2 并指向herdr_read先看清阻塞界面。
pane run / agent prompt 成功时退出码为 0 且 stdout 为空(0.9.5 实测),所以 herdr_run / herdr_prompt 只校验退出码,不要求 JSON envelope;真实失败仍经 parseHerdrError 读出结构化错误。
8 个动词没有覆盖、需要时直连 CLI 的命令族:herdr worktree、api、notification、session、machine、agent attach,以及 pane wait-output/send-text/send-keys/list/layout/focus/swap/move/zoom/resize/process-info/neighbors/edges/rename、tab list/focus、workspace focus、agent list/get/focus/rename/send-keys。其中 agent list 由 herdr_overview 覆盖,agent read / pane read 由 herdr_read 覆盖。
本包不依赖 @ogulcancelik/pi-herdr:同时安装两者会重复注册同名工具,需先卸载上游包。
安装
pi install npm:@muzi3/herdr
用法
- 用户询问 Herdr 是什么、怎么安装/配置/使用,或排查 agent 未识别、快捷键失效等问题时,触发
herdr-guide引导(/herdr-guide) - 触发词:
herdr/herdr 安装/herdr 配置/终端工作区/agent 状态检测等
管理工具面(8 个动词)
八个工具直接驱动 herdr CLI,需在 herdr 集成环境(HERDR_ENV=1 + HERDR_PANE_ID)中加载。每个工具返回统一信封:{ ok, exitCode, timedOut?, output, note?, via? } —— 正文先给 note(判据提示)、再给 output,details 里是同名字段。
| 工具 | 参数 | 做什么 |
|---|---|---|
herdr_overview |
limit / workspace |
一次拿到自己的位置 + workspace 拓扑 + 全机 agent 列表(只读,管别人的第一步) |
herdr_read |
target / scope / source / lines / mode / tail |
读屏;默认 digest(前段信号行 + 尾部 30 行),mode="raw" 看全量;agent 视图不可用时回退 pane |
herdr_wait |
target / until / timeoutMs |
等某个 agent 落定;超时只表示没观测到 |
herdr_prompt |
target / prompt / wait / force |
给别的 agent 下发 prompt;agent_not_ready 时回退 pane run 直接键入,via 说明实际路径 |
herdr_run |
pane / command |
在别的 pane 里原子下发一条命令(文本 + Enter) |
herdr_create |
kind / workspace / label / cwd / direction / focus |
建 workspace / tab / 兄弟 pane,默认不动焦点 |
herdr_agent_start |
name / kind / pane / timeoutMs / agentArgs |
在停着提示符的 shell pane 里启动 agent |
herdr_close |
pane / dryRun |
关 pane;默认 dryRun=true 只预览 |
exitCode 语义:0 成功 / 1 herdr 错误 / 2 参数或前置校验失败(没下发)/ -1 本地超时(此时 ok 仍为 true:本地截止时间只说明没观测到)。本地截止时间默认 120s,herdr_wait 是它请求的等待 + 30s。
环境变量(pi 侧用 PI_ 前缀,语义同 dsh 的 DSH_HERDR_*):
| 变量 | 默认 | 说明 |
|---|---|---|
PI_HERDR_PROMPT_GUARD |
on |
置 off 关闭「目标 working 时拒绝下发」的插队保护 |
PI_HERDR_READ_MODE |
digest |
herdr_read 的默认渲染模式,可设 raw |
PI_HERDR_READ_TAIL_LINES |
30 |
digest 原样保留的尾部行数 |
相对旧 action 面的能力差异
0.2.x 的 herdr_layout / herdr_pane / herdr_agent 三个 action 工具已整体移除:两套面共存会让模型选哪套全凭运气。随之丢掉的操作按需直连 CLI,主要是 pane wait-output(含 echoedInput 判定)、pane send-text / send-keys、pane list / layout、tab list / focus、workspace focus、agent focus / rename / send-keys。herdr_overview 覆盖 agent list,herdr_read 覆盖 agent read / pane read(不含 --format / --raw)。
批量重启 pi 窗口
在任意 pi 窗口执行 /pi-hot-restart,会:
- 列出当前 herdr 里所有
pi窗口; - 跳过
agent_status === "working"的窗口(含当前发起命令的窗口本身); - 弹出确认框,展示将重启的窗口清单与数量;
- 对每个目标窗口:向 pi 前台进程组发 SIGTERM 优雅退出(session 落盘),等待退出后用
pi --session <path|id>在原 pane 恢复。
等用户输入时上报 blocked
herdr 的 pi 集成只认 herdr:blocked 事件,且 herdr 0.9.0 对 pi 仍没有终端 blocked 识别规则(0.9.5 的 herdr agent explain 依旧显示 rule: none、screen_detection_skip_reason: full_lifecycle_hook_authority,内置规则只有一条 working_literal,匹配 Working...),所以 ask_user_question / confirm 弹窗期间 pane 会一直停在 working。本扩展的 blocked 上报段落订阅 pi core 的 ui_prompt_start / ui_prompt_end(select/confirm/input/editor/custom 统一包装,只在外层触发):
- 等待期发
herdr:blocked { active: true, label },结束后发{ active: false };label 形如等待回答:<问题 header>(custom无 title,取rpiv:ask-user:prompt的问题内容)、等待确认:<title>。 - 契约同 pi-subagents 的 herdr-status bridge:herdr 的
blockedCount是计数式的,切 label 前先发active:false再发active:true;本扩展严格配对,只占一个计数。
桌面通知交给 herdr 自己发(~/.config/herdr/config.toml 设 [ui.toast] delivery = "terminal"):通知经终端转交给 Ghostty 显示,点击横幅会把 Ghostty 窗口调到前面。注意它只能到窗口粒度 —— herdr 的 pane 是 herdr TUI 内部的概念,点通知不会切到对应 pane;正文也固定为 <工作区名> · <工作区编号> · <tab 名>,不含 pane id 与问题原文。早期版本试过自建横幅(osascript / terminal-notifier),内容能带 pane 与问题原文,但要么不支持点击动作、要么在本机通知权限不稳;点击跳转要能捕获回调的通知器(如 alerter)才可能做到,为避免与 herdr 自己的通知重复弹两份,自建横幅已整体移除。
扩展环境变量
扩展需在 Herdr 集成环境中运行,依赖以下环境变量:
| 变量 | 说明 |
|---|---|
HERDR_ENV |
为 1 时启用扩展 |
HERDR_SOCKET_PATH |
Herdr pane socket 路径 |
HERDR_PANE_ID |
当前 pane id(同时作为扩展的运行门槛) |
未设置时 herdr-agent-state 与 pane-agent-tools 两个扩展静默跳过(门槛见「扩展结构」),/pi-hot-restart 仍可用:它通过 PATH 调用 herdr CLI(agent list / pane process-info / pane run),不依赖上述变量。
测试
node --test tests/ # 等价于 npm test
tests/ 下三个文件、共 45 个用例,node:test + node:assert/strict,无需引入 bun(Node 原生剥离 TS 类型):
tests/pane-agent-tools.test.ts —— 33 个用例,按工具分组,全部走假 pi.exec:锁的是「herdr 的某种结局被归成哪个信封」以及这层自己加的守卫,而不是 herdr 服务器怎么答。
- 八个工具的名字与加载门槛(不在 herdr 里一个都不注册;旧 action 面不再存在)
herdr_overview:三段拼装、workspace收窄、limit截断写明隐藏条数、单段失败仍给其余段herdr_read:digest 压缩与raw、agent→pane 回退(via说明原因)、失败不压缩herdr_wait:落定、herdr timeout 的「没观测到」文案、其他错误按普通失败herdr_prompt:语义路径、--wait、插队保护(含force)、自己 pane、agent_not_ready回退、pane id 解析失败、agent_blocked/agent_prompt_stalled的反向处理herdr_run/herdr_create/herdr_agent_start/herdr_close:参数拼装与守卫(默认 dry-run、名字与 timeout 边界、agentArgs透传)
tests/herdr-agent-state.test.ts —— 起一个真实 unix socket 充当 pane socket,验证 agent 状态(working / idle)与 blocked 上报(含 label 取值、弹窗结束后的回落)真的落到连接上。用真 socket 而非桩:上报的成败判据本身就在连接上(sendRequestAttempt 只有连上并收到对端数据才算送达),桩掉 net 等于把被测逻辑一起桩掉。这一组只调 default export(扩展唯一入口),所以官方正文里那行 registerBlockedReporting(pi); 被漏帖时会直接失败。
tests/extensions.test.ts —— 把「三个扩展各自独立」锁成断言:pi.extensions 与 extensions/ 下的扩展目录一一对应(不漏声明、也不留死路径)、每个扩展目录都有 index.ts 入口且顶层没有散落的扩展文件、扩展之间没有跨目录 import,并且单独加载每个扩展时只会注册自己的资源(herdr-agent-state 只挂状态监听,pi-hot-restart 只有 /pi-hot-restart,pane-agent-tools 只有八个 manager 工具)。
参考
- 官方文档:https://herdr.dev/docs/
- 引导 guide 原文:https://herdr.dev/agent-guide.md
- 集成文档(Pi 章节):https://herdr.dev/docs/integrations/
- 上游仓库:https://github.com/herdrdev/herdr
- pi-herdr 上游仓库:https://github.com/ogulcancelik/pi-extensions/tree/main/packages/pi-herdr
- dsh 侧同源实现(manager 面):https://codeberg.org/muzi/dsh-plus