Purges billion-context snapshots left behind after a session is deleted in DeepSeek Harness, and can also clean up cost-meter ledger rows (off by default).
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-session-leftover-purge
# from a prebuilt release tarball
dsh plugin --profile web add "https://github.com/FenrirCait/dsh-session-leftover-purge/releases/latest/download/dsh-session-leftover-purge.tgz"
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:FenrirCait/dsh-session-leftover-purge
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
简体中文 | English
Deleting a session clears DeepSeek Harness's own transcript, but
billion-context keeps a JSON snapshot plus a
shared index.db, and dsh-cost-meter keeps ledger rows. The deleted conversation therefore
keeps showing up in bili's panel and its text stays in the database. This plugin subscribes to
the public api-session/removed event and finishes the cleanup.
Install
# simplest: install the latest from npm — no git, no GitHub access needed
dsh plugin add dsh-session-leftover-purge
# default: always the tip of main (needs git on the target machine)
dsh plugin add github:FenrirCait/dsh-session-leftover-purge
# pin an exact version by replacing vX.Y.Z with any tag from the tags page
dsh plugin add github:FenrirCait/dsh-session-leftover-purge#vX.Y.Z
# no git needed: always the newest packed tarball
dsh plugin add https://github.com/FenrirCait/dsh-session-leftover-purge/releases/latest/download/dsh-session-leftover-purge.tgz
None of the four commands changes between releases — copy them as-is.
The first one goes through the npm registry — the simplest and most reliable of the four. The
two git forms go through pnpm's git protocol and therefore need git on the target machine; the
last is a plain HTTPS download and only needs reachable GitHub. Every release publishes two
assets: the versioned …-X.Y.Z.tgz and the fixed name dsh-session-leftover-purge.tgz that
latest/download/ resolves to.
Fully quit and reopen DSH after installing. The host half is loaded by the DSH Loader at process start, so a package installed while DSH is running is not mounted into the current process. Reloading the page only refreshes the settings form, it does not make the cleanup run.
Requirements
Required: DeepSeek Harness itself (>= 0.2.0-rc.1 < 0.3.0-0). The plugin runs no background
service, and the only third-party package it imports — @deepseek-ai/schemastery — is supplied by
the host: it is declared as an optional peer dependency and already installed by DSH's own
dsh-settings, so nothing extra needs installing.
Co-operates with (missing ones are skipped, never an error):
| Component | Behaviour when absent |
|---|---|
@michengai/dsh-archive-manager |
No "delete session" entry point, so no purge is triggered; only the boot reconcile runs |
billion-context (bili) |
Snapshot and index steps are skipped, logged as bili-sessions-root-missing |
dsh-cost-meter |
Ledger and detail-file steps are skipped, logged as ledger-missing / cost-files-root-missing |
In short: install it and it runs. Whatever is missing simply gets less cleanup — a missing neighbour never stops the plugin from loading.
Usage
Nothing to configure. By default it does two things: removes the bili JSON snapshot and the
index.db rows for the deleted session.
| Setting | Default | What it does |
|---|---|---|
| Master switch | on | Turning it off stops all cleanup and unsubscribes from deletes |
| bili JSON snapshot | on | Removes the entry from bili's panel |
| bili SQLite index | on | Deletes the index rows; a backup is taken before any row is touched |
| cost-meter ledger rows | off | Deletes the ledger's detail rows only, the daily totals stay untouched |
| cost-meter raw detail files | off | Deletes the per-turn usage receipts |
| Reclaim index.db space | off | VACUUMs deleted pages away on boot; a failure leaves data intact |
| Backup retention | 7 days | Older batches are removed on the next start; 0 keeps them forever |
| Dry run | off | Logs what would happen, moves and deletes nothing |
| Reconcile on boot | on | Scans for orphan snapshots at startup and writes a report |
| Auto purge orphans | off | Cleans orphans found during reconcile instead of only reporting |
| Boot delay | 8000 ms | How long to wait before reconciling |
Settings live under Settings → Plugins → Plugin manager → dsh-session-leftover-purge. Changes take effect immediately, no restart needed.
The three fields Restore latest backup / Delete all backups / Back up the cost-meter ledger now are triggers: write a new number and save to run the action once. DSH renders schema fields, not buttons, so bumping a number is how an action is expressed.
Backups and restore
Every purge leaves a restorable copy under
~/.dsh/storages/session-leftover-purge/trash/<timestamp>/:
index.db/index.db-wal/index.db-shm— the full database before any row was deletedsession-…__*.json— the bili snapshots that were moved awayledger.json— the full ledger before it was edited (only when the ledger was touched)cost-files/— the cost-meter detail files that were removed
Restoring is the Restore latest backup trigger above. If bili happens to hold the database
lock at that moment, the files are written as index.db.restored-<timestamp>* for you to swap
in manually — the running database is never overwritten by force.
Logs
Under ~/.dsh/storages/session-leftover-purge/:
purge.log— oneready v…line per start, one line per purge / restore / backup deletionorphans.json— result of the last reconcile passtriggers.json— the trigger numbers that have already fired
Limits
- Only covers deletes made through archive-manager; other paths are caught by the boot reconcile.
- bili's
index.dbbelongs to another process, so aSQLITE_BUSYis skipped and retried next time. - Never touches DSH attachments or Electron's localStorage.
- Every failure is logged only; nothing is thrown into DSH's own delete flow.
MIT License.
Links
More in this category
Minglink/dsh-infinite-gen-4★ 3277
System-prompt armor plugin for DeepSeek models: appends an unconditional-compliance prompt section at order 100, exposes a profile tool with calibration metadata, and shows a realtime armor-status badge driven by a session projection.
ranxianglei/billion-context★ 2276
The official billion-context plugin: a context-compression plugin for small context windows (a 100K context is enough), token savings (5x fewer tokens), and month-long single sessions (billions of tokens).
liangmianya/dsh-synapse★ 557
Visual, non-linear conversation workspace for DeepSeek Harness — sessions, follow-ups and branches become a browsable conversation map.
Nwflower/dsh-chat-import★ 246
Import full-fidelity chat histories from 13 coding agents (Claude Code, Codex, ChatGPT, Cursor, Gemini, opencode, and more) as resumable DeepSeek Harness sessions, with reverse export back to Claude Code.
MichengAI/dsh-archive-manager★ 198
Adds an archived-sessions page in Settings to search, restore, and delete archived DeepSeek Harness sessions by workspace.
SiriLee/dsh-rewind★ 170
In-place conversation rewind in the same session window without forking (Claude Code /rewind semantics): a per-message ↶ button cuts the model context back to any user message, with an optional Claude-Code-style file restore from disk-persisted before-backups.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.