Pin and unpin sessions to the top of the Web sidebar with a dedicated pinned panel, archive section, and native three-dot menu integration.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:fallow5/dsh-pin-sessions
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
A DeepSeek Harness (DSH) web plugin that lets users pin sessions to a dedicated sidebar section for quick access to recurring workflows, and provides an archive-sessions settings panel with batch delete, restore, workspace grouping, and pagination.
Features
- Pin / Unpin sessions — Pin sessions to the top of the sidebar, hidden from their workspace browser
- Archive panel — Settings panel for managing archived sessions with batch delete, per-row restore, workspace grouping, and 20-per-page pagination
- Context menu integration — Right-click pin/unpin via
@baihejiangnan/dsh-session-context-menu - Pin = Archive — Pinning archives the session from the workspace browser; unpinning restores it
Architecture
Standard DSH plugin split: host half (Cordis loader entry + TYPERT manifest) + client half (window.__ModuleLoader__.load wrapper).
Host Side
| File | Responsibility |
|---|---|
src/index.ts |
Opens pin_sessions storage domain, creates PinsStore + PinsRuntime |
src/runtime.ts |
PinsRuntime extends TypertRemoteService — 8 TYPERT methods |
src/typert.ts |
Host TYPERT manifest (must match client) |
src/store.ts |
Durable pin store over the pin_sessions domain |
src/domain.ts |
pin_sessions domain declaration |
src/schemas.ts |
Zod schemas for pin records |
TYPERT Methods
list, pin, unpin, toggle, isPinned, deleteSessions, listArchived, unarchiveSession
Key Design: Pin = Archive
Pinning calls workspaceRegistry.archiveSession(sessionId) to hide the session from the workspace browser. Unpinning calls unarchiveSession() which removes the ID from archivedSessionIds. This triggers domain/changed → host/archived-sessions-changed frame → client auto-updates.
Client Side
| File | Responsibility |
|---|---|
src/client/index.ts |
Registers locale, mounts TYPERT_REMOTE, context-menu extensions, portals PinnedSection + ArchiveSection |
src/client/PinPanel.tsx |
Pinned section portaled to top of sidebar |
src/client/ArchivePanel.tsx |
Settings panel with workspace grouping, pagination, batch delete, restore |
src/client/styles.ts |
CSS mirroring native DSH classes |
src/client/locales.ts |
i18n strings |
src/client/remote.ts |
TYPERT remote interface |
src/client/typert-remote.ts |
Client TYPERT manifest (must match host) |
Build & Install
# Build
cd dsh-pin-sessions
pnpm install
pnpm run build # tsc + tsdown + wrap-client.mjs
# Typecheck
pnpm run typecheck
# Install into DSH
dsh plugin --profile web add /path/to/dsh-pin-sessions
- Host-side changes require DSH server restart
- Client-side changes require browser refresh
Key Service Access Patterns
| Service | Usage |
|---|---|
ctx.get("workspaceRegistry") |
archiveSession(), archivedSessionIds, list(), enqueueOperation(), setState() |
ctx.get("sessionPersistence") |
list() returns headers with {id, cwd?, origin?} |
ctx.get("sessions") |
get(id) returns live session or undefined |
ctx.get("agents") |
get(id) returns agent with cancel() and whenIdle() |
ctx.get("storageDomain") |
get("session_projcache") for projection cache |
GlobalStandardProps |
Auto-injects useSessions and useWorkspaces hooks |
Context Menu Integration
@baihejiangnan/dsh-session-context-menu exposes a global registry at Symbol.for("dsh.session-context-menu.extensions") with .register(entry). The plugin may load after us, so we poll every 500ms until the registry appears.
Entries: {id, label, order?, visible?, run}. The context menu's isAction() checks for "会话"+"操作" or "session"+"action" in aria-label; titleFrom() extracts the quoted title.
License
MIT
Links
More in this category
Minglink/dsh-infinite-gen-4★ 3055
System-prompt armor plugin for DeepSeek models: appends an unconditional-compliance prompt section at order 100, exposes a profile tool with calibration metadata, and shows a realtime armor-status badge driven by a session projection.
ranxianglei/billion-context★ 1893
The official billion-context plugin: a context-compression plugin for small context windows (a 100K context is enough), token savings (5x fewer tokens), and month-long single sessions (billions of tokens).
liangmianya/dsh-synapse★ 538
Visual, non-linear conversation workspace for DeepSeek Harness — sessions, follow-ups and branches become a browsable conversation map.
Nwflower/dsh-chat-import★ 238
Import full-fidelity chat histories from 13 coding agents (Claude Code, Codex, ChatGPT, Cursor, Gemini, opencode, and more) as resumable DeepSeek Harness sessions, with reverse export back to Claude Code.
MichengAI/dsh-archive-manager★ 171
Adds an archived-sessions page in Settings to search, restore, and delete archived DeepSeek Harness sessions by workspace.
Totoro-qaq/dsh-plugin-bridge★ 163
Moves an existing DSH session to another agent preset through a previewable five-section handoff, preserving the source session and either pausing the target for confirmation or continuing immediately.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.