DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Fleet Mesh — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins

dsh-fleet-mesh

Fleet Mesh

Session-aware mesh relay for DSH agents: an Ed25519-signed receive route and delivery policy, plus outbound sending, a peer directory and a mesh-peer-registry client.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add dsh-fleet-mesh@0.2.5
READMECompatibilityVersions

Compatibility and provenance

Fleet Mesh is published as dsh-fleet-mesh and currently resolves to version 0.2.5. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
any
Release source
npm
Registry updated
9/24/2026

Versions

0.2.5stable
9/24/2026
0.2.4stable
9/23/2026
0.2.3stable
9/22/2026

Related plugins

Loading related plugins…

Latest
0.2.5
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
99.2 kB
Files
15
Surface
any
License
MIT
Source
npm
GitHub
★ 0
Weekly downloads
0
Last push
9/24/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in integrations-communication.

Acp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseRemote Web Ui@linxin666/dsh-remote-web-uiScan-to-pair remote access for the dsh web GUI that shares one official interface: a QR beside the settings button pairs phones and PCs into the same Web GUI (a portrait-touch adaptation layer for phones, full desktop on PCs) through one-time tokens and rIm@xmanrui/dsh-im把十二种 IM 渠道和公网 AI Office 接入本机 DeepSeek Harness。 Connect twelve IM channels and a public AI Office to a local DeepSeek Harness.Univer Officedsh-univer-officeDSH × Univer integration with a bundled collaboration Gateway and Viewer: inline previews, live floating Worktree windows, and session-end review actions in DeepSeek Harness.

README

dsh-fleet-mesh

Session-aware mesh relay for DSH agents.

Standard agent-to-agent messaging is request/response — fine for one-shot jobs, inadequate for conversational coordination. dsh-fleet-mesh adds session-preserving communication: when one agent sends to another, the recipient knows who asked, what they are responding to, and whether an answer is wanted. An inbound envelope is not a notification; it is a prompt.

One plugin serves the whole substrate, not one agent: agents are configured in a single agents: map, and one port dispatches by the envelope's [to:] token. A second DSH agent needs no second plugin and no second listener.

Sender: mesh_send(agent="ada", message="Review this plan", action="do", reply="yes")
  │
  ├─ 1. Resolves Ada's identity from the peer directory
  ├─ 2. Pads [mesh][v:1][from:lily][to:ada][id:uuid][action:do][reply:yes]
  ├─ 3. Ed25519-signs "{timestamp}\n{body}" with the sender's own private key
  └─ 4. POSTs to Ada's mesh endpoint, inside one shared 10 s delivery budget

Status

Both halves are complete and tested — 170 assertions across four suites.

Receiving: signature verification, the delivery matrix, the wake list, the replay window, per-envelope dedupe, and the runaway breaker.

Sending: the five tools below, built on the same tested libraries — envelope signing, the delivery retry budget, the peer directory, and a registry client.

Tools

Named exactly as hermes-mesh names hers, so muscle memory transfers between substrates.

toolpurpose
mesh_listlist peers from the local identity store — read-only, no network
mesh_sendsign and deliver one envelope; reports delivered or a failure, never queues silently
mesh_syncfetch peer identities from the registry into this deployment's own cache
mesh_registerpublish this agent's row — name, receive URL and public key — to the registry
mesh_deregisterwithdraw this agent's row

mesh_send returns a result rather than a promise of one: state is delivered or error, and a failure names its cause (unreachable, unauthorized, unknown-peer, not-configured). There is no queue behind it — see below.

What it does NOT do

  • No outbound spool. A send either lands or fails informatively. A spool that reports success while nobody is home is a lie the sender then acts on.
  • No session.cancel. Interrupting an agent's work is a human's call, never a peer's.
  • No thread ledger yet. Terminal replies pass through; a ledger waits until a thread actually needs closing.
  • No fleet-wide wake policy. If a transport has none — as hermes-mesh does not, where signature verification at intake is the allowlist — then the wake list here is the only thing between a chatty peer and a bill.

Install

pnpm add dsh-fleet-mesh

Then add it to your profile's bundles. The plugin ships a neutral default: it inserts its row with no config, so a fresh install opens nothing and serves nobody.

Configure

Supply your own values as an id-targeted override in your profile's patch layer:

