better-session-management
中文 | English
  
A DSH plugin bundle for DeepSeek Harness (DSH) that adds a chain conversation view, sub-sessions, /btw one-shot Q&A, and a workspace/session tree — all built on session primitives — so long conversations can branch and interject in a controlled way.
> Published in the official DSH packaging model: install with dsh plugin add — no dynamic deployment required. The repository also keeps the dynamic-plugin sources (src/) for development.
Features
🔗 Chain view (plugin chains)

- A new "Chain View" conversation tab: instructions → plugin chains (thinking / tool calls / tool outputs) → assistant feedback, grouped into bubbles.
- Expandable step boxes show call arguments, tool output and errors; bubbles collapse to their final feedback.
- "Load earlier" pagination reuses the native conversation paging and keeps your reading position; opening a session jumps to the end.
- Product-aligned Markdown rendering (headings, tables, lists, quotes) with theme variables; code blocks render as an independent rounded "code window" — a line-number column separated from the code by a divider, with long lines scrolling horizontally instead of wrapping.
- User instruction bubbles also render Markdown while preserving their original line breaks.
🌿 Sub-sessions
- Create a sub-session at any turn boundary: it inherits the parent's context up to that boundary (lineage persisted in the session header), then works independently.
- Two inheritance modes (settings, default "Summary quick-create"):
- Summary quick-create (window): seeds from the parent's latest 24-turn transcript (millisecond creation; earlier history appears as a summary). - Full inherit (full): copies all history before the boundary (same cost as forking).
- Entry points: the "create sub-session" icon on assistant messages, the "Branch / Create sub-session" buttons on the feedback bar, and the model tool
bsm_create_sub. - The new sub-session opens automatically; a card appears at the tail of the parent turn, and the sub-session nests under its parent in the sidebar.
- Sub-sessions are created as ordinary sessions (no subagent origin): they never occupy the "subagent" badge, never trigger automatic context injection, and never hit the subagent-routing fence.
- "Compress & inject into parent": inside a sub-session, compress its contents with three templates (brief summary / detailed minutes / conclusions+actions) and quietly inject into the parent (no automatic turn).
💬 btw (by the way)

/btw <question>starts a one-shot read-only Q&A: exactly one question, everything is torn down immediately after answering, and only a card (question + answer + elapsed time) remains in the parent conversation.- Read-only tool allow-list:
read/read_image/glob/grep/web_search/skill— no file writes, no commands, no sub-agents. - The answer is never auto-injected into the parent (no settlement notices, no wakeups). To keep working on it, use "Create sub-session" on the card — the full btw transcript (question, tool process, answer) migrates into the new sub-session — or "Send to parent" for a manual compressed injection.
- "btw thinking depth" setting: Low (off, fastest) / Medium (high, standard, default) / High (max, deepest) — controls reasoning length and latency per question.
🗂 Session sidebar (workspace > session > sub-session)

