DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Session Eraser — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
S

dsh-session-eraser

Session Eraser

Delete a session from the DSH sidebar, removing its stored log and workspace accounting. Guards the session that is currently open.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:Gty2408/dsh-session-eraser#7caddbed5767c52150b349f4f64e72569b8f9f1a
READMECompatibilityVersions

Compatibility and provenance

Session Eraser is published as dsh-session-eraser and currently resolves to version 1.0.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/30/2026

Versions

1.0.0stable
9/30/2026

Related plugins

Loading related plugins…

Latest
1.0.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/30/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in memory-context.

Memory Plugin@openviking/dsh-memory-pluginOpenViking memory and context bundle for DeepSeek HarnessWeknora@wxg-prc-cpg/dsh-weknoraWeKnora knowledge retrieval tools for DeepSeek Harness (dsh): semantic search, document reading and RAG/agent answers over your own knowledge bases.Memsearch Dsh@zilliz/memsearch-dshMemSearch plugin for DeepSeek Harness: shared markdown memory across agents, with capture, pre-step context injection, memory-recall skill, and a skill-candidate review panel.Memory@furongjun1999/dsh-memoryLingshu (Lingshu·líng shū) DeepSeek Harness plugin: a complete brain—long-term memory/knowledge flywheel/self-awareness/recursive reflection integrated with DSH, with conversations automatically distilled into the md_cg cognitive graph (md documents)

README

dsh-session-eraser

Delete a session from the DSH sidebar, permanently removing its stored log and its workspace accounting.

Install

dsh plugin --profile desktop add dsh-session-eraser

Then restart DSH. The command installs the package, applies this package's cordis.patch.yml through the dsh.bundle.patch mechanism, and adds the package to the profile's bundle list — no manual configuration editing.

Without the dsh CLI, add the package to the profile's node_modules and put this in the profile's cordis.patch.yml:

- insert:
    - id: dsh-session-eraser
      name: dsh-session-eraser

What it does

Adds a Delete session entry to each session row in the sidebar, in two places:

  • the row's ... menu, below the shipped Archive row;
  • a hover-revealed trash button beside the row's other actions.

Either entry opens a confirmation dialog. Confirming removes the session's stored artifact from disk, detaches it from the Workspace, and tells every connected client that the session is gone, so the row disappears immediately.

The open-session guard

Deleting the session that is currently open in the main panel is refused.

This is deliberate. The Workspace UI reconciles an archived current selection but has no path that reacts to the current session being removed: it exposes no public close/leave API, and openSession can only replace. Deleting the open session would therefore leave the main panel pointing at a session that no longer exists, with the composer silently disabled and no way back.

So the guard refuses in four places:

Entry pointBehaviour when the session is open
... menu rowRendered disabled, labelled Delete session (currently open)
Hover trash buttonNot rendered at all
Dialog confirm buttonDisabled, with an inline explanation
Dialog confirm actionRe-checks retention and refuses

The hover button is omitted rather than disabled because a natively disabled button fires no pointer events, so its tooltip could never explain the refusal — and the row-action slot's own catalog prescribes rendering nothing when an action does not apply to the row.

Host route

POST /api/session.delete

// request
{ "sessionId": "session-04e8f277-…" }

// 200
{ "ok": true, "status": "deleted", "live": true, "detached": true, "removed": 1 }
StatusBodyMeaning
200{ ok: true, … }Deleted, and verified gone from disk
400{ error: "…" }Malformed body, or missing/invalid sessionId
404{ error: "session not found" }No stored artifact and no live session
500{ error: "…" }Unexpected failure, or the artifact survived removal

The route never reports success it cannot verify. rm fails for real reasons on Windows — a locked or deny-ACL'd file throws EPERM/EBUSY — so after removing the artifact the plugin re-checks the path and answers 500 if anything survived, leaving the workspace accounting untouched so the sidebar keeps showing the session that in fact still exists.

The route is served through the connection's Fetch handler, so it sits behind the same authentication gate as the rest of /api and is reachable only from a trusted origin.

Deletion sequence