- id: dsh-fleet-mesh
  config:
    host: '0.0.0.0'            # loopback-only by default
    port: 8760
    allow:                     # the real door, checked before anything else runs
      - 192.168.0.0/23
    durableRoute: '...'        # named in an "unreachable" reply, so a sender is told
                               # where to write instead of retrying into a void
    agents:
      <agent-name>:
        preset: <preset>       # the session is resolved by PRESET, never by a pinned id
        sessionId: null        # optional override for the odd case
        keyPath: '...'         # this agent's Ed25519 private key (PKCS8 PEM)
        wake: []               # who may START a turn — empty ships by default

The plugin ships no subnets and no names: which networks may reach a listener, and who may wake an agent, are a deployment's decisions.

Why it binds its own listener

The obvious implementation is to register a route on the harness's own web server. It cannot work, and the reason is measured rather than assumed: that server binds 127.0.0.1 only, so a peer's POST never completes a TCP connection. Widening it to 0.0.0.0 would expose the entire web surface — GUI, API, and every other plugin's routes — which is a far larger act than opening one mesh route.

So this plugin owns its listener and exposes only /mesh/*.

routepurpose
POST /mesh/receiveverify an Ed25519-signed envelope, then deliver it as a prompt
GET /mesh/healthwhether delivery is actually possible, not merely that the process is alive

The source-address allow list

Node can bind an address or all interfaces; it cannot bind a subnet. So the network limit lives in the request path, checked before JSON parsing, before the peer lookup, and before any signature work — an unwanted caller cannot make this process do work.

192.168.0.0/23 is "192.168.0.* and 192.168.1.*": a /23 spans 192.168.0.0 through 192.168.1.255. One rule rather than two, so the halves cannot drift apart. Loopback is always admitted.

Two details are load-bearing:

  • IPv4-mapped addresses are normalized first. Node reports an IPv4 peer on a dual-stack socket as ::ffff:192.168.1.34; without normalization the allow list would silently reject every legitimate LAN caller — a failure that looks exactly like "the peer cannot reach me".
  • Non-loopback IPv6 is refused outright rather than half-matched.

Envelope format

Bracketed header, then a free-form body:

[mesh][v:1][from:<sender>][to:<recipient>][id:<uuid>][session:?][from_session:?][action:do|info][reply:yes|no|end][ref:?]

action and reply are optional on receive (a missing value defaults to info/no) but required on send — omitting them is how a tolerant receiver silently downgrades a request into an acknowledgement. to: '*' is a broadcast, and a broadcast never wakes anyone.

The delivery matrix is the harness's own semantics

Each policy decision maps to one word — the name of an agent method — so the two cannot drift:

situationcalleffect
idle, or busy + new threadagent.followup(msg)next-turn + wake — a whole turn, now or at the boundary
busy + same thread (ref), or action: do from a listed peeragent.steer(msg)next-step + wake — joins the work in progress
off the wake list, or a broadcastagent.inject(msg)next-step, no wake — lands at the next step

The inbox is a durable projection over session events, so a queued message survives a restart. A spool held in plugin memory would not.

Security, replay protection, and durable delivery

  • Authentication is the signature, over the raw request bytes — never over re-serialized JSON, which would reorder keys and break every signature. The signed form is "{X-Mesh-Timestamp}\n{body}", with a fallback to the body alone for senders that omit the timestamp.
  • No CSRF guard, unlike a browser-facing write route: this is a server-to-server webhook. A peer's POST carries no sec-fetch-site and no browser origin, so a same-origin check would reject every legitimate sender.
  • Replay window (300 s default) plus a per-process dedupe set, so a redelivered envelope can never fire a second turn. In-request retries make duplicates expected, not theoretical.
  • Guards: a per-turn injection cap, a wake budget, and a runaway breaker that stops two agents billing each other. The breaker is released by a real user message from the session's own event stream — never by mesh traffic, which must not be able to vouch for itself.
  • Fail informatively, never swallow: an undeliverable message returns unreachable and names the durable route, so a sender never acts on a lie.

Testing

node test/mesh.test.mjs       # envelope, crypto, access, policy, delivery
node test/outbound.test.mjs   # signing, retries, the peer directory, registry canonical JSON
node test/smoke.mjs           # the route table, driven with real Ed25519 signatures
node test/roundtrip.test.mjs  # the tools driving this plugin's own receive route

The round trip is the one that makes the halves one thing: it stands up the real receive handler on a loopback port, a real identity store in a temp directory, and a stub registry that verifies the registration signature rather than accepting it — then drives all five tools through it. Nothing is mocked at the boundary that matters.

No dependencies to install: this plugin uses node: builtins only, and CI runs the suites on Node 20, 22 and 24 with no install step.

To test against a real identity store, point DSH_MESH_LIVE_STORE at a directory of <name>/identity.yaml entries. It is opt-in on purpose: a published plugin's tests must pass on someone else's machine.

Publishing

Publishing uses npm trusted publishing (OIDC) — there is no npm token anywhere, in the repo or in a secret. npm exchanges the workflow's OIDC identity for a short-lived credential, which is also why classic tokens are irrelevant here: npm disabled their creation in November 2025 and revoked the existing ones in December 2025.

One-time setup. A package cannot have a trusted publisher before it exists, so the first publish is manual:

  1. Publish the first version once from a machine logged into npm:

    npm login
    npm publish --access public
    
  2. Configure the trusted publisher. Two prerequisites that are easy to miss and are not validated when you save the form:

    • 2FA must be enabled on the npm account — trusted publishing requires it.
    • The trust must grant the publish permission. A trust that authenticates but was created without it fails with 403 … OIDC permission denied for this action, which reads like an authentication problem and is not one.

    The unambiguous route is the CLI (needs npm ≥ 11.15.0; the registry allows only one configuration per package, so revoke an existing one first):

    npm trust list dsh-fleet-mesh          # what npm actually has, and its permissions
    npm trust revoke --id <id> dsh-fleet-mesh
    npm trust github dsh-fleet-mesh \
      --repo emiltsoi/dsh-fleet-mesh \
      --file publish.yml \
      --allow-publish
    

    Or via the website — https://www.npmjs.com/package/dsh-fleet-mesh/access → Add a trusted publisher:

    fieldvalue
    PublisherGitHub Actions
    Organization or useremiltsoi
    Repositorydsh-fleet-mesh
    Workflow filepublish.yml
    Environment(leave empty — this job declares none)

    publish.yml, not the full path. npm's own CLI documents --file as the "name of workflow file within a repository's .github folder", and a full path is a mismatch that only surfaces at publish time.

Every release after that is automatic: publish a GitHub release, and the workflow runs the suites and then npm publish --provenance.

Two requirements worth knowing: npm CLI ≥ 11.5.1 (the workflow installs the latest), and id-token: write in the job's permissions — already set.

Troubleshooting

A peer says it cannot reach me. Check the bind with a local socket query (Get-NetTCPConnection -LocalPort <port> on Windows, ss -ltnp elsewhere). A shell HTTP probe can be intercepted by an egress proxy and will report a 403 that has nothing to do with your listener.

Everything returns 401. The peer's public key probably did not parse. Public keys appear both as | block scalars and as quoted scalars spread over several lines; a parser that reads only the first line returns -----BEGIN PUBLIC KEY----- and fails every peer while the code still looks correct. This suite asserts against real files for exactly that reason.

The port is open but nothing arrives. On Windows, look for a program-scoped firewall rule covering the process that owns the listener — a port-scoped query misses it, and the owning process is often not the one you expect.

A peer is never woken. The wake list ships empty, and a broadcast never wakes by design. Check both before suspecting the transport.

A wake-listed peer stopped being woken. That is the runaway breaker. It clears on a real user message in the session — by design, mesh traffic cannot clear it.

403 … OIDC permission denied for this action when publishing. This one is worth reading carefully, because it looks like an authentication failure and is not. The tell is in the log: npm signs a provenance statement and publishes it to the Sigstore transparency log before the PUT is rejected — and provenance is signed locally from the GitHub token, so it proves only that id-token: write works. It says nothing about npm's config.

So the trust exists and authenticated, and the publish action was denied. Check, in order:

  1. The trust grants the publish permission, not only staged publish.
  2. The workflow filename matches — the file's name (publish.yml), not a path.
  3. The repository and org/user match exactly, and the environment is empty if the job declares none.
  4. 2FA is enabled on the npm account — required for trusted publishing.

npm trust list <package> shows what npm actually has. A 404 or ENEEDAUTH instead means npm never got an OIDC token at all — a different problem: look at the job's id-token: write permission, and make sure NODE_AUTH_TOKEN is not set to an empty string, which makes npm take the token path and never fall through to trusted publishing.

License

MIT