← Back to home@Winnie-0721

dsh-plugin-market

DeepSeek Harness plugin market: browse, search and install community plugins from the sidebar foot entry (host + web client halves, DSH plugin spec).

Stars
2
Language
JavaScript
Created
Oct 3, 2026
Updated
Oct 16, 2026
GitHub repo

Introduction

deepseek-harness-market

English · 简体中文

npm version npm downloads GitHub release GitHub stars License: MIT DeepSeek Harness 0.2.0-rc.2

A plugin market that lives inside DeepSeek Harness.

One entry at the bottom of the sidebar: browse and search the community catalog, install, update, enable / disable, uninstall — all without leaving the GUI.

Plugin market: Discover / Installed / Updates tabs, search, categories and real plugin cards

Install · Gallery · Design doc · API contract · Releases

Why it exists

One-line positioning: this is a DeepSeek Harness plugin market that works like a phone app store — browse, inspect, install, update, enable/disable and uninstall, all inside the sidebar, using the same mental model you already have from installing apps on your phone. Everything below is that positioning made concrete:

  • A big catalog that loads fast. The community-curated awesome-dsh-plugin catalog with 4400+ entries (updated daily); it reads npm mirror first with the official URL as fallback, and fetching, caching, retries and degradation all happen in the host process — the browser only talks to our own endpoints, so the list is always instant.
  • Every update step is visible. The left button is one merged state machine: “Check for updates → Update all (N) / Check again”; each row updates to x.y.z on its own; every result stays on its own row and a run ends with one honest summary (restart-pending counts as success, failure reasons are written verbatim on that row — no sugar-coating).
  • The market updates itself. It checks for a new build once at startup; when one exists the button goes straight to “Update to x.y.z”. All four states are covered: Update the market → Updating… → Update succeeded → Check again; downloads pass three checks (path shape + sha256 + artifact self-verification), and after installing it never pretends it already took effect.
  • “Restart required” is told the truth about. When a change only takes effect after a host restart, the panel says so instead of quietly turning green — and it survives a page refresh, because the ledger lives in the host process (/status.pendingRestart), not in page memory. On CLI/dsh web installs it also offers a one-click “Restart DSH” (a detached waiter that relaunches only after the old process is really dead, and the page only reloads after observing the host die once). The desktop app deliberately has no restart button — three independently sufficient reasons (the shell's IPC whitelist has no “restart yourself” message, exiting is treated as a fatal failure, and that failure dialog contains a disable all third-party plugins button) are written up in API-CONTRACT §2.6; there the panel says “close the window and reopen it” instead. See ROADMAP item 6.
  • A tight boundary. Only installs plugins in the catalog, only through the host pluginManager, write operations only accept same-origin POST (64 KiB), catalog bundles must pass dist.integrity checks, and the market refuses to uninstall itself.
  • It feels like part of the host. Colors only use the host --dsw-* theme tokens (with fallbacks); copy is zh / en and follows the host language; dark / light, narrow viewports and prefers-reduced-motion are all handled honestly (the e2e watches every one of them).

UI at a glance

The entry sits at the bottom of the sidebar, above the account row, with an updates badge:

Plugin market entry at the bottom of the sidebar, with an updates badge

The “Updates” page: merged state machine (Update all (2) / Check again), per-row “Update to x.y.z”, inline results and the summary (the screenshot below is the acceptance environment: the list is a pair of injected fixture updates — one succeeds pending restart, one fails with a file lock):

Updates page: update-all, per-row updates to a specific version, inline success and failure results

Quick Start

dsh plugin --profile web add deepseek-harness-market
  1. After installing, restart dsh web once (or let the desktop app recompose) and refresh — the entry appears at the bottom of the sidebar, above the account row.

  2. On Discover, search or filter by category → click “Install”; the Installed tab manages enable / disable and uninstall.

  3. The Updates tab carries a count badge: the left button runs “Check for updates → Update all (N)” sequentially — one failure never blocks the rest; the right button (“Update the market / Check again”) manages the market's own updates.

  4. One-shot Windows install (with profile backup and rollback):

    pwsh -File scripts\install-into-profile.ps1 -Profile desktop
    
  5. You can also install straight from the GitHub Release assets — every release page lists one copy-paste command.

Compatible with DSH 0.2.0-rc.2; the npm package and the GitHub Release are published together; versioning rules and the release process live in docs/RELEASING.md. No DSH yet? npx @deepseek-ai/dsh web starts a local instance.

Which restart applies to you (the honest version — the panel tells you the same thing):

You are runningAfter the market packages a host-side changeWhat you do
dsh web / CLIthe panel shows a “restart required” banner with a Restart DSH buttonclick it, or restart the command yourself
the desktop appthe panel shows the same banner without a buttonclose the window and reopen it — a page refresh will not load the new host code

How it works

One npm package carries both halves, installed into the host per the official plugin spec:

  • Host half (repo process): a Cordis function plugin that only named-exports name / inject / apply; ctx.webServer registers a single prefix route, and ctx.get('pluginManager') optionally bridges install capabilities. Catalog fetching, caching, retries, verification and self-update downloads all happen here — the browser never touches the network or the filesystem.
  • Client half (browser): lib/client.js, a single-file bundle registered through window.__ModuleLoader__.load({ id, factory }), with zero dependencies beyond require("react").
  • Seats and declarations: the entry registers the official sidebar.footer.action, the panel registers the plugin-market key on main, navigation goes through ctx.layout.selectPanel; package.json declares dsh.bundle.patch (the bundle patch layer) and dsh.client (platform: web plus the ./client export).
  • The contract is frozen: host ↔ client endpoints, responses and error codes are governed by docs/API-CONTRACT.md — update the docs and regression tests before changing the contract; the line-by-line comparison against the official spec is in docs/PLUGIN-MARKET.md.

Data sources

OrderSourceAddressMeasured locally
1npm mirror (preferred)the dsh-plugin-catalog package289 ms
2Official URL (fallback)awesome-dsh-plugin.com/plugins.json25–93 s (times out)

The fallback is necessary: DSH only honors the HTTP(S)_PROXY environment variables and ignores the Windows system proxy, while the official source sits on GitHub Pages. Override the defaults with DSHM_REGISTRY_URL / DSHM_NPM_MIRROR.

This repository re-implements the official plugin spec, taking catalog sources and product decisions from dsh-market as a reference but copying none of it: the feature surface is narrowed down to one loop — installing and managing plugins from the sidebar.

Security boundary

  • Only plugins in the catalog may be installed; catalog entries carrying dist.integrity must pass verification before use.
  • Install / uninstall / enable / disable go only through the host pluginManager — the same path and the same build-script approval rules as dsh plugin add.
  • Write operations only accept same-origin POST (64 KiB cap); no cross-origin requests, no GET that mutates state.
  • The market refuses to uninstall itself.
  • The self-update trust anchor is a manifest hash (three checks: path shape + sha256 + artifact self-verification): new versions take sha256 straight from the GitHub attachment digest, older ones from index.json; it stops corruption, truncation and single-point replacement, but not “manifest and artifact swapped together” — stated honestly in API-CONTRACT §2.9, never masquerading as an independent signature.

Design & security decisions · Known limitations · API contract

Development and acceptance

# Real-browser e2e: boots a scratch host + headless Edge, asserts on the real engine and saves screenshots
pwsh -File verify\ui-check.ps1

# Release gate: node --check + every verify/*.test.mjs (no version bump, no packing, no publishing)
pwsh -File scripts\release.ps1 -LocalOnly

# Official release (local stops here): gate → bump → commit → tag → push
# The pushed tag triggers GitHub Actions: pack → GitHub Release assets → npm,
# where publish-npm.yml is the single npm-publish implementation (see docs/RELEASING.md §4.2.1)
pwsh -File scripts\release.ps1 -Bump patch

The gate auto-discovers verify/*.test.mjs (currently 20 suites — copy keys, state machines, install spec, self-update channel, source classification, the OIDC/release-workflow regression…), and release-workflow.test.mjs adds a reverse assertion: pack-release.yml must not contain npm stage publish — writing the publish steps a second time is exactly the bug that broke releases twice (root cause + what CI actually proved, RELEASING §4.2.1). Real-browser e2e is 90 assertions and stays out of the gate (it needs a browser and a scratch host); the independent acceptance report is verify/REPORT.md.

Repository layout

PathContents
plugin-market/The plugin package itself: host half (lib/index.js / catalog.js / catalog-npm.js / http.js / self-update.js / restart*.js) + web client half (lib/client.js, single-file bundle) + cordis.patch.yml
.github/workflows/pack-release.yml (tag → gate → pack → GitHub Release) and publish-npm.yml (the only npm-publish implementation, reused via workflow_call)
docs/API-CONTRACT.mdThe frozen host ↔ client contract (endpoints, response conventions, catalog fetching strategy)
docs/PLUGIN-MARKET.mdDesign and line-by-line comparison with the official spec, data-source decisions, security decisions, limitations, acceptance results
docs/RELEASING.mdVersion rules, the release chain, the three npm-publish root causes, distribution paths
docs/ROADMAP.mdWhat to build next, what not to build, with measured evidence and cost
docs/TEAM-BRIEF.mdImplementation-period environment facts and API signatures (for collaboration / reproduction)
scripts/Install / rollback and release scripts
verify/Regression tests + real-browser e2e + the independent acceptance report

License

MIT. The catalog data and its source repository are licensed by awesome-dsh-plugin; this repository contains no third-party source code.