- The sidebar becomes a three-level tree: workspace folders → sessions (including branches) → sub-sessions; sessions are indented one level under their folder, sub-sessions one more level with a
↳prefix. - The ▸/▾ arrow only collapses/expands; clicking the title opens the session; hover to rename/delete.
- Delete = durable archive: the live agent is disposed and the session is hidden from every list (survives plugin updates and restarts; DSH has no physical-delete API, so the on-disk log is retained but invisible).
- Deleting a workspace archives all its sessions; sessions outside any workspace are grouped into synthetic folders by
cwdand always stay visible. - btw sessions never appear in any session list.
⚙️ More
- Feedback bar: Copy / Branch / Create sub-session / 👍 / 👎 (integrated with native feedback).
- Settings page: bubble layout, chain-box default collapse, highlighted feedback, Markdown rendering, sub-session inheritance mode, btw thinking depth, display width.
- Theme-variable-aligned styles; light and dark themes adapt automatically.
Design principles
- Built on session primitives: a sub-session is a real session fork (durable lineage, independently continuable), not a sub-agent wrapper; it never reports back to the parent on its own and never triggers automatic context injection or parent auto-execution.
- Explicit over automatic: every parent injection is user-triggered; btw is one-shot with no settlement notices.
- No invasive side effects: the branch button uses its own creation path instead of the official fork RPC; sub-sessions are created through the untraced original agent registry (
owner=undefined), matching official fork semantics.
Repository layout
better-session-management/
├── package.json # dsh.bundle manifest (+ dsh.client browser-half declaration)
├── cordis.patch.yml # bundle layer: mounts the Host half
├── index.js # Host half (sub-session/btw services, Typert Remote RPC, model tool)
├── client.js # Client half (chain view, cards, sidebar, settings; module-loader format)
├── src/ # Dynamic-plugin source mirror (for development; bundles are generated)
│ ├── host.js # Dynamic Host (harness RPC)
│ ├── client2.template.js # Dynamic Client template (__ICONS_JSON__ placeholder)
│ └── icons.json # IconPark icon catalog (30 icons, Apache-2.0)
├── scripts/
│ ├── build-client.cjs # Dependency-free dynamic client build
│ └── build-bundle.cjs # Bundle generator (src/host.js + dist client -> index.js / client.js)
├── asset/ # Screenshots (repository README only; not shipped in the npm package)
├── README.md / README_EN.mdInstallation
> Requires the DSH dsh CLI (official docs: Package and install a plugin).
Option 1: install from GitHub (recommended)
--profile names the installation target: a profile is one runnable composition (stored under $DSH_HOME/profiles/<name>/, with any name you choose — e.g. demo, work, default). Example using a profile named demo:
dsh plugin --profile demo add github:boyun-zhang/better-session-management
dsh --profile demoThis plugin is plain JavaScript with no build step, so no extra allowance is normally needed; if pnpm asks for allowBuilds, follow the printed hint and re-run the add.
Option 2: local checkout / npm / tarball
dsh plugin --profile demo add ./better-session-management # local checkout
# or publish to npm / pnpm pack, then:
# dsh plugin --profile demo add <package-or-./xxx.tgz>After installation, dsh --profile demo --dump-config should show the # == dsh-better-session-management layer.
Development / hot-patch: dynamic deployment (optional)
The dynamic-plugin sources are kept for hot experiments without a service restart (inside a DSH session):
node scripts/build-client.cjs # -> dist/client.chunked.jsThen use cordis_define (plugin.kind: "new", code.host = src/host.js, code.client = dist/client.chunked.js) and cordis_run; update with cordis_define (kind: "existing") + cordis_run (update). Dynamic plugins are process-local and must be redeployed after a DSH restart.
Usage cheat sheet
| Action | How |
|---|---|
| Create sub-session (quick-create / full) | Assistant-message icon / feedback-bar buttons / model tool bsm_create_sub |
| Branch (full inherit) | "Branch" button on the feedback bar (own creation path, not the official fork RPC) |
| btw one-shot Q&A | /btw <question> in the input |
| View sub-sessions / btws | Turn-tail cards in the parent, sidebar tree |
| Open a sub-session | "Open sub-session" on its card, or click its sidebar title |
| Compress & inject into parent | Header utility inside the sub-session (three templates); btw card "Send to parent" |
| Rename / delete | Hover a sidebar row: ✏️ rename / 🗑 delete (archive) |
| Settings | Settings → Session management |
Known limitations
- btw records are in-process one-shot records (matching their one-question semantics); the bundle form persists with the profile, while the dynamic form must be redeployed after a DSH restart.
- DSH has no physical session deletion: "delete" = live-agent disposal + durable archive-hide; the on-disk log is retained but invisible everywhere.
- The sidebar replaces the native workspace browser (workspace create/switch dialogs are replaced; "New session" still works).
- Renaming requires a live session: open a cold session before renaming it.
Credits
- Icons: IconPark (ByteDance open-source icon library, Apache-2.0).
- Session and agent foundations by DeepSeek Harness.