npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@muzi3/dsh-plugin-herdr-tools

v0.2.4

Published

DSH plugin: herdr_layout / herdr_pane / herdr_agent tools — inspect and create Herdr terminal topology, drive ordinary commands in panes, and control coding agents. Port of @muzi3/herdr's pane-agent-tools.

Readme

@muzi3/dsh-plugin-herdr-tools

DSH 插件:把 Herdr 的 pane / agent 操作做成注册式工具。默认挂载是四个 herdr_overview、herdr_layout、herdr_pane、herdr_agent;挂载时传 config.manager: true 则换成八个 manager 动词 —— 与一个手工版参考实现(薄封装 herdr CLI 的 manager 插件,本包是它的产品化版本) 逐名逐参一致,便于两套实现做消融对比。见「两种工具面」。

herdr_layout / herdr_pane / herdr_agent 移植自 pi 包 @muzi3/herdr 的 pane-agent-tools 扩展(该扩展 fork 自 @ogulcancelik/pi-herdr 0.4.0,MIT, Copyright (c) 2026 Can Celik);herdr_overview 与 agent prompt 的 agent_not_ready 回退是 DSH 侧新增,pi 版没有(见「与 pi 版的差异」)。

为什么需要它

DSH 侧原本只有 herdr-ops 这类 skill 文档:模型每次操作 herdr 都得自己把 CLI 命令拼出来,还要每次重新记住这些坑。文档兜不住这些错误:

  • pane run 成功时 exit 0、stdout 为空,看着像失败,容易被误报;
  • --timeout 是 herdr 自带的参数 —— 不要指望 shell 里一定有 timeout/gtimeout;
  • wait-output 的超时表示「没观测到」,不是命令失败;
  • 命中行可能是命令回显,而回显在命令跑完之前就已经存在了。

herdr_pane / herdr_agent 把这些判据固化成代码,参数交给 schema 校验; herdr_overview 再把「一次看清全局」也做成一次调用。

两种工具面:默认 4 个 / manager 8 个

同一个包提供两套互斥的工具面,由挂载时的 config 选:

| 模式 | 开启方式 | 注册的工具 | |------|----------|-----------| | 默认 | 不传 config | 恰好 4 个:herdr_overview / herdr_layout / herdr_pane / herdr_agent | | manager | config.manager: true(env 兜底 DSH_HERDR_TOOLS_MANAGER=1) | 恰好 8 个动词:herdr_overview / herdr_read / herdr_wait / herdr_prompt / herdr_run / herdr_create / herdr_agent_start / herdr_close |

两套不共存:manager 模式下不注册那 4 个通用工具。否则工具面就不是与手工版 1:1,消融实验会比出「模型选错工具」的噪声,而不是两套实现的行为差异。

怎么开:config 是主开关,env 是兜底

Cordis 调用插件的形式是 callback(ctx, config),loader 条目里的 config: 块会作为 apply 的第二个参数传进来。所以:

- insert:
    - id: herdr-tools
      name: '@muzi3/dsh-plugin-herdr-tools'
      config:
        manager: true

config.manager 是主开关;DSH_HERDR_TOOLS_MANAGER=1 是等价的 env 兜底,两者都认、 config.manager === true 优先。用 env 的好处是不必改 loader 条目 —— 想在同一份配置里 把两套工具面做成可切换的消融开关时更省事。

manager 模式同样只在 herdr 里注册(HERDR_ENV=1 且有 HERDR_PANE_ID),理由 与默认面相同。手工版没有这道门 —— 它在 herdr 外也注册 8 个、靠脚本 exit 3 拒绝; 见下面的「已知差异」。

与手工版的参数对应

| 动词 | 参数(与手工版逐字一致) | 底层 herdr 调用 | |------|--------------------------|-----------------| | herdr_overview | limit / workspace | pane current --current + workspace list + agent list | | herdr_read | target / scope / source / lines / mode / tail | agent read / pane read(agent 视图失败回退 pane,via 说明) | | herdr_wait | target / until / timeoutMs | agent wait --until --timeout | | herdr_prompt | target / prompt / wait / force | agent prompt →(agent_not_ready)pane run | | herdr_run | pane / command | pane run | | herdr_create | kind / workspace / label / cwd / direction / focus | workspace create / tab create / pane split | | herdr_agent_start | name / kind / pane / timeoutMs | agent start | | herdr_close | pane / dryRun | pane get(预览)/ pane close |

要点:是 timeoutMs 不是 timeout;herdr_agent_start.kind 是自由字符串(没有 enum,手工版也没有);herdr_create.direction 缺省时从 pane 几何判断; herdr_close.dryRun 默认 true(只预览)。统一信封是 { ok, exitCode, timedOut?, output, note?, via? }。

manager 模式是 DSH 侧新增、pi 版没有:pi 扩展只有拓扑原语,没有这套动词面。

