DeepSeek Harness Plugin

a1113622001/dsh-auto-update

Stars ★ 2 Category Development & Runtime Added 2026-08-23

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

  1. 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 via config.installRoot. If the harness is running from source (pnpm dsh), auto-update is unavailable and logs a note.
  2. 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 as 1.2.3-rc.1).
  3. Staging — npm pack downloads the exact version's tarball into $DSH_HOME/updates/ and writes pending-update.json (with from/to, install root, process pid, whether to relaunch, etc.). This step never touches the running installation.
  4. Applying — on the harness's process.on('exit') it detaches bin/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 relaunches dsh <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 the github: prefix) fails with a missing-package error.

When installing manually, you must register the cordis.patch.yml bundle at the repo root with the harness so the plugin starts with it. dsh plugin add already carries that bundle, so no manual patching is needed — the YAML block below is exactly the content of cordis.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 relaunch to true, or click "Update and restart" in the panel.
  • Panel buttons: /auto-update is a loopback-only HTTP channel mounted on the harness web server; the browser calls status / check / stage / cancel / applyRestart via POST /auto-update/<endpoint>. It is a plain webServer prefix route, not a connection.rpc channel — on dsh ≥ 0.1.5 the latter throws cannot get property "webServer" without inject from inside the connection service and the route silently never mounts.
  • Manual trigger: applyRestart forces a check first, stages if needed, then writes relaunch: true to 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 exit event), 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.jsonl records the outcome of each apply; update-result.json holds 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 dsh CLI 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 EBUSY during npm 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 -g requires write access to the npm global directory and cache (normal user permissions are enough).
  • If the plugin source directory is moved away, the helper path recorded in a staged manifest becomes stale; re-checking re-stages a fresh manifest.

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →

Community comments

Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.