@lucagiftzek/dsh-workspace-rail
Replaces the DSH sidebar list with a workspace rail: pinned chats and folders, projects that are folders with their own AGENTS.md and files, a virtualized Recents list ordered by the last finished turn, a project_search tool, unread markers, a collapsed icon column with an unread count and a live br
Install
dsh plugin --profile web add @lucagiftzek/dsh-workspace-rail
Sandbox test
This plugin has not been tested yet. Submit a test →
README
dsh-workspace-rail

A workspace-first sidebar for DSH: pinned chats, projects as folders, live Recents and unread markers.
dsh plugin --profile web add @lucagiftzek/dsh-workspace-rail # or from GitHub: dsh plugin --profile web add github:lucagiftzek/dsh-workspace-rail # then restart dsh web
<sub>Screenshot from a demo DSH instance with sample data.</sub>
A workspace-first sidebar rail for the DeepSeek Harness (DSH) web GUI: Pinned
chats (folders included), Projects (isolated workspace folders with their own
instructions and files), a virtualized Recents list ordered by the last
finished turn, graded transcript search, unread markers and a live browser tab
title.
Runs on DSH 0.2.x (tested on 0.2.1) and on DSH 0.1.5 with the same build.
Install
Install from npm: dsh plugin --profile web add @lucagiftzek/dsh-workspace-rail, or from GitHub: dsh plugin --profile web add github:lucagiftzek/dsh-workspace-rail.
dsh plugin --profile web add @lucagiftzek/dsh-workspace-rail # or from GitHub: dsh plugin --profile web add github:lucagiftzek/dsh-workspace-rail
The package declares dsh.bundle, so dsh plugin add lists it in the
profile bundles; restart dsh web to load the host half. To work on a
checkout instead:
git clone https://github.com/lucagiftzek/dsh-workspace-rail cd dsh-workspace-rail && npm install && npm run build dsh plugin --profile web add link:$PWD
lib/ is committed, so a plain install needs no build step.
Options
Row options go in the - id: workspace-rail row of your profile
cordis.patch.yml, under config:.
Option · Default · Meaning
enableRail · true · Mount the rail in the web GUI.
stripeEdge · right · Edge of the colour stripe on chat, folder and project rows.
recentsMaxRows · 5000 · Cap on rows kept in Recents.
projectsRoot · ~/dsh-projects · Where per-project folders are created.
trustedHosts · [] · Host names (besides loopback) the rail API accepts. Empty means the authorities DSH itself trusts: every --trusted-host value of the dsh web command line, plus the comma-separated DSH_WORKSPACE_RAIL_TRUSTED_HOSTS environment variable.
enablePointerHealth · true · Check that linked project files still exist.
enableWindowsIndex · false · DSH 0.1.5 only: transcript-window bridge for search.
If you serve DSH under a public host name behind a reverse proxy, you already
start it with dsh web --trusted-host app.example.com (the core's own API
fence needs it), and the rail picks that up with no extra setting.
How it is built
Dual-face plugin (host and browser), the same harness contract as
dsh-session-pin:
src/index.ts: host face. Serves the rail's own API and file store; on
DSH 0.1.5 it also registers the workspace-rail settings namespace (see
"DSH versions").
src/client.ts: browser face. Catalog sync (sessions and workspaces
snapshots), the rail panel (vanilla DOM, outside React's tree), virtualized
Recents.
src/scoring.ts: pure 4-tier graded search scoring (title x40, doc
names and tags x15, first 3 messages x8, last 3 messages x4, 14-day recency
decay, pinned x1.2 boost).
Placement
The rail is the sidebar list: the browser face registers the
sidebar.workspaces seat at priority -2, one below dsh-metafolder-plugin
(-1), which is one below the shipped browser (0). The header's
Rail | Folders switch unregisters the seat to reveal the folder view
underneath (nothing is hidden with CSS); a Rail button in
sidebar.footer.action brings it back. The choice is per browser
(localStorage['dsh.workspace-rail.view']). Hosts without a slot registry
fall back to a floating panel.
The rail hides the "Pinned sessions" footer button of dsh-session-pin, since
the rail's PINNED section lists the same pins; pinning itself is untouched.
One CSS rule in src/rail-style.ts (PIN_FOOTER); delete it to bring the
button back.
Colours come from the host's --dsw-alias-* tokens, so the rail follows
light and dark mode and any theme on top; a theme plugin can also set
--tz-* variables (accents, display font, radius, shadows). Subagent
transcripts are excluded from Recents; rows show a compact age and open the
chat on click.
Rename: triple-click a chat title, or the row menu, Rename. Enter saves,
Esc cancels, clicking away saves. It goes through the host
(ctx.sessions.binding(id).session.rename), which also pins the title
against automatic regeneration.
Projects
Clicking a project opens its view inside the rail: Chats first (same rows
as Recents: open, rename, age; row menu, Remove from project), with
+ New chat (created and filed in the project, then opened) and
Add chats... (a searchable picker). Files below: paste a path or URL
and press Enter, or drop text paths; name and kind are inferred
(src/files.ts). Clicking a file opens it in dsh-better-sidebar's editor when
that plugin is installed (optional ctx.inject(['betterSidebar'])); links
open in a new tab. Files the server cannot find are marked and can be removed
in one click. Files are links only: nothing is copied.
Moves, removals and deletes apply immediately with an Undo toast.
Projects are folders
Each project gets ~/dsh-projects/<name>-<id>/ (option projectsRoot).
+ New chat registers that folder as a DSH workspace (titled like the
project) and opens its chat, the same path as DSH's New Session. DSH's own
instructions loader then applies the folder's AGENTS.md, which the rail
writes from the project's Instructions, Project memory (the assistant
keeps PROJECT-MEMORY.md) and Answer from project files only settings.
Uploads land in the folder, so the assista
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::3,最后更新 2026-11-01