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

@aiwayds/dsh-subagent-registry

v0.1.3

Published

dsh plugin: register locally-defined custom agents (~/.dsh/agents/*.md) as callable subagents via the use_agent tool

Readme

dsh-subagent-registry

Register locally-defined custom agents (~/.dsh/agents/*.md) as callable subagents in dsh: the main conversation can invoke any of them by name through the use_agent tool, and each runs as a real dsh subagent with its own persona (system prompt).

中文简介:把 ~/.dsh/agents/*.md 定义的自定义 agent(frontmatter 元数据 + markdown 正文作为 persona)注册成 dsh 可按名调用的 subagent。主对话通过 use_agent 工具点名调用;每个自定义 agent 以独立 subagent 运行,拥有自己 的 system prompt,跑在 dsh 自带的 spawn provider 上,不需要 patch dsh 本体。

How it works

  • One file per agent: <agents-dir>/<name>.md — a loose key: value frontmatter block (name, description, model, deep, display_name, …) followed by a markdown body that is used verbatim as the child's persona (system prompt).
  • One tool: at session startup the plugin registers use_agent (configurable toolName). The tool's static description carries the roster — every agent name plus its sanitized description — so the main model can pick an agent by name.
  • At call time the target file is re-read and parsed; the body becomes the child's persona, the frontmatter model (provider/model route) is split into agentOptions, and the child is started through the already-assembled spawn subagent provider (the same single-instance realm dsh uses for its native subagent tool). The result is returned to the parent conversation.

Installation

Option A — add this checkout as a dsh plugin (tui profile):

dsh plugin --profile tui add ~/github/dsh-subagent-registry

Option B — npm dependency: npm i @aiwayds/dsh-subagent-registry, then load the plugin under the stable id dsh-subagent-registry in your profile's config, or mount it through a bundle patch (see cordis.patch.yml in this repo for the pattern).

Configuration

| Config field | Default | Description | | ------------- | -------------------- | ------------------------------------------------------------------------ | | agentsDir | ~/.dsh/agents | Directory holding <name>.md agent definitions. | | provider | spawn | Subagent provider the child runs through (reuses dsh-base's spawn). | | toolName | use_agent | Name of the registered tool. | | leafDenyTools | [] (computed default) | Explicit tool-deny list installed on deep: 0 (leaf) children. Empty = computed default (every agent-spawning tool in the dsh base distribution plus toolName). |

deep semantics

deep is the agent's spawn-depth budget, declared in the frontmatter:

| deep | Meaning | | ------ | -------------------------------------------------------------- | | 0 | Leaf: the agent runs normally but can never start a subagent. | | >= 1 | May start subagents. Default when the key is absent: 1. |

Implementation, at use_agent execute time:

  • deep: 0 — the start request carries toolFilter: { deny: [...] } and no maxDepth. The in-process spawn driver applies the filter as a scoped tools.restrict() in the child's creation window, so the named tools vanish from the child's tool prompt and refuse to execute — the child keeps its full non-spawn tool set but has zero spawn capability. Passing maxDepth: 0 (the old behavior) would have rejected the child's own start, since the child's absolute depth is always ≥ 1. Default deny list: subagent, subagent_fork, workflow, ralph, plus this plugin's own tool name (use_agent by default; a customized toolName is denied automatically). send_message / interrupt_agent / list_agents only address already-running children and cannot spawn, so they stay visible. Override with leafDenyTools when your deployment's tool set differs.
  • deep >= 1 — no toolFilter; maxDepth is set to the child's absolute depth plus deep — a relative budget. Start can never be blocked by the depth check (childDepth ≤ childDepth + deep always holds), while the "deep = how many generations of subagents I may open" reading is preserved. Each subsequent delegation level enforces its own per-request caps (the native subagent tool defaults to maxDepth: 3), which acts as the outer recursion backstop.

Default agent roster

The author's personal ~/.dsh/agents/ ships with three agents: workhorse (牛马狗, the general workhorse), oldfox (老法师, the review/audit oracle), and rubber-duck (小黄鸭). rubber-duck is the multimodal visual agent: it reads screenshots / charts / OCR text and draws plotext / mermaid / matplotlib figures, running on an image-capable model. It now occupies the role formerly filled by the removed ArtyDuck (艺术鸭) in this setup.

Usage example

A multimodal example — ~/.dsh/agents/rubber-duck.md:

---
name: rubber-duck
display_name: 小黄鸭
description: "小黄鸭:多模态视觉 agent,看图识别、OCR、画 plotext/mermaid 图……"
model: digitalvolvo/kimi-k2.7-code
thinking: max
extensions: ["*"]
---
你是「小黄鸭」——多模态视觉 agent。……(这里写完整的 system prompt)

Then ask in a conversation:

用 rubber-duck 看一下这个浏览器截图,描述页面状态并提取文字

The main model calls use_agent(agent: "rubber-duck", prompt: "…"), the child runs with the file body as its persona and an image-capable model, reads the screenshot, and its result comes back into the conversation.

A text-only example — ~/.dsh/agents/workhorse.md:

---
name: workhorse
display_name: 牛马狗
description: "牛马狗:干活的主力……"
model: opencode-go/deepseek-v4-flash
deep: 0
---
You are 牛马狗,干活的主力。……(这里写完整的 system prompt)

Then ask in a conversation:

用 workhorse 把今天的发布清单整理成表格

The main model calls use_agent(agent: "workhorse", prompt: "…"), the child runs with the file body as its persona, and its result comes back into the conversation.

Known limitations

  • deep is a per-agent relative budget enforced at each use_agent call; it does not re-arm deeper descendants. Real recursion is additionally bounded by every spawning tool's own maxDepth (native subagent tools default to maxDepth: 3) as the outer backstop.
  • Continuable / background follow-up conversations with a custom agent (send_message-style resumption) are v2; today every use_agent run is one-shot.
  • tools.restrict() validates the deny list against globally registered tool names and throws on unknown names — the default list only names tools the stock dsh base distribution always registers; non-stock deployments should tune leafDenyTools.

Publishing note (read before npm publish)

This plugin is a dsh plugin: its @deepseek-ai/* imports must resolve to the single dsh closure instance the host provides. Never declare @deepseek-ai/* in dependencies — pnpm would install a second copy of the cordis/dsh-session closure, breaking module identity and surfacing as bizarre runtime errors like Cannot read properties of undefined (reading 'prepare') in session-persistence. Keep them in peerDependencies (and devDependencies for local typecheck/build), matching @aiwayds/dsh-tui-pi's convention.

Development

npm run check    # tsc --noEmit -p tsconfig.json
npm run build    # tsc -p tsconfig.json -> lib/
npm test         # node test/deep-semantics.test.mjs (no LLM)

License

MIT