Publish a DeepSeek Harness plugin to npm: build traps

Plugin DevelopmentPublished 2026-09-12Author: DeepSeek Plugin Market
DSH pluginDeepSeek Harnessnpm publishdistributionallowBuilds
How to publish a DeepSeek Harness plugin to npm: why git installs need prepare and allowBuilds, pre-publish package.json checks, and pnpm publish or pack.

The core value of publishing a DeepSeek Harness plugin to npm is distributing prebuilt code: what users install from npm is already compiled, so installing triggers no build script and needs no allowBuilds permission. A git install pulls sources instead, and without a prepare script there is no lib/ — it breaks the moment it installs. The same constraints apply to every DSH plugin you ship.

First, the trap: a DSH plugin git install gets sources

A git install never runs your build script, so a TypeScript package arrives without its lib/ output. The official docs are blunt about it, and the fix has two halves (source):

  1. Author side: ship a prepare script (pnpm runs it after a git install) that builds the published entry points from source, and make it self-contained — it must not assume dev-only context such as a sibling monorepo checkout.
  2. User side: allow the build. pnpm ≥10 refuses to run a git dependency's prepare by default, so the first dsh plugin --profile demo add github:you/hello-plugin fails; dsh points out the fix, which is writing the package key pnpm printed into the profile's pnpm-workspace.yaml — after which the add should be expected to succeed:
yaml
allowBuilds:
  dsh-hello-plugin: true

Take that allowance seriously: it means "permission to execute this package's code on your machine at install time," outside any sandbox the agent runs under. Allow only packages whose source you trust, and pin a commit (github:you/hello-plugin#<sha>), or a later push could silently change what actually runs.

Why publishing a DSH plugin to npm is easier

Publishing to npm moves the build from the user's machine into your release process. The two distribution paths the official docs describe as needing no build permission at all are:

PathWhat is distributedUser needs build allowance?
pnpm publish to npmThe lib/ built at publish timeNo
pnpm pack tarballThe built artifactsNo

On the user side, dsh plugin add <package> is enough to get prebuilt code. That is the entire reason to prefer npm — not reputation, but one less install-time authorization and one less class of failure.

DSH plugin pre-publish checklist

Five items, none optional; missing one shows up as "installed but not in effect" rather than a clear error.

  1. main (or exports) points at the built entry — not src/;
  2. type: module;
  3. files includes the entry and cordis.patch.yml — drop the patch file and the config layer never installs;
  4. dsh.bundle.patch points at the patch file — drop it and the package installs as a plain dependency with no layer;
  5. version is bumped — npm refuses to overwrite a published version.

Install it locally with dsh plugin add ./hello-plugin before publishing; the package layout and layer order are covered in packaging into a bundle.

The DSH plugin publish flow

The flow is short; the risk sits in the checklist above. A typical sequence:

  1. Build the publish artifacts: pnpm run build, which you should expect to leave lib/ current.
  2. Self-test through the install path: in a clean profile run dsh plugin --profile demo add ./, which you should expect to load the plugin and apply its behavior.
  3. Publish: pnpm publish.

Two easily missed points: ① a scoped package (@your-scope/xxx) must declare itself public on first publish, or it defaults to private; ② tag the matching git commit afterwards, so "the version users installed" maps to "the commit in your repo" — that saves time when debugging in production.

Alternative: shipping a DSH plugin as a pnpm pack tarball

For internal distribution or a pilot, use a tarball instead of npm. The official route:

  1. Author side: pnpm pack, which you should expect to produce dsh-hello-plugin-0.1.0.tgz.
  2. User side: dsh plugin add ./hello-plugin-0.1.0.tgz, which you should expect to install the built artifacts.

A tarball is also built code, so it needs no build permission; the trade-off is no version index, so upgrades mean shipping a new file.

Verifying a published DSH plugin

Verify in a clean environment, or you are testing "dependencies already present locally" rather than "the package is complete."

  1. Use a different profile (or a clean machine): dsh plugin --profile fresh add <package>;
  2. Inspect the layer before booting: dsh --profile fresh --dump-config to confirm the bundle's layer appears;
  3. Boot and watch the plugin's log lines;
  4. To list it in the plugin directory, follow publishing to the plugin hub, then check the installed list in DSH Plugin Hub.

If install reports a missing entry, first check whether the file main points at is inside files — the most common npm-publishing failure. It works locally because src/ exists there, but the published package does not carry it. Environment-level issues (Node version, pnpm) are covered in environment setup.

FAQ

Why does a DeepSeek Harness plugin installed from GitHub often break right away?

**Because a DSH plugin git install fetches sources, not built artifacts**: nothing runs your build script, so a TypeScript package arrives without its lib/ output and fails to load. The fix has two halves — the author ships a prepare script (pnpm runs it after a git install) that builds the entry points self-containedly, and the user allowlists the build (source: official "Package and install a plugin").

What is pnpm's allowBuilds and why should it be treated carefully?

**allowBuilds is the DSH plugin install-time allowlist that lets a git dependency run its build script**: pnpm ≥10 refuses to run a git dependency's prepare script until it is explicitly allowed, and dsh points at the fix — copying the package key pnpm printed into the profile's pnpm-workspace.yaml under allowBuilds and re-running the add. **Treat it as permission for that package to execute code on your machine at install time**, allow only packages whose source you trust, and pin a commit (github:you/plugin#<sha>) so a later push cannot silently change what runs (source: official "Package and install a plugin").

How does publishing to npm differ from publishing a GitHub repo for DSH plugins?

**Publishing a DSH plugin to npm distributes prebuilt code, so installing triggers no build script and needs no allowBuilds permission**; a GitHub repo distributes sources, which requires a prepare build plus a user allowance. The two paths the official docs call out as needing no build permission are exactly: publish to npm (with lib/ built at pnpm publish time) and ship a tarball from pnpm pack (source: official "Package and install a plugin").

Which package.json fields should you check before publishing a DSH plugin?

**Before publishing a DSH plugin, check five fields in package.json**: main (or exports) points at the built entry; type: module; files includes the entry and cordis.patch.yml; dsh.bundle.patch points at the patch file; and version is bumped. Missing any of the first four shows up as "installed but not in effect" or "failed to load" rather than a clear error (source: official "Package and install a plugin").

Is there a distribution option that avoids both npm and user build allowances?

Yes: **run pnpm pack to produce a tarball and have users install it with dsh plugin add ./hello-plugin-0.1.0.tgz**. A tarball contains built artifacts and needs no build permission, which suits internal distribution or a small pilot before publishing to npm (source: official "Package and install a plugin").

Related Terms

prepare script
prepare is the DSH plugin package.json lifecycle script that pnpm runs after a git install. Plugin authors use it to build the published entry points self-containedly, without assuming dev-only context such as a sibling monorepo checkout.https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md
allowBuilds
allowBuilds is the DSH plugin user-side allowlist in a profile's pnpm-workspace.yaml. pnpm ≥10 refuses to run a git dependency's build script until its key is listed, which amounts to authorizing that package to execute code at install time.https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md
bundle
A bundle is an npm package that ships a configuration layer, declaring its patch file via dsh.bundle. When a DSH plugin is published to npm, this package is what users install with dsh plugin add.https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md
pnpm pack
pnpm pack is the alternative DSH plugin distribution route: it turns the current package into a tarball (a .tgz by default) whose contents follow the files field. Users can install it directly with dsh plugin add ./xxx.tgz, with no build permission needed.https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md

Sources