Introduction¶
DSH sessions are scattered under $DSH_HOME/sessions/<workspace encoding>/<session id>/. The official version only provides archival capabilities, not true deletion. To clean up an old session, you have to manually delete the directory; what’s more troublesome is that as long as the session is still loaded in memory by the host, deleting the file will cause it to be written back, and it will appear again after a restart.
full626/dsh-session-trash-90d is here to fill this gap: a DSH client bundle that provides a session list, trash bin, restore, permanent deletion, and the “unarchive” function which the official version lacks. The following text explains “what it solves → how to use it → what to watch out for”.
What is it¶
One-sentence positioning: A session management plugin for the DSH Web GUI, providing a list, archive/unarchive, and true deletion (it catches the session with a recoverable trash bin before performing an irreversible permanent deletion).
- Maintainer: Full626
- Category: Client (DSH bundle, not a standalone app)
- Stars: 0
- License: MIT
- Compatible Hosts: DSH
>=0.2.0 <0.3.0, Node>=22
Its entry point is “Settings → Session Management”, without adding a new standalone interface.
Why can’t we delete files directly¶
DSH 0.2.x’s sessionPersistence only has create/open/stat/list/flush, and sessions only has create/prepare/enter/announce/flush/get/list/fork; there is no API for deleting sessions. Therefore, “true deletion” can only be achieved by directly deleting the artifacts on the disk.
However, previous “true deletion” plugins encountered a pitfall here: they only skipped agent.status === 'running' (generating a response), but running and live (loaded into memory) are two different things. Consequently, when a session that is “idle but live” has its file deleted, the host will write it back, and it is as if it wasn’t deleted after a restart.
This plugin’s approach is Tombstone + Startup Replay:
Delete request
├─ Not live → Delete file directly (clean)
└─ Live → Record a tombstone + attempt release + delete file, marking it as pending truthfully
Host startup (plus 5s later) → Replay tombstones: at this time, no one has them open, so deletion is real
Only after confirming disappearance and no longer being live is the tombstone cleared
Each deletion simultaneously cleans up: the session directory, projection cache, archive set, and workspace accounting.
There is a trade-off worth noting in the design: the host side relies only on the file system, plus two optional services—workspaceRegistry managing the archive set, and sessions for liveness detection—without touching any private APIs. In the future when DSH is refactored, this plugin’s behavior is graceful degradation (the list becomes empty) rather than crashing.
Core Features¶
| Feature | Description |
|---|---|
| Session List | Title, Workspace, Last Modified, Size, and In Memory / Archived tags |
| Move to Trash | Not wiped directly: the session directory with projection cache is moved to sessions-trash, kept for 90 days |
| Restore | Returns to the original workspace, cache restored along with it |
| Purge / Clean Expired | Manually select, or clear those older than 90 days; also auto-cleans when listing the trash |
| Empty Session Collapse | Sessions that have only been opened but not used (only header records) are hidden by default, can be expanded |
| Archive / Unarchive | Official only has archive, not unarchive; this fills that gap |
| Tombstone Status | UI prompt indicating how many are pending next startup |
Export functionality is not implemented; the official /export is sufficient, so no need to reinvent the wheel.
Trash Bin Directory Structure¶
$DSH_HOME/sessions-trash/<deletion-timestamp>-<session id>/
├─ meta.json Original workspace, title, size, deletion time
├─ session/ Session directory (moved as is)
└─ cache.json Projection cache (moved as is)
Each entry carries its own metadata, so there is no global list, preventing mismatches between the list and actual files. The directory name starts with a timestamp, naturally sorted by time; restoring simply moves it back. Expired cleanup is triggered at two times: when the host starts, and every time the trash bin is opened.
Installation and Enablement¶
This package is a DSH bundle: in the profile, simply select the package name into dsh.profile.bundles, and the loader will apply the built-in cordis.patch.yml.
The install.ps1 script in the repository supports three dry-run modes:
cd dsh-session-trash-90d
.\install.ps1 -Profile desktop # Default is desktop
.\install.ps1 -Profile desktop -DryRun # Just see what changes will be made
.\install.ps1 -Profile desktop -Uninstall
Step 1, DryRun first. It will print which profile files will be changed; confirm there are no errors before executing.
You can also use the profile’s own plugin manager (the “Plugins” page in Settings) and fill in the repository address:
https://github.com/Full626/dsh-session-trash-90d
Or via command line:
dsh plugin --profile desktop add 'github:Full626/dsh-session-trash-90d'
Step 2, Restart the app. New bundle layers only take effect on the next bundle composition; you won’t see changes immediately after installation.
Step 3, Open Settings → Session Management.
Typical Usage¶
After installing and restarting, daily operations are completed within “Settings → Session Management”:
- See all stored sessions and their metadata in the session list, distinguishing between
In MemoryandArchived. - To clean up a session, click “Move to Trash” — it moves the directory and cache together, not wiping it directly.
- When you need to retrieve it, click “Restore” in the trash bin; it will return to the original workspace.
- Only when you confirm you don’t want it anymore should you use “Purge”, or let “Clean Expired” handle those older than 90 days.
Sessions that are alive in the host’s memory and couldn’t be released won’t disappear immediately after deletion. The interface will prompt “N more pending next startup”, which is intentional honesty: next time the host starts, the tombstones are replayed, and only after confirming disappearance and no longer being live, are they cleared.
The command line side also has a set of interfaces available for automation:
| Method | Path | Description |
|---|---|---|
| GET | /list |
Session list + pending tombstones + retention days |
| GET | /trash |
Trash entries (also cleans expired items on the fly) |
| GET | /state |
Tombstones, home, two root directories, retention days |
| POST | /delete |
body {"ids":[...]} — move to trash |
| POST | /restore |
/purge |
| POST | /archive |
/unarchive |
How to run during verification¶
The host side has a set of tests that don’t touch real data: it creates fake sessions in a temporary $DSH_HOME, drives the real plugin code with a minimal fake ctx, specifically covering that regression — fake “memory writeback”, then verify that startup replay clears it.
node scripts/test-host.mjs # 27 items: list/delete/tombstone/replay/archive/error handling
Checks running on a real desktop are read-only by default:
# Read-only: list sessions, tombstone status
node scripts/check-api.mjs --url http://127.0.0.1:19387
# If you really want to delete a few (be careful)
node scripts/check-api.mjs --url http://127.0.0.1:19387 --delete session-xxxx
Applicable Scenarios and Notes¶
Suitable for these people:
- Developing on DSH 0.2.x and tired of “sessions that can’t be deleted / come back after being deleted”.
- Need to batch clean up old sessions without the risk of losing them if accidentally deleted.
- Need the ability to unarchive, which the official version doesn’t provide.
Points to note:
- Deletion defaults to keeping for 90 days; “Purge” and expired cleanup are irreversible. So don’t treat the trash bin as an indefinite safety deposit box, and don’t treat permanent deletion as a routine operation.
- The trash bin consumes disk space; if you delete a lot, remember to clean it up, or let it expire on its own.
- The host will not delete a session while it is running (it will skip and notify), this is intentional design, not a bug.
- This plugin runs with the permissions of the current DSH process and installs by directly modifying profile files — read the source code and MIT license before installing, and use
-DryRunwithinstall.ps1first to review. - The session body is JSONL + multi-frame zstd; this plugin only does management and does not parse the body content, so it cannot obtain the semantics of “what this session talked about”.
- The path layout is parsed according to DSH 0.2.x’s
$DSH_HOME/sessions/<workspace encoding>/<session id>/; if the layout changes in the future, the behavior is that the list becomes empty rather than accidental deletion. - This plugin is a community third-party package; the directory page and the repo are independent site projects, with no official affiliation with DeepSeek / Hypothesis.
Summary¶
The value of dsh-session-trash-90d lies in its acknowledgment of the real constraint that “sessions revive after deletion,” and providing a verifiable solution: Tombstone + Startup Replay, plus a 90-day trash bin, original workspace restoration, and unarchiving. If you are doing session governance on DSH 0.2.x, it is worth running node scripts/test-host.mjs first to see the 27 tests pass, then installing it to your profile.
Directory Page: https://www.skillhub.cn/plugins/Full626/dsh-session-trash-90d
Repository: https://github.com/Full626/dsh-session-trash-90d