- Início
- Plugins
- Melhorias de UI
- dsh-enhancer
dsh-enhancer
adamcjm/dsh-enhancer
Quality-of-life enhancements for the DSH workspace sidebar: hide workspaces and their sessions, reveal them from the view options, and open any workspace folder in Finder, Explorer or your file manager. Display-only: workspace, session and archive data ar
Instalar
dsh plugin --profile web add github:adamcjm/dsh-enhancerREADME
@adamcjm/dsh-enhancer
English | 中文
A DeepSeek Harness plugin that adds the small, everyday operations the shipped workspace menus are missing. It is deliberately named after the area rather than one feature, so new menu enhancements can be added without renaming the package again.
Today it ships four things:
| Where | Entry | What it does |
|---|---|---|
| Workspace row → "…" menu | Open folder | Opens the workspace's directory in Finder, Explorer or your file manager |
| Workspace row → "…" menu | Hide workspace / Unhide workspace | Hides the workspace and every session it owns from the sidebar |
| Sidebar → View options | Show hidden workspaces (N) | Reveals hidden workspaces again so they can be restored |
| Session row → "…" menu | Move to Trash | Moves the session's files to $DSH_HOME/trash, restorable from Settings → Plugins → Trash |
Almost display-only by design:
- no archive, unarchive, rename, move or pin side effects beyond what a user action asks for;
- no changes to workspace records, session logs or the archive set;
- opening a folder is read-only: it launches the OS file manager and nothing else;
- moving a session to the trash never deletes it: the files are renamed into
$DSH_HOME/trash/sessions/and can be restored; - the only durable non-trash state is one small Host file
(
$DSH_HOME/storages/dsh-enhancer.json).
Install
dsh plugin --profile <profile> add @adamcjm/dsh-enhancer
Or wire it by hand in the profile's package.json:
{
"dependencies": {
"@adamcjm/dsh-enhancer": "^1.0.0"
},
"dsh": {
"profile": {
"bundles": ["…", "@adamcjm/dsh-enhancer"]
}
}
}
Restart the Host (or let the profile's live patch reload pick it up) and refresh the Web UI.
Local development
Point the profile at this checkout instead of the registry:
{
"dependencies": {
"@adamcjm/dsh-enhancer": "link:/absolute/path/to/dsh-enhancer"
},
"dsh": {
"profile": {
"bundles": ["…", "@adamcjm/dsh-enhancer"]
}
}
}
npm test runs both halves with zero dependencies: the browser half in a vm sandbox
with a fake DOM, the Host half against a temp DSH_HOME and Node-style request/response
fakes. The suite never launches the real file manager.
Usage
Open a workspace folder
Click the "…" button on any workspace row and choose Open folder. The Host resolves the directory from the workspace registry and launches:
| Platform | Command |
|---|---|
| macOS | /usr/bin/open <path> |
| Windows | explorer.exe <path> |
| Linux | xdg-open <path> |
The entry reports failures in place instead of dismissing the menu silently:
- Folder no longer exists — the registered directory is gone (
status()ismissing-dir); - Could not open — the launcher could not be spawned, or the platform is unsupported.
The page never sends a path. It sends only a workspace id, and the Host looks the directory
up itself, so a stale row can never make the Host open an arbitrary folder. The registered
path is the canonical fs.realpath of the directory at registration time, which means it is
unaffected by renaming the workspace (rename only changes the display title).
Hide and restore workspaces
- Workspace row → "…" menu → Hide workspace — the row and all of its sessions disappear. While hidden rows are visible again, the same entry reads Unhide workspace.
- Sidebar → View options → Show hidden workspaces (N) — a persisted switch that reveals every hidden workspace; the label carries the current hidden count.
Hidden ids live on the Host in $DSH_HOME/storages/dsh-enhancer.json. The browser keeps no
copy: it fetches the state once, then receives every change over an SSE stream
(/dsh-enhancer/stream), so Desktop and dsh web (two Host processes sharing one
$DSH_HOME) stay in sync without a refresh. Mutations travel as increments, so two clients
hiding different workspaces cannot overwrite each other.
Move a session to the trash
Session row → "…" menu → Move to Trash.
- A running session is refused: the dialog says so and offers only Close. Stop the session first.
- A session with child sessions (sub-agents) asks what to do:
- Delete only this session — the parent leaves, the children stay in place as orphans
(their
parentSessionnow points at a session that no longer exists); - Delete with N child sessions — the parent and all of its children move together, and restoring the parent restores them too.
- Delete only this session — the parent leaves, the children stay in place as orphans
(their
- A session whose files cannot be located is reported and nothing is touched — the plugin fails closed rather than guessing a path.
Files move to $DSH_HOME/trash/sessions/<timestamp>_<sessionId>/data/, beside a
manifest.json that records the title, workspace, cwd, original relative path, size and the
child entries created by the same deletion.
Restore from Settings → Plugins → Trash. The tab lists every deleted session with its title, workspace, age, size and child count. Tick the entries you want, then:
| Button | Scope | Confirmation |
|---|---|---|
| Restore (N) | the ticked entries only | none |
| Delete permanently (N) | the ticked entries only | yes, "cannot be recovered" |
| Empty trash (N) | the whole trash, ignores the selection | yes, "empties everything" |
Restoring a parent also restores the child entries created with it. Restored sessions are
re-attached to their original workspace when it still exists, otherwise re-grouped by their
cwd. Empty trash only removes $DSH_HOME/trash/sessions/* — it never touches DSH's own
sessions/ directory.
How it works
- Hiding never touches the DOM. The plugin wraps the
workspaces.listclient model (getSnapshot/subscribe) and projects a filtered snapshot, so the sidebar, its search results and the Hero workspace picker all hide the workspace from one place. Sessions belonging to a hidden workspace are unioned into a view-only archived set so the shipped grouping cannot trail them into "Ungrouped" — nothing is written to the archive. - Menu entries are DOM additions. The shipped Workspace row menu and View options menu
are hardcoded arrays with no slot in DSH 0.2.1-rc, so the plugin appends entries that clone
the shipped item's own classes. A
MutationObserverfinds the menu portal after it opens. The session menu entry and the trash tab are real slots (sidebar.workspaces.session.menu.item,settings.plugins.tab,shell.overlay), not DOM injections. - The Host half owns the durable state and the
open-workspaceaction. Opening is a detachedspawnwithstdio: 'ignore', so the HTTP request resolves as soon as the launcher exists. - Trashing never edits DSH's storage directly. The Host first drops the durable
references through the public registry API (
detachSession,unarchiveSession,unpinSession), then renames the session directory into the trash and writes the manifest. A session is located by matching the<sessionId>entry name inside$DSH_HOME/sessions/<group>/, so a change in DSH's path encoding or a switch to a single-file layout fails closed instead of deleting the wrong thing.
Upgrading from @adamcjm/dsh-workspace-visibility
This package replaces it. The hidden-workspace feature is identical, and the first start adopts the old state file once, so your hidden list survives the upgrade.
dsh plugin --profile <profile> remove @adamcjm/dsh-workspace-visibility
dsh plugin --profile <profile> add @adamcjm/dsh-enhancer
Migration details:
$DSH_HOME/storages/workspace-visibility.jsonis read once, copied todsh-enhancer.json, and left in place so a rollback still works.- Do not keep both packages enabled at the same time: each one injects its own menu entries, so the workspace menu would show duplicates.
Compatibility
- DSH 0.2.1-rc or newer (
workspaceRegistryHost service,workspaces.listclient model, locale service,webServerroute carrier). - Node.js 20+ in the Host process.
- macOS, Windows and Linux. "Open folder" requires a desktop session; on a headless Host the
route answers with
open-failed. - The Host that serves your page is the one that opens the folder. With a remote Host, the file manager opens on the remote machine (or fails), never on your laptop.
License
MIT
Plugins relacionados
dsh-web (dsh-task-board)
zhu1090093659/dsh-web
dsh-web (dsh-web-all)
zhu1090093659/dsh-web
dsh-web-ui (dsh-task-board)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-web-ui-all)
zhu1090093659/dsh-web-ui