Back to home@leonardoxr

dsh-harness-updater

Claude Code / Codex CLI update detection, prompting, and one-click channel updates for DeepSeek Harness

Stars
1
Language
TypeScript
Created
Aug 24, 2026
Updated
Aug 25, 2026
GitHub repo

Introduction

dsh-harness-updater

English | 简体中文

Agent harness updates for DeepSeek Harness. Detects the locally installed Claude Code and Codex CLI, compares them against the latest published versions, prompts in the DSH web UI, and — on your explicit click — runs the correct channel-specific upgrade command.

Inspired by the provider maintenance model of T3 Code.

What it does

  1. Detects each harness on PATH (Windows .cmd/.ps1 shim aware) and probes <harness> --version with a bounded timeout.
  2. Classifies the install channel from the resolved binary path: native installer, npm / pnpm / bun global, Homebrew, or manual-only.
  3. Checks npm (registry.npmjs.org/<pkg>/latest) for the latest version with a 4 s timeout and a 1 h cache. Fully disabled via settings when offline.
  4. Prompts: a persistent Updates card in DSH Settings → Plugins lists each harness with current → latest and an in-place Update button. Under DSH Native it also shows the native app's own self-update status.
  5. Updates on click only — never silently. The runner serializes per channel lock, enforces a hard timeout with process-tree termination, caps captured output, then re-probes to verify and reports succeeded, unchanged, or failed.
Detected channelUpdate command
Claude native (~/.local/bin/claude*)claude update
npm globalnpm install -g --allow-scripts=<pkg> <pkg>@latest
pnpm globalpnpm add -g <pkg>@latest
bun globalbun install -g <pkg>@latest
Homebrewbrew upgrade claude-code / brew upgrade --cask codex
anything else (WinGet, standalone installers)manual: copyable hint, no one-click

The npm command passes --allow-scripts because npm ≥ 12 blocks lifecycle scripts by default while still exiting 0, which would leave Claude Code's placeholder binary unreplaced.

Safety model

  • Every route is loopback + same-origin gated; updates are POST-only mutations.
  • One update per harness at a time; updates sharing a package manager queue behind a shared lock instead of racing.
  • DISABLE_UPDATES=1 in the Harness environment blocks all automatic paths.
  • Child processes are killed as a tree on timeout (Unix signals / taskkill /t /f).
  • Updates are never started without a user click; nothing runs on a timer.

Install (local development)

Reference the plugin from your DSH profile:

// ~/.dsh/profiles/web/package.json
"dependencies": { "dsh-harness-updater": "link:C:/path/to/dsh-harness-updater" }

Add the bundled patch entry (the repo's cordis.patch.yml inserts it), run pnpm install in the profile, then restart DSH Web (host half).

Development

pnpm install
pnpm check        # typecheck + build + test

Configuration

All fields are editable in DSH Settings → Plugins → Harness updater (restart applies):

FieldDefaultMeaning
enableUpdateCheckstrueQuery npm for latest versions
statusRefreshIntervalMs900000Background status poll interval (min 60000)
hoverRefreshMinAgeMs30000Min age before a forced refresh is allowed (min 5000)
probeTimeoutMs5000Timeout for each --version probe (min 1000)
latestTimeoutMs4000Timeout for each registry lookup (min 1000)
latestVersionTtlMs3600000Registry result cache lifetime (min 30000)
updateTimeoutMs300000Hard timeout for an update command (min 30000)
claudeCommand / codexCommand / npmCommandclaude/codex/npmExecutables to use

License

MIT