dsh-plugin-anything: Making ALL Software DSH-Native
Turn anything into a DeepSeek Harness plugin.
One pipeline, one compiler, one verifier — for the harness where everything is already a plugin.
An agent-native compiler and verification pipeline that turns software capabilities into
installable, tested, and verified DSH plugins.
One command: dsh plugin --profile <profile> add dsh-plugin-anything-bundle — install, restart, and call
the tools. Surviving the restart is the whole point; it is what a dynamic package cannot do.
Golden E2E
The claim is in the name, and a claim like that is worth what its weakest category is worth. Each category is
a small but real representative, run through the whole deterministic pipeline — IR → compile → static gate →
build → typecheck → package integrity:
Git CLI ██████████ PASS
Python CLI ██████████ PASS
npm CLI ██████████ PASS
Local Script ██████████ PASS
GitHub Repository ██████████ PASS
OpenAPI ██████████ PASS
MCP Server ██████████ PASS
Pipeline coverage 15 / 15 stages mechanized
Runtime acceptance PASS (accept → accepted, with evidence)
Package integrity PASS (every promised entry is in the artifact)
node --experimental-strip-types scripts/golden-e2e.mjs
The table above is generated by that command and pinned by scripts/check-readme-status.mjs — a
hand-maintained status table drifts, and a drifted one is read as current.
MCP's PASS is a refusal, and that is the correct outcome. An MCP server already has a supported route
into dsh; generating a plugin for one duplicates that route. Its golden case asserts the compiler refuses
it and names the route to use instead — a category that "passed" by emitting a redundant plugin would be a
regression, and bundle/src/compile.ts throws to prevent it.
The pipeline is the unit, not the tool
bundle/src/pipeline.ts carries twenty stages, each with an owner and the reason
for that owner. Coverage is computed from it, never asserted:
| Owner |
Meaning |
If it has no tool |
deterministic |
Has a correct answer, or a contract that cannot be re-derived per run |
A hole |
runtime |
Reachable only through a running harness |
A hole |
agent |
Requires judgement |
Correct — mechanizing it replaces intelligence with a heuristic |
external |
Owned outside this project |
Nothing; named so the pipeline has no silent gap |
Eight tools cover fifteen stages, because a verdict like acceptance is one decision made of seven checks.
The coverage number is the thing to watch — not the tool count. docs/pipeline.md is
the full map.
What this is
DeepSeek Harness (dsh) is built on vendored Cordis,
where everything is a plugin: the model adapter, the tool registry, the session log, and the agent loop
itself. There is no privileged core, and every part is replaceable from cordis.yml.
dsh-plugin-anything is the missing on-ramp to that architecture. Given any operable target — an external
CLI, an HTTP/REST API, a local service — it produces an installable plugin bundle that a dsh agent can
load, call, and still have after a restart.
It is a deliberate isomorphic mirror of CLI-Anything: the same
phase-by-phase methodology, the same "use the real system, don't reimplement it" iron rule, the same
registry packaging — with every landing point translated into dsh's native concepts.
| CLI-Anything |
dsh-plugin-anything |
| GUI software → agent-usable CLI |
anything → dsh plugin bundle |
HARNESS.md 8-phase SOP |
the same 8 phases, dsh landing points |
core/ + utils/<sw>_backend.py |
src/ + src/provider.ts (the single egress module) |
click + REPL |
defineTool + ctx.tools.register |
SKILL.md |
SKILL.md (dsh frontmatter) + a mount row |
setup.py → PyPI |
package.json → npm / tarball / git |
registry.json + cli-hub |
the existing market registry — reused, not rebuilt |
Why it exists
dsh already ships a loop that generates plugins from a request: the cordis agent preset mounts
tool-cordis, and the model can inspect its own runtime, write a package, and run it. That loop is
excellent for exploration and useless for delivery:
Dynamic packages live only in the shared DSH process memory. […] They create no Plugin file, install no
package, change no cordis.yml or personal/project configuration, do not survive restart, and cannot be
promoted automatically.
— packages/extensions/tool-cordis/README.md
The gap is not generation. It is promotion — turning something that works for one session into a bundle
that persists, installs, and distributes. That, plus the SOP, templates, verifier, and CI discipline around
it, is what this project provides.
Layout
dsh-plugin-anything/
├── kit/ # the SOP kit — the single source of truth for how a bundle is built
│ ├── HARNESS.md # the 8-phase methodology. Read this before anything else.
│ ├── commands/ # /plugin-anything, :list, :refine, :test, :validate
│ ├── guides/ # progressive disclosure — one guide per deep area
│ ├── templates/ # the files a generated bundle is assembled from
│ ├── scripts/verify-plugin.mjs # the static gate
│ └── tests/ # the gate's own acceptance tests
│
├── bundle/ # the npm package: the plugin_anything_* tools
│ ├── src/ # tools.ts, pipeline.ts, ir.ts, compile.ts, inspect.ts, accept.ts, pack.ts
│ ├── tests/ # 141 tests over the whole surface
│ ├── scripts/ # accept-bundle.mjs, package-bundle.mjs, typecheck-example.mjs, render-example.mjs
│ ├── templates/ sop/ skills/ docs/ # shipped copies of what the tools read at runtime
│ └── cordis.patch.yml # the bundle's patch layer
│
├── examples/
│ ├── golden/ # one real representative per target category
│ └── dsh-plugin-git/ # a generated bundle, rendered from the templates
│
├── registry/ # the awesome-dsh-plugin entry, and the metadata that format lacks
├── notes/ # Agent Notes — the decisions, and what was rejected
├── scripts/ # the acceptance ladder, the golden E2E, three consistency checks
├── docs/ # pipeline.md, runtime-acceptance.md, and the archived plan
└── .github/workflows/ # CI: gates, golden E2E, composition against a real dsh
Two of those directories matter for distribution, and only one of them is published:
| Directory |
What it is |
How it ships |
bundle/ |
The npm package dsh-plugin-anything-bundle |
cd bundle && npm publish — installed by dsh plugin add |
kit/ |
The SOP, templates, and gate |
Nothing to publish. It is what this repository's own tooling and agents read. |
Quick start
# 1. Read the SOP. It is the authority on every phase.
# kit/HARNESS.md
# 2. Gate a generated bundle statically.
node kit/scripts/verify-plugin.mjs examples/dsh-plugin-git
# 3. Install and verify composition.
dsh plugin --profile dev add ./examples/dsh-plugin-git
dsh --profile dev --dump-config | grep -A3 '# == dsh-plugin-git'
# 4. Boot it, use the tools, then RESTART and use them again.
# Surviving the restart is the whole point — it is what a dynamic package cannot do.
dsh --profile dev
The kit
The methodology, templates, and gate that produce installable bundles. A generated bundle is an output of
it, and nothing here is derived from a generated bundle.
Contents
| Path |
What it is |
HARNESS.md |
The 8-phase SOP. Read it before anything else. |
commands/ |
Slash commands that execute the SOP: /plugin-anything, :list, :refine, :test, :validate |
guides/ |
Progressive disclosure. Each guide is loaded on demand, never up front. |
templates/ |
The files a generated bundle is assembled from — manifest, patch, plugin entry, provider, tool, build config, skill |
scripts/verify-plugin.mjs |
The static gate. Catches what fails silently. |
tests/verify-plugin.test.mjs |
The gate's own acceptance tests — every check against a mutant that must fail |
The guides
Loaded when a phase reaches them, not before.
The templates
package.json, cordis.patch.yml, index.ts, provider.ts, tool.ts, tsconfig.json,
tsdown.config.ts, SKILL.md — each carries the verified contract for its artifact as comments, including
the traps that produce a bundle which builds cleanly and then fails to load.
The gate
node kit/scripts/verify-plugin.mjs <plugin-dir> # a generated bundle
node kit/scripts/verify-plugin.mjs --kit # the kit's own structure
node --test kit/tests/verify-plugin.test.mjs # prove the gate's checks can reject
It is a static approximation and says so. It catches the mistakes that fail silently — a patch file the
gate's glob never sees, a row that matches nothing, an entry the Loader discards. It never claims a plugin
boots; only a real dsh --profile <p> --dump-config and a live tool call do that.
Conventions
- Every rule in the kit cites the
dsh source that enforces it. When a dsh doc and its gate disagree,
the gate wins — that has already happened once, and
in-tree-vs-out-of-tree.md records it.
- A check is not evidence until it has been observed rejecting something.
- Generated output is never hand-edited into correctness; fix the template.
The three rules
- Wrap the real system. Never reimplement it. Exactly one module in a generated plugin touches the
outside world; everything else is pure logic and testable without the backend.
- Render intent is part of the design.
generic / terminal / diff and locations are decided up
front, never after the fact.
- Presenters are pure functions. They run on live streaming and on session-log replay — no I/O, no
session state, no clock.
Non-negotiables the gate enforces
A patch file whose name does not contain cordis; a missing dsh.bundle.patch; a patch not listed in
files; a comments-only patch (it throws at boot); !!js outside config/disabled; an undeclared bare
plugin name in a row; a function plugin with a default export; an impure presenter — each is rejected.
The gate is itself tested against single-field mutants, so every check has been observed rejecting something.
Status
The pipeline is complete: 15 of 15 stages that require mechanization are mechanized, and the four that do
not are judgement by design. Everything below has evidence, not assertion.
|
Evidence |
| The kit's gates pass, and each rejects a mutant |
node --test on both suites |
A generated bundle compiles against the real @deepseek-ai/dsh-tools types |
both the scaffolded and the compiled output |
| Installation, composition, load, registration, persistence |
against a real dsh, on both release lines |
| The model sees and calls the tools |
a real turn listed all eight and called one |
| Presenters replay |
from a tool/result a real session logged |
| The full acceptance verdict |
accept → accepted, all seven stages with evidence |
| Seven target categories |
scripts/golden-e2e.mjs, 7/7 |
What is not. publish — registry submission — is not this project's to manage; the entry is
format-complete and blocked on a public repository existing. And dsh itself is in developer preview and
warns that compatibility-breaking changes will land, so the version you peer on matters:
kit/guides/bundle-distribution.md.
License
MIT — see LICENSE. The published bundle carries the same text, and
scripts/check-shipped-copies.mjs pins the two together, so a change to
one cannot quietly leave the other asserting the old terms.