dsh-workspace-cleaner
Manifest validWorkspace & session cleanup for DeepSeek Harness: a settings page listing every workspace with its session count, plus a sidebar session menu row that really deletes a session log (into a recoverable
dsh-workspace-cleaner
Workspace and session cleanup for DeepSeek Harness — a settings page that lists every workspace registration with its session count, plus a delete session row in the sidebar's session menu that really removes the log (into a recoverable trash).
Git 版说明见 README.zh.md。
Why this exists
DSH deliberately ships no session deletion. The JSONL persistence backend documents it plainly:
Nothing deletes session files — logs accumulate under
rootuntil removed externally; the seam has no deletion API.
So the sidebar's session menu only offers Archive. Once a few hundred sessions pile up, the sidebar becomes unmanageable and the logs keep growing on disk. This plugin fills the two gaps:
- Settings → Workspace Cleanup — one table of every workspace: its path, session count, whether the directory still exists, bulk archive of its sessions, and deletion of the workspace registration.
- Session menu → Delete session — moves that session's log directory into a trash folder, hides the sidebar row immediately, and offers restore/permanent deletion from the settings page.
Nothing is unlinked on the first click: deletion is a rename, so it stays recoverable.
Install locally
# from the directory that contains this package
dsh plugin add /absolute/path/to/dsh-workspace-cleaner
Or, inside a DSH session, ask the agent to install the bundle from the local directory; plugin_manager install_bundle links the checkout into the profile (node_modules/dsh-workspace-cleaner), so later edits to the files need only a restart.
Restart DSH after installing (the Host half registers HTTP routes), then reload the Web GUI.
Use
Session menu
Open a session's "…" menu → Delete session → confirm.
- Deleting a live session is refused: its writer still owns the log. Switch to another session first.
- The row disappears immediately — deletion archives the session (what the sidebar filters on) before moving the log, because the registry's in-memory session index would otherwise keep listing the file until a restart.
- The log directory is renamed to
<dsh-home>/session-trash/<timestamp>--<session-id>/with ameta.jsonrecording the title, project directory, cwd and deletion time.
Settings → Workspace Cleanup
| Action | Effect |
|---|---|
| Archive sessions (per workspace / bulk) | workspaceRegistry.archiveSession — sessions leave the grouped list, recoverable from the archived list |
| Delete workspace (per workspace / bulk) | workspaceRegistry.delete — drops the registration only; session logs, directories and files stay |
| Trash → Restore | Moves the log back, unarchives the session and re-attaches it to its workspace |
| Trash → Delete permanently | Removes the trashed directory for good and reports the freed bytes |
How it works
client.js ──POST /workspace-cleaner/api/{list,apply,trash,deleteSession,restore,purge}──► index.js
(settings.section page + sidebar session menu row) (Host: workspaceRegistry,
sessionPersistence,
node:fs over the log root)
- The Host half owns every operation and exposes them over one JSON route guarded by the same browser-trust fence as the shipped browser routes (
ctx.connection.requestRejection). It is the only part that touches the filesystem. - The Client half registers two slots: a
settings.sectionpage (Workspace Cleanup) and one row insidebar.workspaces.session.menu.item(Delete session, order 500, after the shipped rows). All text goes through the locale service (zh/en), and all styling uses--dsw-alias-*theme tokens. - Data comes from the Host rather than the Client's
ctx.workspacesface, because that face can only mutate a workspace it is already given — it cannot enumerate them for a plugin page.
Session log discovery
The JSONL backend's documented layout is:
<root>/
--<normalized-cwd>--/
<session-id>/
session.v4.jsonl.zstd
<root> is resolved from the first candidate that exists and holds project directories:
config.sessionRoot(see below)$DSH_PROFILE_DIR/../../sessions$DSH_PROFILE_DIR/sessions$DSH_HOME/sessions~/.dsh/sessions
A session is matched by its own directory name, and the directory must contain session*.jsonl[.zstd].
Configuration
- id: workspace-cleaner
name: dsh-workspace-cleaner
config:
sessionRoot: 'D:\somewhere\session-logs' # optional override
| Field | Default | Meaning |
|---|---|---|
sessionRoot | auto-discovered | Absolute path of the JSONL session-log root |
Safety model
- A live Agent (
ctx.agents.get(id)) is refused with409 session/live. - A missing log is not an error: the session was either never materialized (nothing on disk) or already deleted; the accounting is cleaned and the caller gets
unmaterialized/alreadyDeletedinstead of a failure. - A failed rename rolls back the archive, so the row never claims a deletion that did not happen.
- Trash entry ids are validated (no
.., no separators) before any path is built. - Deleting the currently open session is refused — it is always live.
Known limitations
- A session deleted while its row is still cached in the GUI needs a page reload/restart to drop from the archived list; the grouped list updates immediately.
- The SQLite search index can hold a stale hit for a deleted session until the next DSH start.
- Session directories are matched by id; ids containing characters the backend escapes differently would report "no session log on disk".
- The trash lives beside the log root (
<dsh-home>/session-trash) so the backend never scans it.
Development
No build step: plain ESM, plain browser module.
node .verify-host.mjs # Host route + real filesystem (delete/restore/purge) — 58 checks
node .verify-client.mjs # both slot components under a tiny hook renderer — 67 checks
License
MIT
Comments
Loading…
Similar plugins
by LucasCaleb-ggg
Batch session cleanup for DeepSeek Harness — pick a workspace, see which sessions are archived, and permanently delete logs, projection caches and workspace records.
★ 0
MIT
JavaScript
Oct 31, 2026
dsh plugin --profile web add dsh-session-cleanupby OliYogSothoth
Delete DeepSeek Harness sessions for good — via a recycle bin: move, restore, then the next start wipes the log, projection cache, spill files and workspace accounting.
★ 1
MIT
JavaScript
Nov 4, 2026
dsh plugin --profile web add dsh-plugin-session-purgeby The932
Delete sessions from the DeepSeek Harness Web sidebar: a menu action plus a confirmation dialog that removes the session log.
★ 0
MIT
JavaScript
Oct 27, 2026
dsh plugin --profile web add dsh-session-deleteby SunshineR04
Settings-page manager for archived DeepSeek Harness sessions: restore an archived session to its previous workspace position or permanently delete it (direct physical deletion, no backup layer). Adds
★ 1
↓ 3.8k/wk
MIT
JavaScript
Oct 10, 2026
dsh plugin --profile web add dsh-session-managerby liudapeng0311
Delete sessions into a recoverable trash, clean up sessions orphaned by deleted workspaces, and group workspaces into categories. A DSH plugin.
★ 0
MIT
JavaScript
Nov 5, 2026
dsh plugin --profile web add dsh-session-hygieneby reverse-PAI
Permanently delete a DeepSeek Harness session: a sidebar session-row "..." menu item plus a hover button, a risk-consent dialog, and an authenticated Host route that removes the session log, its projection-cache row and its archive mark.
★ 1
MIT
JavaScript
Oct 19, 2026
dsh plugin --profile web add dsh-minimal-session-delete