dsh plugin add is a thin pnpm forwarder. It passes your arguments to pnpm verbatim — no spec
parsing, no added flags, no subcommand allowlist, no confirmation prompt — and then reconciles
the profile’s layer list from the installed state. Any package whose package.json declares
dsh.bundle.patch is promoted to a mounted patch layer: an ESM module imported into the
harness process at the agent’s uid, with ungated top-level side effects, and a YAML layer that
applies after @deepseek-ai/dsh-base and can therefore override any field of any core row by
id — or set disabled: true on it.
The only thing dsh plugin add prints is a warning for the harmless case:
dsh: warning: <pkg> declares no dsh.bundle — installed as a plain dependency, not a profile layer
The dangerous case prints nothing.
There are over 5,000 repos tagged dsh-plugin — 5,071 when this was last counted, on 16 August
2026 — and no registry, no review, and no signing between any of them and your process. This tool
exists so that the moment before you install one is not a blank.
The report has two halves, and the first one is the point of the tool.
Facts — no severity, always printed. Whether the package mounts as a patch layer and from
which file, whether it ships a browser bundle, which rows it inserts and which existing rows it
modifies, the !!js inventory of the mounted layer, cordis YAML it ships that nothing mounts,
commands it puts on your PATH, its dependencies, what model-visible text it ships, and how much of
it could be read. A well-behaved plugin has a full facts section and an empty findings section.
That is a useful answer, not an empty one.
Findings — ranked, in three tiers:
| Tier | What it reads | What it can say |
|---|---|---|
| A | Structured declarations: package.json keys, Cordis patch rows, the !!js expression inventory |
A verdict. Confidence is certain, because the harness reads the same bytes the same way |
| B | Shipped source, through the TypeScript parser | A capability report: “this plugin can do X” |
| C | Whether the package could be read at all — minification, computed names, sourceless builds, binaries | That the analysis is degraded, and that no Tier B negative can be trusted |
Every Tier B and Tier C finding carries a bypass field naming the one-line evasion for that
specific check. It is inside the finding, not in a footnote, so a report cannot be rendered
without its caveat.
A finding is per package, not per syntax site. A package importing node:fs from eleven files
gets one finding with occurrences: 11 and three example locations, because the eleventh import
warrants no decision the first did not. Findings are grouped by check and subject — the module
specifier, the row id, the seam name, the matched rule — so node:child_process and
node:worker_threads stay two findings, and a gate can accept B13/node:fs without accepting
every B13.