DSH Plugin Manager
August 28, 2026 · View on GitHub
English | 简体中文
A local companion GUI for DeepSeek Harness plugin development — install, update, build, inspect, and run plugin profiles without memorizing CLI verbs.
Electron + React + TypeScript. Runs as a desktop app or in your browser via a built-in web mode.
Features
- Profile management — list
$DSH_HOME/profiles, switch DSH_HOME (isolated test homes supported), one-click launch on any free port with multi-instance tabs. - Plugin center — one merged table of installed dependencies × locally scanned packages: real installed version (not just the declared range), local build status, remote registry latest (cached 5 min, red highlight when behind), per-row update / uninstall / build / install / publish actions on a serial operation queue.
- Source scan — scan any roots for plugin workspaces (two levels deep,
dshmanifest orcordis.patch.ymldetection), with four built-in manifest-discipline checks (missingdsh.bundledeclaration, missing patch file, missing client bundle, unbuildablegithub:installs). - Build & publish — one-click build (
install+run build, pnpm/npm auto-selected per lockfile) and publish to a private Gitea registry or public npmjs with scope-hijack-safe inline registry overrides. - Doctor — multi-category profile health audit: manifest/BOM, entry points, patch validity, build/pack/install smoke, shadow copies & attribution, peer ranges (OR-range support) with preflight, native bundles, large files, duplicate entries, bundles reconcile, supply-chain security, session tool-call pairing.
- Run profiles — launch multiple DSH web profiles concurrently, each on its own port/tab; live log streaming with fatal-signature capture (loader tree failures surfaced as startup failures, not connection refused).
- Multi-node ops — remote machines running the GUI web host appear in one desktop app (health checks, remote start/stop, embedded per-node tabs); or skip the aggregator and open any node directly in a browser at
http://host:port/?token=…— identical GUI, identical gates. - A2A messaging — send messages to A2A network nodes (hosts running dsh-open-a2a-net), attach launch logs, one-click send plugin health reports from any table row.
- Serial op queue — every mutating action (install/update/remove/build/publish) flows through one queue: buttons queue instead of freezing the UI, same-label dedupe, cross-label ordering preserved.
Usage
Desktop (Electron)
npm install
npm run dev # build + open window
Browser (web mode)
npm run build
npm run web -- --port 3090
# stdout prints a one-time URL:
# open in browser: http://127.0.0.1:3090/?token=<hex>
Web mode binds 127.0.0.1 only, requires a per-launch Bearer token, and serves the same handler registry as the Electron main process (single source of truth). Dangerous channels (port kill, publish, force-start, close-running) stay gated behind confirmation UIs.
Tests
npm test # unit + IPC/web-channel suites (node:test)
Headless smoke
Runtime mount smoke (both run forms) — catches black-window class regressions that type-checks and unit tests cannot see:
npm run smoke:runtime
# Form A: web host boots, health/token/bundle references verified
# Form B: the real Electron binary mounts the app (CDP asserts the
# React root, body content, and key cards); a mount crash
# fails with "black window regression"
npm run smoke # install → check → uninstall round-trip
npm run smoke -- web_test file:/path/to/your-plugin
Requirements
- Node.js ≥ 22
- A DeepSeek Harness checkout (all
dshCLI calls run with the harness checkout as cwd) - pnpm ≥ 10 (profiles) — the GUI pins per-profile store dirs automatically
Effective boundaries
- Host-side plugin code is parsed at DSH startup: restart the profile after install/uninstall for changes to take effect.
file:/link:installs are snapshot copies; re-install to refresh after source changes.
Known limitations
- Windows-specific port-kill semantics use process-tree termination; Linux/macOS support is being hardened.
- Private-registry plugins (
@your-scope/*) resolve against the registry URL you configure in the GUI (persisted per user data dir); the code ships neutral placeholders only.