dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Dennis Rongo's plugin collection for DeepSeek Harness (dsh)
Dennis Rongo's plugin collection for DeepSeek Harness (dsh) — an MIT agent harness where every capability is a plugin.
Everything here is built on the harness's public seams: cordis service keys, the Typert host/client bridge, shell.* slots, the system-prompt section registry, and ctx.cmdlineArgs. No forks, no patched launcher, no vendored harness code.
Both surfaces are supported. Every plugin runs unchanged under the dsh CLI and under DSH Desktop — a community desktop wrapper that ships the harness pre-packaged with multi-provider model support ("Any model, zero setup"), for Windows and macOS. It is an independent project, not affiliated with DeepSeek.
The desktop keeps its own DSH_HOME (%APPDATA%\dsh-desktop\harness on Windows) with its own profiles, so you install a plugin once per profile on whichever surface you use. Nothing here is CLI-specific: the same package, the same cordis.patch.yml row, and the same /api endpoints serve both.
Status: works with DSH Desktop
0.10.0(dsh0.1.7-rc.2) and thedshCLI at0.1.5-rc.3— both surfaces verified live, all six host services answering. Desktop0.10.0needs the codec-fix releases of the host plugins (see the table below); older Desktop/CLI versions keep working, since the fix is backward-compatible. dsh is a fast-moving0.1.xdev preview that promises breaking changes — re-verify against your installed version, and read Harness compatibility for what has broken so far and what is still open.Platforms: the plugins are plain Node and platform-agnostic, and DSH Desktop ships for Windows and macOS, so they should run on either. The tooling is portable —
verify.mjs,anchor.mjs,link-superpowers-skills.mjsare plain Node, and profile live-linking has a script per platform (dev-link.ps1on Windows,dev-link.shon macOS/Linux) behind onedev-link.mjsentry point. Everything here has been exercised on Windows against both the CLI and DSH Desktop; macOS and Linux are untested.
| Verified against | |
|---|---|
| DSH Desktop | 0.10.0 |
| dsh (harness) | 0.1.7-rc.2 — the copy DSH Desktop 0.10.0 bundles |
| dsh (CLI, global) | 0.1.5-rc.3 — what npm i -g @deepseek-ai/dsh resolves to, and what anchor.mjs links against |
Desktop 0.10.0 requires the codec-fix releases of the six host plugins:
@dennisrongo/dsh-git ≥ 0.5.1, dsh-hooks ≥ 0.2.1, dsh-memory ≥ 0.1.3,
dsh-mission-control ≥ 0.5.2, dsh-plan-board ≥ 0.3.2, dsh-todo ≥ 0.5.3.
Older releases of those six fail to boot on Desktop 0.10.0 (see the
2026-10-03 entry); older Desktop and CLI versions are unaffected either way,
because the fixed codecs carry both era's members.
Older harnesses are not pinned or tested. Because dsh is a 0.1.x preview, a
plugin here is expected to break on upgrade rather than warned about in advance;
what follows is the running record, newest first.
2026-10-03 — DSH Desktop 0.10.0 (dsh 0.1.7-rc.2). Two changes, one of them ours:
Every host service refused to register, and the harness refused to boot.
dsh-typert-loader 0.1.7 changed the strict-codec contract: a codec is no
longer a schema (a zod v4 instance the loader validates and the gateway
parses through) but a create() factory returning the schema, which
requireStrictCodec demands as a function and the gateway calls as
codec.create().parse(value) (dsh-api-gateway, decode()). All six host
manifests here predate that, so validateTypertManifest threw for the first
invocation of each, auditStartupEntries failed the entry, and the host
exited before serving anything:
typert-loader: @dennisrongo/dsh-todo invocation
"@dennisrongo/dsh-todo#dshTodo/list" parameter codec has no create() factory
… 6 typert contributor(s) failed to register
[desktop] Harness entry failed during startup; stopping immediately
The fix carries both members — schema for dsh ≤0.1.5 (whose loader
requires a zod instance and whose gateway parses codec.schema.parse(...))
and create: () => schema for 0.1.7+ — in the one descriptor() builder
each plugin's src/remote.ts shares between its host and client faces.
Neither era's validator rejects the other's member, so one build serves both
surfaces and stays backward-compatible; the CLI at 0.1.5-rc.3 was still
booting on schema the whole time. Fixed in dsh-git 0.5.1,
dsh-hooks 0.2.1, dsh-memory 0.1.3, dsh-mission-control 0.5.2,
dsh-plan-board 0.3.2, dsh-todo 0.5.3 — until those are published,
market installs of the older releases still fail to boot on Desktop 0.10.0.
Verified by importing every built manifest through the Desktop bundle's own
validateTypertManifest, then scratch-booting the bundled harness against a
throwaway DSH_HOME with the profile plugins junctioned at this repo: all
six services answer ok:true on 0.1.7-rc.2.
Plugin deployment moved to enforced "generations" — dev links no longer
reach the Desktop. 0.10.0 migrates profile plugins into
profiles/.generations/live/<pkg>+<version>+<hash>/node_modules/<pkg>
snapshots, with the profile's node_modules/@dennisrongo/<pkg> symlinked
there and dsh.desktop.generationProjection in the profile manifest naming
the generation each plugin must use. At every app start a repair ENFORCES
that projection, and it owns every layer you might try to repoint — each of
these was tried and reverted within one app start:
dev-link.ps1 junctions at the profile entry → the repair restores the
generation symlink (the junction never survives a restart).dsh plugin add link:<repo> (with the profile's own pnpm 10 via
corepack pnpm@10.34.5) rewrites the dependency and symlink correctly —
but the CLI does not know generationProjection, so the app reprojets
the manifest back to version pins and restores the old generations.What the repair DOES respect is a generation whose own pnpm lockfile
records the install — the existing generations are file: installs of a
staged source copy (their node_modules/.pnpm/lock.yaml says so), which
pnpm materialises as a copied directory. scripts/desktop-generations.mjs
mints generations that way from this repo's builds — a file: install
pointing straight at the package, with generation.json carrying the local
source path — then wires the ids into the projection, desired.json, the
manifest deps/overrides and the node_modules entries, so every layer the
repair checks agrees and there is nothing to revert. Verified end to end:
the app boots and all six host services answer ok:true. A minted
generation is a COPY, so it does not self-deploy — re-run the script (then
restart the Desktop) after host-half rebuilds. The dsh CLI surface keeps
the old dev-link workflow unchanged.
For other people's machines none of this applies: they install from the
market, which only sees published versions — during this break the
profile held dsh-plan-board 0.3.0 while 0.3.1 was already published, so
even published fixes wait for the user's update click.
Also observed: with the CLI at 0.1.5-rc.3 and the Desktop at 0.1.7-rc.2, the
anchors point at a dsh two prereleases older than the one that runs them
(dev-link.ps1 reports 244 desktop-bundle vs 2 npm-host shared deps). The
scratch boot above ran exactly that skew and every service mounted — these
plugins are manifest-driven, so the per-copy WeakMap identity concern in
dev-link.ps1's header still does not bite. Keep an eye on it anyway: that
note predates any real divergence.
And two tooling fixes rode along: verify.mjs --port now authenticates
(--token=<t> from the launch URL, exchanged for the session cookie — a
plain fetch loses the 302's Set-Cookie, so the mint reads the redirect
response directly), and its /plugins/<pkg>/client.js fetch is gone —
dsh-client-modules serves that route only under a revision (?rev=…),
so a bare fetch 404s by design and the old check was reporting a defect
that never existed.
2026-09-16 — DSH Desktop 0.9.0 (dsh 0.1.5-rc.2). Three separate breaks, two of them ours:
The harness would not boot at all. Not a plugin in this repo: DSH
Desktop's own bundled dshmarket imports installSettingsSection and
settingsNamespace from @deepseek-ai/dsh-settings, and dsh deleted both
(dshmarket's own source dates this to 0.1.2-alpha.1). A missing ESM named
export is a SyntaxError at module evaluation, so the loader failed the entry
and the host exited 1:
dsh: plugin tree failed to load: … The requested module
'@deepseek-ai/dsh-settings' does not provide an export named
'installSettingsSection'
dshmarket 1.45.1 inlines the helper and fixes it. The catch is that the
profile only receives that version once plugin migration completes — and
migration was being aborted by the next two items, which left the profile
pinned to dshmarket 1.36.0. Anything that blocks migration therefore
presents as this crash, whatever the real cause. Read the
migration failed, restoring the pre-upgrade profile: <reason> line in
%APPDATA%\dsh-desktop\logs\harness.log; the reason is the actual bug.
dsh-skills aborted plugin migration. 0.9.0 validates every generation's
required dependencies with a bare require.resolve. @dennisrongo/skills is
a bin-only CLI package — no main, no exports, no index.js — so it does
not resolve that way and migration failed closed:
@dennisrongo/dsh-skills failed peer validation: @dennisrongo/skills does not
resolve from the generation or installation closure
Fixed in dsh-skills 0.1.1 by declaring the catalog an
optionalDependency, which matches how the plugin already treats it — it
resolves the manifest subpath and falls back to skillsRoot, then
DSH_SKILLS_ROOT, then a clone probe. pnpm still installs it, so the catalog
ships unchanged.
dsh-plan-board's panel slid underneath dsh-mission-control's rail.
The shell slot for the conversation column was renamed conversation →
main.conversation. The lookup missed, useDock fell through to its
no-column branch, and that branch pinned right: 0 to the viewport — putting
the whole panel under the 400px rail instead of beside it. Nothing logged;
it only showed up as clipped text. Fixed in dsh-plan-board 0.3.1: the
slot name is now a candidate list (newest first), and the fallback honours a
frame reservation too, so the next rename degrades to a slightly-wrong width
instead of a buried panel.
2026-09-04 — @deepseek-ai/dsh-client-runtime removed from the dsh install.
Seven plugins (dsh-git, dsh-memory, dsh-mission-control, dsh-plan-board,
dsh-theme, dsh-todo, dsh-weather) import ClientContext from it as a
type-only import. anchor.mjs now reports MISS … is not in the dsh install for each, and tsc fails with TS2307, plus TS7006 fallout where
parameters lose their inferred types. CI has been red since this date and
the last green run was 2026-09-02.
Status: open, and deliberately so. The import is types-only — it is erased at
build time, every runtime suite passes, and all eleven packages build and ship
correctly. Fixing it means either vendoring the type or dropping to unknown
across seven plugins, which is worth doing deliberately rather than under a
release. Two knock-on effects are worth knowing:
pnpm run typecheck fails locally for the same reason. Compare against a
stash before blaming your own change.node_modules/@deepseek-ai/. On Windows that broke DSH
Desktop 0.9.0's migration preflight (ENOENT … stat … dsh-client-runtime),
which is how it contributed to the boot failure above. Delete them; the
current anchor.mjs skips a missing package rather than re-creating the link,
so they do not come back.| Package | npm | Adds | Halves | Endpoints |
|---|---|---|---|---|
dsh-todo | npm | per-workspace sprint/roadmap task list, plus a dsh-todo CLI | host + client + CLI | dshTodo/list, replace, scanDigest, readSuggestions |
dsh-git | npm | source-control tab — changes, history, branches, stash, worktrees | host + client | dshGit/status, diff, commitFiles, commitDiff, stage, commit, init, sync, suggestMessage, changeToken, refs, branch, merge, stash, worktree, suggestBranch, stashFiles, stashDiff |
dsh-weather | npm | weather bar in the shell overlay | client only | — |
dsh-headless-plus | npm | --model / --resume / --continue for the headless app | CLI app | — |
dsh-superpowers | npm | Superpowers methodology as a system-prompt section and a skill provider (bundled, no clone needed), plus a nudge to ask via ask_user_question instead of prose | host | — |
dsh-skills | npm | the @dennisrongo/skills library as an installable skill catalog | host | — |
dsh-mission-control | npm | fleet dashboard overlay — sessions, swarm tree, token burn, permission inbox, pomodoro timer | host + client | dshMissionControl/load, save |
dsh-theme | npm | twelve themes, eight accents, contrast and scale sliders, and three fonts with two bundled, live preview | client + tiny host | — |
dsh-hooks | npm | Claude Code-compatible hook lifecycle — shell commands at eight lifecycle points, plus contextual skill hints beside the composer | host + client | dshHooks/describe, recent, hints, hintsToken, dismissHint |
dsh-plan-board | npm | durable plans — captures every exit_plan_mode plan to disk, opens a review panel you can approve or revise from, keeps the history | host + client | dshPlans/list, get, changeToken, discard, pin |
dsh-memory | npm | /remember into the AGENTS.md hierarchy, plus a tab showing which instruction files the loader kept | host + client | dshMemory/inspect, remember, read |
dsh-todoA task tab scoped to the workspace you're working in, so each project keeps its own backlog instead of one global pile. It is a sprint/roadmap list, not a checklist: each task carries a status, a priority, and optional release and sprint labels.
What you get. A tab beside Chat and Trajectory. Tasks move through real workflow states — backlog · todo · in-progress · blocked · done — changed from a pill on the row, because a boolean can't express the two things a standup actually asks: what is moving, and what is stuck. Priority is P0–P3 as a chip, with only P0/P1 coloured so the list flags what's urgent instead of turning into a rainbow. Release (1.5 or 0.5.1, what ships together) and sprint (24, when it's worked) are deliberately separate numeric axes — a release takes up to three numbers so a patch gets its own label, a sprint is a single decimal, neither admits alpha, and they sort by version semantics (1.10 above 1.9) with no releases table to administer. Group by None · Status · Release · Sprint · Priority gives collapsible sections with their own progress bars; grouping by status is a kanban board without drag-and-drop. Clicking a title opens a task detail modal (description, status, priority, labels, due date) where Done is the save — the only control that refuses to proceed on an invalid label, while Esc, the backdrop and the X always let you out and discard it; the chevron still gives a cheap in-row peek, and double-click renames inline. Due dates are stored as calendar days, so "due the 14th" reads as the 14th in every timezone; overdue is flagged red, due-today amber. Completed work is archived, not deleted — an item carries an optional archivedAt stamp whose presence is the archived state, so there's one source of truth and no way to store an archived item without a date. Every irreversible action goes through a confirmation dialog that quotes the task by name.
Suggest. A button in the tab header scans the workspace and proposes concrete next tasks — unresolved TODO/FIXME/HACK comments, features the docs promise but the code does not implement, and modules with no tests — each with a rationale, a priority and a file:line pointer where there is one. Tick the ones worth doing and Add selected files them into the backlog; until then they are proposals, stored nowhere. Refresh returns genuinely new ideas because every title already shown joins the exclusion set alongside the existing backlog. The scan runs as a background session that writes a result file the modal polls, on a bounded digest rather than the repository — so it spends tokens, and it is never automatic.
CLI. The package ships a dsh-todo binary so an AI agent can shell out and manage the same list you see in the tab — no profile, no session, no running server:
npx dsh-todo list --open --json
npx dsh-todo add "Fix token refresh" --priority p0 --release 1.5 --due 2026-03-14
npx dsh-todo update t1a2 --status in-progress --sprint 24
npx dsh-todo done t1a2 && npx dsh-todo archive
It targets a workspace directory (--workspace, default cwd) and talks to the same SQLite file the host uses, which is safe by construction: SQLite's file lock refuses a writer that lands inside another process's transaction, and the CLI sets a busy_timeout so it waits for the harness to commit rather than failing. Verified live — the CLI wrote while a running server held its handle and the API returned the new task with no restart. Ids accept any unambiguous prefix, an empty value clears a field (--release ""), and invalid values are refused rather than dropped — nothing is written. Every --json payload leads with ok, so an agent never infers the verdict from the shape: success carries the stored task back for confirmation, and a refusal carries field, expected and got alongside the message. Exit codes are distinct: 0 ok, 2 usage, 3 not found.
How it works. TodoService extends TypertRemoteService registers under the cordis key dshTodo and owns one SQLite database per project at <workspace>/.dsh/todo.db, resolved through workspaceRegistry. Writes use optimistic concurrency: every replace states the revision it observed, and the host rejects a stale write with ok:false, code:'revision-conflict' and the current list, rather than silently clobbering. A legacy central ~/.dsh/storages/dsh_todo.json is migrated on first read.
Endpoints. POST /api/dshTodo/list → { list: { items, revision, updatedAt } }; POST /api/dshTodo/replace → the new list or a revision conflict; POST /api/dshTodo/scanDigest → the bounded workspace digest a scan reasons over; POST /api/dshTodo/readSuggestions → pending until the scan's result file lands, then ready with the parsed suggestions or error, consuming the file either way. All four take a single parameter named request.
The task shape is { id, title, description?, status, priority, release?, sprint?, dueDate?, createdAt, completedAt?, archivedAt? }. status is the source of truth — there is no separate done flag to fall out of sync — and only the status transition writes completedAt. Absent optional fields are absent keys, never ''. Existing v1 databases are migrated in place on first open: CREATE TABLE IF NOT EXISTS doesn't add columns to a table that already exists, so each new column is added with ALTER TABLE after consulting PRAGMA table_info, then title is backfilled from the old text and done = 1 becomes status = 'done'. The v1 columns are still written on every insert, so a downgrade still reads a sane list. src/db.ts is shared by the host and the CLI on purpose — a second copy of the migration is the one duplication that could genuinely corrupt a database.
Requires. workspaceRegistry from dsh-base, which @deepseek-ai/dsh-web-app composes by default. The CLI requires none of it.
dsh-gitnpm: @dennisrongo/dsh-git
Source control for the workspace, without leaving the harness. Read what changed, stage it, let the model write the commit message, and push — in the tab you are already looking at, against the same repository your agent is editing.
What you get. A Changes tab showing branch, upstream ahead/behind, and a file list split into staged and unstaged, with per-row stage/unstage/discard and a diff pane. An ✦AI message button drafts a commit message from the staged diff through the harness's own llm service, then Commit all commits. Recent history is listed underneath. A directory that isn't a repository reports repo: false and offers Initialize repository rather than erroring.
Branches, merge, stash and worktrees. The branch name in the header is a menu: switch branches, create one, merge another into it, or delete one. A third Repo tab lists your stashes (push / pop / apply / drop) and your worktrees (add / remove / prune). Every worktree row has an Open button that registers the directory as a workspace and switches to it — a worktree you can see but cannot get into is just a list.
Worktrees go beside the project, named <project>-<branch>. Type a branch and the path fills itself in: feature/login in myproj suggests ../myproj-feature-login, which puts the worktree next to the project on disk and next to it in dsh's workspace list. Slashes are flattened, because ../myproj-feature/login would quietly create a myproj-feature directory with the worktree buried inside it. The suggestion is editable and stops auto-filling as soon as you type your own path.
The model names the branch, not the path. Type a rough description in the branch box — "fix login retry" — hit ✦, and it becomes fix/login-retry, with the path following as ../myproj-fix-login-retry. Naming is a judgement call worth a model; deriving a path from a branch is arithmetic with one right answer, so a regex does that. It fails soft in exactly the way you'd want: no provider configured, or any error, leaves your text untouched with the reason in the log strip — typing the name yourself is always the shortest path.
A worktree can fork from a branch other than the one you're on. The form carries a from select over the local br