Plugin directory / Data / dsh-single-instance-guard
dsh-single-instance-guard
Verified · install-tested on dsh Tang-mm95
What it does
DSH_HOME single-instance lock plugin for DeepSeek Harness: aborts startup loudly when another dsh server uses the same data directory (prevents session-log corruption)
Works — verified, early-stage project
DSH_HOME single-instance lock plugin for DeepSeek Harness: aborts startup loudly when another dsh server uses the same data directory (prevents session-log corruption) It installs cleanly and boots without issues in our testing. It's early-stage but functional.
“Verified” means our automated CI actually ran dsh plugin add in a clean profile and it booted — nothing more. Feature descriptions and version compatibility are the author’s claims. This is not a security audit and not an endorsement of third-party code.
README
dsh-single-instance-guard
A zero-dependency DeepSeek Harness plugin that takes an exclusive lock on the DSH_HOME data directory at startup and aborts loudly when another live dsh server already uses it.
Why
The JSONL session persistence backend documents "One live writer per session" and has no cross-process defense. Two dsh servers sharing one DSH_HOME (a desktop wrapper spawning its own server, or two dsh web processes) append batches with stale sequence cursors, corrupting session logs:
history unavailable for session "…": Error: corrupt session log: seq gap in committed region …
See this report for the full diagnosis, a read-only scanner, and a manual repair procedure.
This plugin turns the silent corruption into a loud startup failure.
Install
After publishing to npm:
dsh plugin --profile <profile> add dsh-single-instance-guard
Manual (any dsh install): add the row to the profile's cordis.patch.yml before session-related bundles:
- insert:
- id: single-instance-guard
name: 'dsh-single-instance-guard'
The guard is a profile bundle: its manifest declares the same patch, so the CLI installs it as a patch layer.
How it works
- Creates
<DSH_HOME>/.dsh-server.lockatomically (O_EXCL), holding{ pid, startedAt, hostname }. - On conflict, probes the holder's pid liveness: a live holder aborts startup with a clear bilingual error; a stale lock (dead pid or unparsable file) is removed and acquisition retried once.
- On process exit the lock is removed — only if still owned by this process.
DSH_HOME is resolved exactly like dsh itself: $DSH_HOME or ~/.dsh. Servers with different data roots never conflict.
Known limits
- The unlink+retry path has a tiny race when two processes discover the same stale lock simultaneously; the atomic
O_EXCLwrite still admits exactly one winner, and the loser fails correctly on the retry. - The lock protects against concurrent servers sharing one
DSH_HOME. It does not protect against two dsh instances deliberately pointed at the same session file via different roots (unsupported anyway).
Development
npm test # node --test
License
MIT
Install
Install the catalog once, then DeepSeek Harness can find and install any plugin from this site automatically:
dsh plugin add dshbase-catalog Then say "install dsh-single-instance-guard for me" — your agent finds it in the directory and installs it. Docs: dshbase-catalog · verified packs.
This plugin is GitHub source (not published to npm) — install it straight from the repo:
Web profile:
dsh plugin --profile web add github:Tang-mm95/dsh-single-instance-guard Headless (CLI) profile:
dsh plugin --profile headless add github:Tang-mm95/dsh-single-instance-guard Test report
Verified: L1 install + L2 load + L3 runtime from GitHub source on dsh 0.1.0-rc.6.