Self-update for the harness launcher; checks npm for a newer @deepseek-ai/dsh, stages the tarball, and applies it on harness exit or via update-and-restart from the web panel.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:a1113622001/dsh-auto-update
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
A DeepSeek Harness (cordis) plugin that makes the harness update itself.
It periodically checks npm for a newer version of @deepseek-ai/dsh than the
currently installed one; when an update is found it downloads the tarball and
stages it; when the harness process exits, a detached helper process runs
npm install -g to replace the global installation with the new version; and
optionally it can relaunch dsh with the original startup arguments. By
default the web panel shows a small "Check for updates" pill in the bottom-right
corner (click to expand the full panel), which displays version status and
offers "Check for updates", "Update and restart", and "Cancel staged update".
How it works
- Install discovery — derives the global install root from
process.argv[1](the npm shim launches…/node_modules/@deepseek-ai/dsh/lib/bin.js); can also be set explicitly viaconfig.installRoot. If the harness is running from source (pnpm dsh), auto-update is unavailable and logs a note. - Version check — calls
npm view @deepseek-ai/dsh@<distTag> version --json, reusing your configured registry / mirror / proxy. Includes a minimal built-in semver comparison (handles prereleases such as1.2.3-rc.1). - Staging —
npm packdownloads the exact version's tarball into$DSH_HOME/updates/and writespending-update.json(with from/to, install root, process pid, whether to relaunch, etc.). This step never touches the running installation. - Applying — on the harness's
process.on('exit')it detachesbin/apply-update.js: it waits for the old process to actually exit (on Windows a running process locks native modules such as sharp/koffi/node-pty, so installation must happen after exit) →npm install -g <tarball>→ verifies the installed version → records the result → optionally relaunchesdsh <original args>.
Installation
Install the plugin in your profile directory (same as dsh-session-stats-panel):
# Local path install example (Windows / Linux / macOS)
corepack pnpm --dir "%USERPROFILE%\.dsh\profiles\web" add "C:\path\to\plugins\dsh-auto-update"
# Or Linux / macOS:
# corepack pnpm --dir "$HOME/.dsh/profiles/web" add "/path/to/plugins/dsh-auto-update"
Or, install directly from GitHub using the bundled manifest:
dsh plugin --profile web add github:a1113622001/dsh-auto-update
This plugin is distributed through its GitHub repository only and is not published to the npm registry, so
dsh plugin add dsh-auto-update(without thegithub:prefix) fails with a missing-package error.
When installing manually, you must register the
cordis.patch.ymlbundle at the repo root with the harness so the plugin starts with it.dsh plugin addalready carries that bundle, so no manual patching is needed — the YAML block below is exactly the content ofcordis.patch.yml.
Then append this to %USERPROFILE%\.dsh\profiles\web\cordis.patch.yml:
# dsh-auto-update: lets the harness update itself (check npm → stage → apply on exit)
- insert:
- id: auto-update
name: 'dsh-auto-update'
config:
distTag: latest
checkOnStart: true
checkIntervalMinutes: 240
autoStage: true
applyOnExit: true
relaunch: false
After saving, the running harness hot-reloads the host plugin (cordis.patch.yml
is watched); refresh the page once and the "Check for updates" pill appears in
the bottom-right corner (collapsed by default; click to expand the panel).
Configuration
| Field | Default | Description |
|---|---|---|
distTag |
latest |
npm dist-tag to track (e.g. latest / next) |
registry |
"" |
npm registry override; empty uses your configured registry |
checkOnStart |
true |
check once at startup |
checkIntervalMinutes |
240 |
periodic check interval (minutes); 0 disables periodic checks |
autoStage |
true |
download and stage automatically once an update is found |
applyOnExit |
true |
run the detached apply process when the harness exits |
relaunch |
false |
relaunch dsh with the original args after applying ("Update and restart" in the panel always relaunches) |
installRoot |
"" |
explicitly specify the harness install root (used when auto-discovery fails) |
updateDir |
"" |
updates directory; defaults to $DSH_HOME/updates (C:\Users\<you>\.dsh\updates) |
Behavior details
- Safe defaults: by default it only "stages + applies on exit" — it never
kills the process mid-session. For a fully automatic loop set
relaunchtotrue, or click "Update and restart" in the panel. - Panel buttons:
/auto-updateis a loopback-only HTTP channel mounted on the harness web server; the browser callsstatus/check/stage/cancel/applyRestartviaPOST /auto-update/<endpoint>. It is a plainwebServerprefix route, not aconnection.rpcchannel — on dsh ≥ 0.1.5 the latter throwscannot get property "webServer" without injectfrom inside the connection service and the route silently never mounts. - Manual trigger:
applyRestartforces a check first, stages if needed, then writesrelaunch: trueto the manifest; ~0.8s after responding it exits the process, and the exit hook starts the apply process and relaunches. - Crash tolerance: if the process is force-killed (no
exitevent), the staged manifest is preserved; on next start the plugin recovers it and re-checks, then applies as usual. - Update history:
$DSH_HOME/updates/update-history.jsonlrecords the outcome of each apply;update-result.jsonholds the most recent result.
Verification / manual testing
# 1) Plugin syntax
node --check lib/index.js
node --check lib/updater.js
node --check bin/apply-update.js
# 2) Panel channel mounted (harness running; open the UI once to get the cookie)
curl -s -X POST http://127.0.0.1:3080/auto-update/status -H "content-type: application/json" -d '{"type":"client-request","rpcId":"t1","method":"status","payload":{}}'
# 3) Force a check
curl -s -X POST http://127.0.0.1:3080/auto-update/check -H "content-type: application/json" -d '{"type":"client-request","rpcId":"t2","method":"check","payload":{}}'
Known limitations
- Only supports harnesses installed as a global npm package (the
dshCLI in%APPDATA%\npm). Source runs (pnpm dsh/ a dev checkout) are not updated. - Applying happens after exit: if the process never exits gracefully (e.g. a hard kill or power loss), the update is deferred to the next exit.
- On Windows, native modules (sharp/koffi/node-pty) can still hold file handles
open after the process exits, occasionally causing
EBUSYduringnpm install -g. The helper waits until the recorded process has truly exited, then retries with backoff, so a single lingering handle does not fail the update. npm install -grequires write access to the npm global directory and cache (normal user permissions are enough).- If the plugin source directory is moved away, the
helperpath recorded in a staged manifest becomes stale; re-checking re-stages a fresh manifest.
Links
More in this category
yjh051108/dsh-routing-suite★ 7005
One repository, three parts: a runtime injector for DSH plugin packages (inject, hot-reload, unload, promote a dev staging tool to the front, route self-heal, plus a settings-page plugin manager that lists, unloads and drags folders in to internalize), a task-aware reasoning-mode router agent preset (router-standard / router-spec / router-react), and a graded two-level task protocol whose six tools (commit_star, lock_stage, revise_do, edit_plan, mark_task, redteam_verdict) pin task state to disk. The injector implementation ships in-tree, so the install carries its own behaviour rather than a dependency list.
strukto-ai/mirage#dsh★ 3675
Swaps the filesystem and bash providers for a mirage virtual workspace: file tools and shell commands run over mounted resources (RAM, S3, Redis, Slack, Gmail, Notion, Postgres) instead of the host disk, with per-mount read/write/exec modes, per-command sandbox routing (monty, pyodide, quickjs in process; docker, e2b, daytona remote), and installed CLIs (git, gh, slack, linear, ntn, gws, or one you register) as head words in the virtual terminal.
hust-open-atom-club/oh-dsh★ 322
Community distribution: TUI, desktop, and Web UI as one bundle with layered installation.
weijiafu14/pi2dsh★ 212
Pi Host ABI compatibility engine: after one install, unmodified Pi extensions from npm mount as native DSH plugins with `dsh plugin add <pi-package>`. Verified end to end on stock DSH with pi-mcp-adapter (full MCP manager: OAuth, resources, prompts, MCP Apps, elicitation, sampling), @tintinweb/pi-subagents, pi-code, pi-hermes-memory and pi-background-tasks; `pi2dsh inspect` reports a package's compatibility before installing.
Fishquito7/dsh-skill-mcp-panel★ 179
Manages DSH skills and MCP servers from the web settings: skill cards with hot enable/disable, workspace scopes, groups, batch migration and drag-and-drop import, plus stdio/HTTP MCP CRUD with connection tests, secret redaction and the unified dsh-panel CLI.
lire1131/dsh-undo-savepoint★ 176
Undo/redo & rollback system for DSH: every config change is auto-snapshotted; undo/redo/restore to any version from the WebUI or the offline CLI/GUI tools (works even when DSH fails to boot).
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.