jinhuang712
dsh-session-link
Link and read DSH sessions: one-click @session-id reference, an @ mention menu by title, and a session_read tool that projects any session to readable text. DeepSeek Harness plugin.
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-session-link
Pass context between DSH sessions without the download–transfer–unzip dance.
dsh-session-link is a plugin for DeepSeek Harness. One click in the session header copies a reference to the current session; any other session picks it up and reads the whole conversation back as clean user:/assistant: text.
| Copy | Mention | Read |
|---|---|---|
Header button → @session-<uuid> on the clipboard | @ menu lists sessions by title | session_read projects the conversation |
When you'd want this
- Session A figured something out; session B needs it. Without this, you export the session log, move the file, unzip it, and read zstd JSONL by hand. Here, A's header button copies
@session-<uuid>, you paste it into B, and the model callssession_read— done. - The reference stays a first-class object.
@session-<uuid>is all ASCII, so it renders as a colored chip in the composer and in sent bubbles — not as a blob of text you have to explain. - What comes back is readable, not raw.
session_readprojects the event stream to conversation rows and skips chunk/tool/reasoning noise; a 7MB log typically reads back as ~60KB of dialogue.
What you get
- Header action「🔗 复制 Session ID」 — one click copies the current session's
@session-<uuid>. Pure clipboard work; no host round-trip. @mention sourcesession— typing@in the composer lists every local session by title (searchable by title or id); picking one inserts the reference as a chip.- Chip repaint —
@session-…references show blue-on-white in sent bubbles, scoped precisely so other@mentions are never touched. session_readtool — the model resolves@session-<uuid>, adsh-session:URI, or@titleand receives{ sessionId, title, cwd, logPath, seqRange, transcript, truncated }. Read-only, live-first, works for sandboxed sessions too.
Preview
Copy — one click in the session header puts @session-<uuid> on the clipboard:
Paste — the reference lands in another session's composer as a chip, ready to send and read:
Install
Pinned to a release — build artifacts are committed, so there is nothing to build and no registry involved:
dsh plugin --profile web add "github:jinhuang712/dsh-session-link#v0.1.0"
# restart dsh web, then refresh the page
Or track main to pick up unreleased commits:
dsh plugin --profile web add "github:jinhuang712/dsh-session-link#main"
Or from a local checkout, linked so edits show up on refresh:
git clone https://github.com/jinhuang712/dsh-session-link.git
dsh plugin --profile web add "link:$PWD/dsh-session-link"
If your dsh profile directory is a pnpm workspace, pnpm asks for -w before
touching its root — pass it through: dsh plugin --profile web add -w ….
After install (and one restart), the header button, the @ menu group and
the session_read tool are available permanently in every session. The
companion skill dsh-session-link registers with the install
(dsh.skills declaration) and teaches the model when and how to read a
reference.
Usage
Share a session: open it, click「🔗 复制 Session ID」in the header, paste into any other session's composer — the reference appears as a chip — and send.
Pick a session without switching: type @ in the composer, find the
session by title in the session group, insert it.
Read a reference: the model calls
session_read({ "link": "@session-7fc2d98e-…" })
| Input | Behaviour |
|---|---|
@session-<uuid> | Exact, recommended — what the button produces |
dsh-session:<b64> | The URI form from older link payloads |
@title | Exact title match; a miss or ambiguity returns candidates/ids — retry by id |
Optional: maxChars (projection budget, default 64000), truncate
("tail" keeps the most recent rows — default; "head" keeps the earliest),
raw (debug: first 200000 chars of the original JSONL).
Boundaries (measured, not guessed)
- Chinese titles (
@分析…) don't chip — the shipped@-mention regex has no/uflag. The copy format is the id, never the title, precisely for this. @titleresolution needs the host'ssessionQuerytitle snapshots; when unavailable the tool says so and points at the id form.- Reading is read-only and live-first:
sessionQuery.readSessionreflects a running session at its current state; the on-disk log path is resolved for reference (logPath) but never written.
Architecture
- Host half (
lib/index.mjs): Cordis entrydefineToolregisterssession_read;executeparses the reference, resolves titles viasessionQuery, projects the JSONL event stream, and caps it by budget- no webServer routes — the copy button is pure clipboard
- Client half (
src/→lib/client.js):__ModuleLoader__.loadbundleruntime.jsbinds the host's React from the loader'srequire— never bundled, so the plugin shares the host's React instancecopy-button.jsthe header action;mention.jsthe@session source;chips.jsthe MutationObserver repaint
- Skill (
skills/dsh-session-link/SKILL.md): usage guide shipped with the install
Develop
lib/client.js and its source map are build output, committed so the GitHub
install stays one line. Edit src/, then:
pnpm install
pnpm build # esbuild src/index.js -> lib/client.js + lib/client.js.map
Verify
It loaded at all:
__DSH_BOOT__includes thedsh-session-linkclient row, and/plugins/dsh-session-link/client.jsreturns 200cordis_inspect_query(Tool.listTools) listssession_read
Then exercise the loop:
| Look at | Expect |
|---|---|
| the session header | the「🔗 复制 Session ID」button; clicking flips it to「✓ 已复制」 and the clipboard holds @session-<uuid> |
| the composer | pasting the reference shows a chip; typing @ offers the session group by title |
| a sent message | the reference renders as a blue chip, other @ mentions unchanged |
session_read on the pasted reference | returns the session's title/cwd and a user:/assistant: transcript |
Uninstall
- Remove the
dsh-session-linkinsert row from the web profile'scordis.patch.yml - Remove the
dsh-session-linkdependency from the web profile'sdsh.profile.bundlesand runpnpm remove
License
MIT