DSH Plugin Bootstrap
Restore a known-good DeepSeek Harness (DSH) plugin set on a new machine.
The source of truth is plugins.json: every plugin is pinned to an exact version, with notes and optional post-install config. The scripts reproduce the setup without asking the user to remember package names.
User story
I'm on a new machine. I want DSH to install all the plugins I use on my other machine, with the same versions and the same key behaviours.
Getting this skill onto the new machine
The canonical public copy lives at:
https://github.com/GGGengXXX/make-dsh-better
On the new machine:
git clone https://github.com/GGGengXXX/make-dsh-better.git
mkdir -p ~/.agents/skills
cp -R make-dsh-better/skills/dsh-plugin-bootstrap ~/.agents/skills/
If you already have the repository cloned, just copy the skill directory. Then start a new DSH session. DSH discovers skills under ~/.agents/skills/<name>/SKILL.md; the skill appears as dsh-plugin-bootstrap. If the skill is already in that directory, skip the copy.
The workspace copy is the source of truth for editing; re-copy after changing it.
What this skill does
- Reads
plugins.json(the version-pinned plugin list). - Detects the right DSH CLI. The
desktopprofile is reserved by the Desktop app, so the skill prefers the app's bundled CLI wrapper over a genericdshonPATH. - Checks the DSH version against the manifest and warns/blocks on mismatch.
- Shows an install/update/skip plan, asks for confirmation, then installs each plugin with
dsh plugin --profile <profile> add <name>@<version>. - Optionally applies the profile-level
dsh-browser-cdpconfig (Chrome path +--headless) tocordis.patch.yml. - Verifies that each plugin is both a dependency and a selected bundle.
- Optionally applies the two version-pinned local patches:
[email protected]:optimizeComposerKeysdefault true.[email protected]: Enter=newline, Cmd/Ctrl+Enter=send.
It does not copy secrets, API keys, sessions, workspace files, or the entire ~/.dsh directory.
Workflow when the user invokes this skill
Work from the skill directory (the directory containing this SKILL.md).
1. Inspect before touching anything
node scripts/install.mjs --profile desktop --dry-run
Show the plan to the user. If the plan installs or updates anything, ask for explicit confirmation before running it without --dry-run.
If the user's target is not the Desktop app, pass the actual profile (for example --profile web or --profile tui). For a non-Desktop profile a normal dsh on PATH is enough; the script handles that.
2. Install
node scripts/install.mjs --profile desktop --yes
Useful flags:
| Flag | Meaning |
|---|---|
--dry-run | Print the plan; change nothing |
--yes / -y | Non-interactive confirmation |
--json | Machine-readable summary on stdout (logs go to stderr) |
--no-config | Do not touch cordis.patch.yml |
--skip <pkg> | Skip one plugin (repeatable) |
--strict | Require an exact DSH version match |
--allow-dsh-mismatch | Continue even when major.minor differs |
--dsh-cli <path> | Explicit CLI path |
--manifest <path> | Use another manifest |
The script is idempotent: plugins already installed at the pinned version and selected as bundles are skipped.
3. Apply the optional local patches
Only if the user wants the exact key behaviour from the source machine:
node scripts/apply-patches.mjs --profile desktop --dry-run
node scripts/apply-patches.mjs --profile desktop --yes
This modifies installed third-party files under node_modules/. It refuses on version mismatch unless --force is given, and keeps a .bak-<timestamp> copy. Tell the user this is a local patch that a future plugin update may overwrite; after an update, re-run the patch script or set the behaviour in the plugin's settings.
--only keyboard and --only markdown limit the patch scope.
4. Restart / refresh
After installing plugins, tell the user to restart DeepSeek Harness (or hard-refresh the Web UI with Cmd+Shift+R on macOS). Client bundles are cached per page load; a normal refresh may not be enough.
5. Verify
The installer prints a verification table. If a plugin shows FAIL, check:
- the profile's
package.jsondependencies anddsh.profile.bundles; - whether the package's version is compatible with the running DSH version;
- the plugin manager logs under
~/.dsh/profiles/<profile>/.plugin-manager/logs/.
Updating the manifest (capture on the source machine)
When the user installs/removes plugins on their main machine, refresh the manifest:
node scripts/capture.mjs --profile desktop --dry-run # preview
node scripts/capture.mjs --profile desktop # write plugins.json
This reads the profile's selected bundles, records the installed version of each, and preserves existing note fields. Commit/push the skill directory (or copy it to the new machine) afterward.
Desktop profile rule
The generic DSH CLI deliberately rejects --profile desktop:
error: profile "desktop" is managed exclusively by the Electron application
Use the Desktop app's CLI wrapper instead:
/Applications/DeepSeek Harness.app/Contents/Resources/runtime/cli/bin/dsh
install.mjs finds it automatically on macOS. On other platforms, or if the app is elsewhere, set DSH_CLI or pass --dsh-cli.
Manifest format
plugins.json:
{
"schemaVersion": 1,
"targetProfile": "desktop",
"dshVersion": "0.2.1-rc.2",
"plugins": [
{ "name": "@scope/plugin", "version": "1.2.3", "note": "why it is here" }
],
"config": {
"dsh-browser-cdp": {
"chromePath": "auto",
"runtimeArgs": "--headless"
}
},
"localPatches": [
{ "package": "dsh-keyboard-shortcut", "version": "0.2.0", "description": "..." }
]
}
dshVersionis the version the manifest was captured on. Same major.minor is allowed with a warning; different major.minor needs--allow-dsh-mismatch.targetProfileis only a default;--profileoverrides it.config.dsh-browser-cdp.chromePath: "auto"makes the installer probe common Chrome/Chromium/Edge/Brave locations. Set an explicit path if the probe misses.localPatchesis documentation for humans; the installer does not apply it automatically. Runapply-patches.mjsexplicitly.
Included plugin set (captured 2026-10-24)
| Plugin | Version | Role |
|---|---|---|
@flyer103/dsh-side-chat | 0.6.0 | Native right-sidebar side conversation |
dsh-browser-cdp | 1.6.0 | Agent browser over Chrome/CDP; headless watch panel |
dsh-keyboard-shortcut | 0.2.0 | Enter=newline, Cmd/Ctrl+Enter=send |
dsh-markdown-bubble | 0.1.5 | Markdown-rendered user messages |
dsh-markdown-input | 0.2.0-alpha.20 | Live Markdown composer (alpha) |
dsh-better-sidebar | 0.28.0 | File tree + editable CodeMirror + Git/tasks/terminal (heavy) |
Notes:
dsh-markdown-inputis alpha; if its composer takeover misbehaves, disable it in Settings → Plugins.dsh-better-sidebaris heavy and includes its own side chat; it can coexist with@flyer103/dsh-side-chat, but the user will see two side-chat entry points. Decide which one to keep.- Built-in Files and Document Preview are part of DSH itself; they are not in this manifest and need no install.
Safety
- Third-party DSH plugins run in-process and can execute with the user's permissions. Install only from the manifest the user trusts.
- Exact versions are pinned. Do not silently replace them with
latest. - The local patches modify
node_modules; they are optional, version-pinned, backed up, and reversible (restore the.bakfile or reinstall the plugin). - Do not copy
~/.dsh/.credentials.yaml, session logs, or workspace files as part of "installing plugins".
Troubleshooting
| Symptom | Fix |
|---|---|
profile "desktop" is managed exclusively… | Use the Desktop app CLI wrapper or DSH_CLI; see above |
Could not find a dsh CLI | Install DSH Desktop, or pass --dsh-cli /path/to/dsh |
profile "desktop" is not initialized | Open DSH Desktop once so ~/.dsh/profiles/desktop is created |
ECONNRESET / fetch failed | Retry; the installer retries once automatically; check network/proxy/registry |
| Plugin installs but UI unchanged | Restart DSH or hard-refresh (Cmd+Shift+R); client bundles are cached |
| Plugin installed but not active | Confirm it is in dsh.profile.bundles; the plugin manager's add normally appends it |
dsh-markdown-input composer missing | Check Settings → Plugins; alpha plugin; hard-refresh; check console for slot/composer errors |
dsh-better-sidebar/side-chat conflict | Both can boot; choose one side-chat entry or remove one plugin |
Patch says already-patched | Expected; the file already has the target behaviour |
Patch says skipped — version … | Manifest/plugin version changed; review the new version before using --force |
Files
| File | Purpose |
|---|---|
SKILL.md | This workflow |
plugins.json | Version-pinned plugin manifest |
scripts/install.mjs | Dry-run/install/verify |
scripts/capture.mjs | Refresh manifest from a live profile |
scripts/apply-patches.mjs | Optional local key-behaviour patches |
patches/README.md | Patch rationale and manual fallback |