dsh-skill-manager
A skill manager for the DeepSeek Harness (dsh) Web GUI: browse every installed skill right inside Settings — a top-level Skills entry in the sidebar that you can move into the Plugins section with one click.
Features
- Settings → Skills (top-level, default): a read-only catalog of every
skill the session can load, scanned from your user skill roots ($DSH_HOME/skills, ~/.agents/skills).
- Each card shows the skill name, an invocation badge (Model + user /
User-only / Model-only), and its description; expand it to see the source root and file path.
- Search filters by name and description.
- Move the entry with one button: "Move to the Plugins tab" removes the
Skills entry from the sidebar and re-creates it as a tab inside Settings → Plugins; "Move back to the sidebar" reverses it. The choice is persisted in localStorage — exactly one entry exists at any time.
- Read-only: this plugin never writes or modifies skill files.
Installation
Pick one of the two ways below — never both.
Option A — one command (recommended)
dsh plugin --profile web add dsh-skill-managerThis adds the package to the profile's dsh.profile.bundles; its bundle patch (cordis.patch.yml) mounts the plugin automatically on boot. Do not also add a manual insert row for it.
Or from a local checkout:
dsh plugin --profile web add /absolute/path/to/dsh-skill-managerOption B — manual patch only
Use this only when the package is already resolvable from the profile's node_modules (e.g. it was installed as a dependency some other way) and is not in dsh.profile.bundles. Add one insert row to ~/.dsh/profiles/web/cordis.patch.yml (the config watcher hot-reloads it, no restart required):
- insert:
- id: ui-skill-manager
name: dsh-skill-manager> ⚠️ Never combine the two options. Keeping the same plugin both in > dsh.profile.bundles and in a manual insert row mounts the same loader > entry id twice — boot fails with > duplicate loader entry id: ui-skill-manager.
Troubleshooting
duplicate loader entry id: <id> on startup
Boot fails when the same plugin is mounted from two sources — typically a package that appears both in dsh.profile.bundles (from dsh plugin add) and as a manual insert row in cordis.patch.yml. The reported id may be any duplicated plugin, not necessarily the one you just installed.
Fix: remove one of the two sources — delete the manual insert row from ~/.dsh/profiles/web/cordis.patch.yml, or remove the package from bundles (dsh plugin --profile web remove <pkg>).
The DSH loader treats a duplicate id as fatal. A local patch makes it idempotent (keep the first occurrence, warn, ignore the duplicate) so this can never lock you out of the harness again; see the upstream issue and re-run this patch script after every DSH upgrade:
# 升级 DSH 后重跑(自动定位最新 loader,已打过会跳过)
powershell -ExecutionPolicy Bypass -File patch-dsh-dedupe.ps1Structure
lib/index.js— host half: scans skill roots, parsesSKILL.md
frontmatter, serves the catalog at GET /api/skill-manager/list (same-origin fenced).
lib/client.js— browser half: registers thesettings.sectionentry
(sidebar, order 12) and the settings.plugins.tab entry, and moves between them at runtime through ctx.slots.register disposers.
cordis.patch.yml— the bundle patch that inserts theui-skill-manager
row.
License
MIT