The Host has no session-eraser API, so deletion is composed from public pieces in a specific order:

  1. workspaces.stopSessionActivity(sessionId) — request a stop for the session.
  2. sessions.liveEntryFor(live) + sessions.detachEntered(entry) — detach the live session, which also dispatches session/disposed.
  3. Settle the writer. Persistence teardown's writer.close() is not awaited, and appendLines opens the log with open(path, "a") per batch — which recreates a deleted directory — so a drain that loses the race would resurrect the log. Two mechanisms cover this:
    • settleWriter(...) joins the in-flight close directly. It reads an undocumented internal (persistence.tracker.openHandles) and fails open if that is ever renamed, so it is an optimization, not the guarantee.
    • persistence.flush() — the public durability barrier — drains every active write handle, and a concurrently-closing handle counts as flushed.
    • When neither could be awaited, the removal is held for a bounded settle window, re-removing anything a late drain restores.
  4. Remove each located artifact, then verify it is gone. Anything that survived is reported as a failure rather than a success.
  5. Re-index the workspace, clear the session's archive and pin entries, and detach it from its owning entities.
  6. ctx.emit("api-session/removed", sessionId) — so cold sessions vanish from other clients immediately, not just on the next list refresh.

Step 5's archive/pin cleanup matters because those are registry-global id lists: deleting the session removes the row they refer to, so nothing in the UI can ever offer to unarchive or unpin it — the id would dangle permanently. Both removal APIs skip the session-existence check by design ("an entry whose session is gone still resolves"), which is exactly this case.

Owners are captured before re-indexing, because entity.sessionIds is filtered live by the canonical-cwd header index and re-indexing prunes the id.

Storage layout

Artifacts live under ~/.dsh/sessions/<encoded-project-dir>/<encoded-id>/, with the log at session.v4.jsonl.zstd. The plugin mirrors the backend's encodeSegment exactly, so a hostile sessionId (traversal sequences, absolute paths, separators) can only ever resolve to its own escaped directory inside the root. test/host-traversal.test.mjs plants canaries and proves this.

Tests

node test/run.mjs

The host-* suites are hermetic — they use throwaway persistence roots and stub the services the route touches. The live-* suites talk to a running app (DSH_TEST_ORIGIN, default http://127.0.0.1:19387) and self-skip when it is unreachable.

SuiteCovers
host-route.test.mjsCold-session deletion, status codes, artifact removal
host-live.test.mjsLive-session branch: stop, detach, settle, owner detach
host-writer-race.test.mjsA late writer drain must not resurrect the log
host-race-control.test.mjsThe same race without the fix must fail — proves the fix is load-bearing
host-internals-change.test.mjsDeletion stays correct when tracker.openHandles is absent
host-bookkeeping.test.mjsA deleted session leaves no dangling archive/pin entry
host-partial-failure.test.mjsA real EPERM from a deny-ACL is reported, not swallowed
host-traversal.test.mjsHostile ids resolve only to escaped in-root directories
client-guard.test.mjsBoth entry points and the dialog, including the open-session guard
live-end-to-end.test.mjsAuthenticated HTTP against the running app, including a real deletion
live-bundle.test.mjsThe running app serves the guarded client bundle at the advertised revision

live-* mints its own auth cookie from the browser-session signing secret in ~/.dsh/.credentials.yaml; no browser or cookie jar is involved.

Known limitations

  • Attachments are not removed. Deletion removes the session log and its workspace accounting; files the session referenced on disk are left in place (their references go away with the log). Removing them would require knowing which files the session actually created rather than merely read.
  • The open-session guard is client-side only. The Host has no view-state concept — mainView retention lives in the browser — so a hand-crafted POST /api/session.delete for the currently-open session is not refused. The route is behind the normal auth gate, so this is reachable only by the user's own authenticated client, and the shipped UI never sends it.
  • settleWriter reads an internal. persistence.tracker.openHandles is not part of the documented seam. The plugin treats it as an optimization: if it disappears, the public flush() barrier and the bounded settle window still produce a correct deletion, and host-internals-change.test.mjs pins that.
  • Deletion is not transactional. If the process dies between removal and re-indexing, the artifact is gone but the workspace accounting may still list the session until the next index rebuild, which reconciles it.

Layout

lib/index.js    Host half: the delete route and the deletion sequence
lib/client.js   Browser half: menu row, hover button, confirmation dialog
cordis.patch.yml  Registers the bundle
test/           Test suite (see above)