已知差异(manager 模式 vs 手工版)

判据与安全边界对齐,措辞与机制上有这些差异:

  1. 底层实现不同。手工版 execFile python3 <skill>/scripts/herdr,把 skill 脚本当 第二份真值(带 preflight 门禁);本包直接调 herdr CLI,复用本包的 execHerdr / execHerdrJson / execHerdrText,不依赖那个脚本。因此 output 是本包自己的 文本渲染(列表 / 摘要 / 读屏),不是脚本的归一化输出 —— 内容等价、措辞有出入。
  2. exitCode 取值域。手工版沿用脚本的 0/1/2/3/-1;本包只会产生 0/1/2/-1, 没有 3(不在 herdr 里)—— 因为本包在 herdr 外一个工具都不注册,走不到那一步。
  3. herdr 外注册数:手工版始终注册 8 个(调用时 exit 3);本包注册 0 个。
  4. herdr_overview 的 workspace 真的生效。手工版把它透传给脚本,而脚本的 layout workspace-list 忽略它、agent list 也没接 —— 参数等于摆设。本包按 workspace_id 客户端过滤拓扑段与 agent 段(见下文「herdr_overview 的 workspace 语义」)。这是有意的差异。
  5. 列表截断文案。本包复用默认面那份 capList:[Showing X of Y agents — raise with limit];手工版是 ... — raise with --limit N]。纯措辞。
  6. herdr_prompt 的解析兜底更强。手工版只用一次 agent get 解析 pane id,解析 不到就拒绝回退;本包复用 resolveAgentPaneId,agent get 失败后还会扫一遍 agent list。更少拒绝、不会更差;解析不出来同样明确报错、绝不猜。
  7. 回退后的成功文案。手工版回退走脚本,output 是 Submitted command to pane X; 本包是 Submitted prompt to pane X。两者都在 via 里写明 pane run <pane>(agent prompt 不可用:对方是自报 agent,非 herdr 命名 agent)。
  8. 校验文案。herdr_agent_start 的名字/超时校验、herdr_close 的自 pane 拒绝, 手工版来自脚本(中文提示 + 示例),本包是等义短句。判据与 exitCode=2 一致。
  9. 本地超时的 output。手工版本地超时会带上已读到的部分 stdout;本包走 execHerdr 的中止路径拿不到部分输出,output 为空、note 说明「未观测到 ≠ 失败」、timedOut: true。herdr_wait 的 herdr 侧超时两套一致:ok:false + note,timedOut 不置位(那是 herdr 的等待上限,不是本地超时)。
  10. herdr_read 回退时的 via 文案:手工版嵌脚本首行错误,本包嵌 herdr 错误 消息首行。结构一致、措辞不同。
  11. 参数描述文案:本包在个别参数上把描述写得更准(如 herdr_create.workspace 注明 kind=workspace/pane 时忽略),参数名、默认值与行为不变。

默认工具面:四个工具

| 工具 | 用途 | |------|------| | herdr_overview | 舰队快照(只读):调用者自己的位置 + workspace 拓扑 + agent 列表(名称/状态/cwd/pane id)。管别人的第一步 | | herdr_layout | 查看/创建 workspace、tab、pane 拓扑(current / *_list / *_create / *_focus / pane_layout / pane_split) | | herdr_pane | 操作裸终端 pane:get / run / read / wait_output / send_text / send_keys / close | | herdr_agent | 操作 pane 里被识别出的 coding agent:list / get / start / prompt / wait / read / send_keys / focus / rename |

herdr_overview 的 workspace 语义(本包的选择)

workspace 同时约束两段:workspace 拓扑段 和 agent 列表段。给了它就是 「这个 workspace 的视图」,不传才是全机快照。调用者自身的位置段永远不受它约束。

为什么这样选:手工版的参数描述说「只看某个 workspace 的拓扑」,但 agent list 仍 全机返回,与描述不符(其脚本层实际上还把 --workspace 丢掉了,参数等于摆设)。 两条路里我们选了「让 agent list 也按 workspace 过滤」—— 因为 herdr agent list 虽然没有 --workspace 选项,但每条 agent 记录都自带 workspace_id,按它做 客户端精确过滤即可,不需要额外请求、也不靠 pane 反查,语义与描述终于一致。 指定了不存在的 workspace 时,拓扑段和 agent 段都为空,并附一行提示。

只在 herdr 里注册:apply() 检查 HERDR_ENV=1 且有 HERDR_PANE_ID, 不成立就注册零个工具 —— 避免在非 herdr 环境暴露四个必然失败的工具。

与 pi 版的差异

| 项 | pi | DSH | |---|---|---| | 参数 schema | TypeBox | DSH 的 ParameterSchemaSpec({type, enum, required}) | | 输出 | 内联 content blocks | 必填 output.schema + render | | 执行 | pi.exec | ctx.shell.resolve/run | | 结果渲染 | renderCall/renderResult | 刻意不实现(见下) | | herdr_overview | 无此工具 | DSH 新增:一次调用拿到位置 + 拓扑 + agent 列表 | | agent prompt 的 agent_not_ready 回退 | 无(pi 版直接报错) | DSH 新增:回退成 pane run 键入 |

这两项是 DSH 侧新增,pi 版没有:pi 扩展只暴露拓扑原语,而驱动一支 agent 舰队还需要「一次看清全局」和「够得着 herdr 不代它输入的 agent」这两件事。

两处因 DSH 的 spec 没有 pattern / minimum 关键字,约束移进了函数体:

  • agent 名必须匹配 ^[a-z][a-z0-9_-]{0,31}$;
  • agent start 的 timeout 必须 > 3000 且 <= 300000。

模型可见的文案与 pi 版逐字一致,因为 render 完整保留了原措辞。 presentCall/presentResult 没做:pi 的渲染器画的是 pi 自己的主题,照搬只会 引入第二份真值,而模型侧输出已经完全一致。

保留的加固

  1. 不要求 JSON envelope 的写操作:pane run / send-text / send-keys 成功时 stdout 为空。若强制解析 JSON,会在命令已经下发到目标 pane 的情况下误报 "Expected JSON output"。close / wait-output / agent send-keys 确实返回 envelope,照常解析。

  2. timeout ≠ 失败:wait_output 超时返回 matched:false 加 pane 尾部输出; agent prompt 遇到 agent_prompt_stalled 返回「已下发(submission accepted), 但 5s 内未观测到 working/blocked」,并明确提示不要重发。

  3. 正则元字符自动升级:match 含 | ( ) [ ] { } ^ $ * + ? \ 且未显式传 regex 时按正则处理 —— 字面量语义下 a|b 永远不可能命中。

  4. echoedInput 判据:记录本进程最近一次下发给某 pane 的文本;命中行包含它时 提示这是回显行、命令可能还没跑完。

  5. 拒绝关闭自己所在的 pane:close 先比对 pane current,相同则报错。

  6. agent_not_ready 回退到 pane run:绝大多数被管理的 agent 是 dsh-tui 这类 自报 agent,不在 herdr 的命名 agent manifest 里,agent prompt 会对它们 返回 agent_not_ready(is not an active named agent)。命中该错误码时自动 回退成 pane run <完整 pane id> <prompt>(文本 + Enter 直接键入)。

    • 回退前必须先解析 pane id:pane run 只认完整限定 pane id,而 target 可能是 agent 名。先 agent get <target> 取 .result.agent.pane_id,失败再扫 agent list 按 pane id / 名字匹配;解析不出来就明确报错,绝不猜一个 pane 去键入(键错终端比失败更糟)。
    • 只对错误码 agent_not_ready 回退,其它错误照旧上抛。
    • 输出里三条路可区分:语义路径 Prompt settled/submitted: ...;回退路径 Prompt 已回退为 pane run 键入 <pane> ...;stalled 路径 submission accepted ... 不要再下发一次。回退路径同样提示「已键入 ≠ 已开始 干活」,并把该 pane 记进 echoedInput 判据。

安装与挂载

npm install @muzi3/dsh-plugin-herdr-tools

在 profile 的 cordis.patch.yml 里插入一行:

- insert:
    - id: herdr-tools
      name: '@muzi3/dsh-plugin-herdr-tools'
      inject: []

只 inject 两个 host 注册表(tools、shell),不发布服务,因此挂在 profile 层 或 agent preset 里都可以。

注意

  • pane id 必须完整限定:是 w1B:pF 这种,不是侧边栏短名 pF;传短名会报 pane_not_found。工具从 .result.pane.pane_id(agent 则是 .result.agent.pane_id)取,一定是完整的 —— agent_not_ready 回退也走同一条 解析,解析不出来就报错,不会拿短名去 pane run。
  • isConcurrencySafe 一律返回 false:工具携带自由文本参数 (command/text/keys/match/workspace),不该并发命中同一个 pane。herdr_overview 其实是只读的,但它同样遵守这条统一契约,免得为它单开一份真值。
  • manager 模式沿用手工版的并发划分:只读的 herdr_overview / herdr_read 标为可并发,其余六个(会往 pane 里键入)互斥。注意 defineTool 会先做参数校验, 参数不合 schema 时一律返回 false。

开发

npm test

test/ 用 stub host 驱动 apply(),覆盖 schema 契约、参数对齐与错误归因分支, 不触碰真实的 herdr server。

许可

Apache-2.0 AND MIT:内容来自 Herdr(Apache-2.0)并 fork 了 @ogulcancelik/pi-herdr(MIT,见 LICENSE)。