
Security News
vlt 1.5.0 Adds Agent Skills Management
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.
dsh-devpanel
Advanced tools
Maintenance mode. DeepSeek Harness 0.2 now ships built-in equivalents for most of what this plugin provides, so
dsh-devpanelis no longer actively developed — only critical fixes will be applied. Existing installs keep working; new users should prefer the official features below.
Plugin capability Official replacement (dsh 0.2+) Terminal panel — multi-tab PTY @deepseek-ai/dsh-client-ui-sidebar-terminal— interactive shell tabs in the right Sidebar (xterm.js, reconnect, shell picker)Usage stats panel @deepseek-ai/dsh-session-statsplus the composer stats pills / per-turn usage panel in@deepseek-ai/dsh-client-ui-chatAI-output file sidebar (no full equivalent) — @deepseek-ai/dsh-client-ui-deliverablesshows per-turn changed files and@deepseek-ai/dsh-client-ui-sidebar-filesbrowses the whole workspace, but neither lists every file a session's AI produced. This surface remains the plugin's only unique value.
A developer toolkit for the DeepSeek Harness (DSH) web console: a real multi-tab PTY terminal plus an AI-output file browser.
dsh-devpanel is a plugin for the DeepSeek Harness that brings three things into the browser console:
The terminal and file surfaces are driven by TerminalPanelService; the usage panel by UsageService. Both wrap harness primitives (ctx.subprocess.spawnTerminal for the PTY, the session/event firehose + terminal events for usage) and are exposed to the browser over the Typert Remote boundary — no harness changes required. The Gateway auto-discovers both services through their typertRemote bindings.
$SHELL, falling back to /bin/sh) in the session's working directory, wrapped so it exports a real TERM (the harness forks PTYs with TERM=dumb, which breaks clear and prompt glyphs). Colored output from git, ls, and prompts renders like a native terminal.+ new tab, per-tab close, and a close button that ends every session. Closing the last tab closes the panel; reopening spawns a fresh default tab.Cmd/Ctrl+Shift+V pastes, clear works, and multi-byte UTF-8 output survives arbitrary byte-chunk splits without ? mojibake.SIGINT / SIGTERM / SIGKILL / SIGTSTP / SIGHUP to the verified foreground process group, or terminate the captured process tree with a 2-second grace period.read for incremental output; the host keeps a per-session scrollback (1 MB tail) so long output stays browsable without unbounded memory.write/edit tool calls produced (from diff views and raw args, de-duplicated in first-seen order) plus shell-command products (paths extracted from terminal-card commands/output, verified on the host by existence + mtime window), reads them through the remote, and renders them as image, Markdown, highlighted code, or plain text, with a fullscreen mode.session/event firehose (tokens, calls, messages, per-model share, response duration, reasoning effort) and the terminal side (sessions, submitted commands, wall time) into overview cards, a daily dual-series trend, a yearly activity heatmap, paginated call + terminal detail tables, and CSV/JSON export. Historical chat sessions are replayed best-effort through ctx.sessionQuery; the index is persisted (debounced, atomic) under DSH_HOME/devpanel/usage-v1.json.toolkit locale namespace.The plugin is a two-face bundle, mirroring the harness client preset:
┌─────────────────────────── browser (web platform) ───────────────────────────┐
│ src/client/ │
│ index.ts plugin body: mounts the Remote, registers slots │
│ remote.ts TYPERT_REMOTE contribution + ctx.remote typing │
│ ConsoleHeaderActions three header icons (terminal + sidebar + usage) │
│ ConsoleSidebar AI-output file viewer (right details column) │
│ TerminateDialog multi-tab xterm dialog (composer dock) │
│ UsagePanel dual-dimension usage dashboard (modal overlay) │
│ console-store.ts shared sidebar/dialog/usage open state │
│ console.css.ts injected <style> tag (no CSS pipeline) │
│ locales.ts zh / en dictionaries (namespace 'toolkit') │
└───────────────▲──────────────────────────────────────────────────────────────┘
│ Typert Remote (JSON wire, zod-strict codecs)
┌───────────────┴──────────────────────────── host (node) ────────────────────┐
│ src/index.ts TerminalPanelService (TypertRemoteService) │
│ src/usage.ts UsageService (TypertRemoteService, usagePanel ns) │
│ src/typert.host.ts TYPERT manifest for the typert-loader │
│ src/types.ts terminal wire vocabulary (pure data) │
│ src/usage-types.ts usage wire vocabulary (pure data) │
│ src/usage-schemas.ts usage zod codecs (pure data) │
└──────────────────────────────────────────────────────────────────────────────┘
Host half — TerminalPanelService (src/index.ts) extends TypertRemoteService and owns an owner-free session map. Each session wraps a SubprocessTerminalHandle from ctx.subprocess.spawnTerminal with a streaming TextDecoder (so a multi-byte char straddling two output chunks stays intact), a bounded scrollback buffer, and a read cursor for delta consumption. It emits terminal lifecycle events (devpanel/terminal/spawn|command|exit|dispose) on the shared ctx. Session lifetimes follow the plugin: the constructor registers a fiber effect that terminates every live PTY on dispose. UsageService (src/usage.ts) extends TypertRemoteService under the usagePanel namespace: it folds the live session/event firehose into per-chat-session AI activity records, folds the terminal events into per-terminal-session records, persists a debounced atomic index cache under DSH_HOME/devpanel/usage-v1.json, replays historical chat sessions best-effort through ctx.sessionQuery, and serves aggregated snapshots, call/terminal detail pages, and CSV/JSON exports. The plugin's apply wires UsageService first (so it subscribes before any terminal can spawn), then TerminalPanelService.
Client half (src/client/) — apply mounts the TYPERT_REMOTE contribution first (the dialog needs the namespace mounted before it injects it), then contributes three slots over one shared console store:
conversation.session.header.utilities (id toolkit-actions, order 10) — the terminal-dialog, sidebar, and usage-stats toggle icons;details (priority -10) — the AI-output file viewer; a lower priority shadows the harness DetailsPanel (lowest renders, so -10 wins) and drives the right column through ctx.layout;conversation.composer.dock (id toolkit-dialog, order 10) — the multi-tab terminal dialog.The usage-stats toggle renders UsagePanel as a fixed modal overlay; it calls the usagePanel Remote face for snapshots, detail pages, and exports.
Because the plugin itself mounts the remote.terminalPanel and remote.usagePanel namespaces, it reads the live instances out of the service store (ctx.get) instead of declaring a static inject entry, avoiding a self-wait deadlock.
Wire vocabulary — src/types.ts (terminal) and src/usage-types.ts (usage) hold the JSON-safe shapes crossing the Remote boundary, shared by the host encode and the client descriptors; src/usage-schemas.ts adds the usage zod codecs. src/typert.host.ts ships a strict hand-written manifest so the endpoints are known to the gateway regardless of module identity (out-of-tree bundles would otherwise 404 on the runtime reflection fallback).
dsh-devpanel is developed as a workspace package next to the harness source. Requirements:
^22.19.0 || >=24.0.0dsh-v0.2.0 or newer — the right-Sidebar tab system and several client/subprocess interfaces this plugin targets exist only from 0.2../deepseek-harness (see pnpm-workspace.yaml)# from the workspace root
pnpm install
pnpm --filter dsh-devpanel build
Minimum harness version. 0.2 removed the client
detailsseat and thectx.layoutopen/close actions this plugin used to occupy: the right column now belongs to@deepseek-ai/dsh-client-ui-sidebar-right, and the plugin re-enters as a right-Sidebar tab type (the type registers intoctx.sidebarRightTabs, the component into the keyedsidebar.right.pane.tabseat, and the column is driven throughctx.sidebarRight). The same release changed the other interfaces this plugin depends on: the session-list snapshot no longer carriescurrent(the current Session comes fromctx.uiSession.adapter.current), the terminal spawn spec requiresterminalType(the caller declares the TERM emulation, replacing 0.1's hardcodedTERM=dumb), the Typert codec materializes through a lazycreate()instead ofschema, andDiffBlockLabelsgained the code-toolbar labels. Older harness releases —dsh-v0.1.*, including everything before thesession/end-seedrework — are not supported: the file sidebar never mounts on those runtimes, and the terminal panel cannot get a real TERM.
The plugin contributes a bundle row via cordis.patch.yml ({ id: toolkit, name: dsh-devpanel }); enable it in a harness profile that lists this bundle. The published package exposes four entry points:
| Export | Path | Purpose |
|---|---|---|
. | lib/index.js | host service entry (default export TerminalPanelService) |
./client | lib/client.js | browser CJS closure-factory bundle |
./types | lib/types/types.js | shared wire types |
./typert | lib/typert.host.js | host-face Typert manifest |
Click the terminal icon (>_) in the session header to toggle the terminal dialog docked under the composer. The first open spawns a default tab in the session's working directory (the user home when the session has none). Use the tab bar to switch between sessions, + to open a new tab, and the × on each tab to close it — closing the last tab closes the whole panel, and reopening starts a fresh default tab.
Input is delivered keystroke-by-keystroke into the PTY (Enter included, no newline conversion), so interactive programs (vim, top, REPLs) behave as expected. Select text to copy it; press Cmd/Ctrl+Shift+V to paste. The shell badge next to the tab bar shows the running shell program (e.g. zsh).
Click the panel icon in the session header to toggle the file sidebar in the right details column. It lists every file the current session's write / edit tool calls produced (from diff views and raw args, in first-seen order, de-duplicated), PLUS files the session's shell commands created or modified: file paths are extracted from the terminal-card command lines and captured output, then verified against the host filesystem — a candidate enters the list only when the file exists and its mtime falls inside the producing tool call's window. Click a file to read it through the host:
.md / .mdx renders as Markdown;png, jpg, gif, webp, avif, svg, tiff, heic, …) render inline as data URLs;mp3, wav, ogg, flac, …) and video (mp4, webm, mov, …) play inline;Use the ⛶ button to open the current file fullscreen; the × button closes the sidebar.
Click the bar-chart icon in the session header to open the usage dashboard as a modal overlay (Esc or × closes it). The toolbar lets you pick a range (last 7 / 30 / 90 days), a lineage scope (all / main tasks only / subtasks only), and a workspace (session cwd). The panel shows:
Data is collected from the moment the plugin loads: live AI activity comes from the session/event firehose, terminal activity from the terminal panel's own events, and historical chat sessions are replayed on startup (best-effort, via ctx.sessionQuery). The index is persisted under DSH_HOME/devpanel/usage-v1.json.
The terminalPanel namespace is available on the client as ctx.remote.terminalPanel.*. All methods take an optional trailing AbortSignal and return a RemoteResult<T> ({ ok: true, value } or { ok: false, error }).
| Method | Parameters | Result | Description |
|---|---|---|---|
spawn | { argv, cwd, rows, cols, name? } | { id, pid, shell } | Spawn one PTY session. Empty argv resolves the system login shell with a real TERM; empty or ~ cwd lands in the user home. |
write | id, text, submit | { ok: true } | Write text to the terminal; submit appends the Enter sequence (\r). |
read | id | { delta, status } | Consume the output produced since the previous read, plus the current session status. |
signal | id, sig | { delivered: true, targetPgid } | Deliver SIGINT/SIGTERM/SIGKILL/SIGTSTP/SIGHUP to the verified foreground process group. |
terminate | id | { ok: true } | Terminate the captured process tree (2 s grace) and await quiescence; the record stays listed as exited. |
list | — | { sessions } | List live sessions in creation order. |
dispose | id | { ok: true } | Remove the session record, terminating it first if still running; unknown ids are idempotently ok. |
readFile | path, cwd? | { path, content, kind, dataUrl?, size? } | Read one file for the viewer. ~-prefixed and relative paths resolve against cwd (default: host cwd); image/pdf/audio/video return a base64 data URL, unknown binary files return only their byte size (kind: 'binary'). |
statFile | path, cwd? | { path, exists, kind?, mtimeMs?, size? } | Probe one path's existence and metadata (the shell-artifact verifier); a missing or unresolvable target reports exists: false instead of throwing. |
Session status is { kind: 'running' } or { kind: 'exited', exitCode, signal }. The full TypeScript vocabulary lives in src/types.ts and is re-exported from the package's ./types entry.
The usagePanel namespace is available on the client as ctx.remote.usagePanel.*, with the same RemoteResult<T> contract.
| Method | Parameters | Result | Description |
|---|---|---|---|
snapshot | { from, to, timeZone, scope, workspace? } | UsageSnapshot | Aggregated AI + terminal figures for a date range (totals, day rows, model share, workspaces, index health). |
calls | { from, to, timeZone, scope, workspace?, model?, provider?, minInputTokens?, minOutputTokens?, page, pageSize } | UsageCallsPage | Paginated assistant-call detail rows, newest first. |
terminals | { from, to, timeZone, workspace?, page, pageSize } | UsageTerminalsPage | Paginated terminal-session detail rows, newest first. |
exportCsv | { from, to, timeZone, scope, workspace? } | { filename, body } | CSV export of the merged day rows. |
exportJson | { from, to, timeZone, scope, workspace? } | { filename, body } | JSON export of the full snapshot. |
scope is 'all' | 'main' | 'subtasks'; from/to are YYYY-MM-DD in the given IANA timeZone. The usage vocabulary lives in src/usage-types.ts.
src/
index.ts host: TerminalPanelService (TypertRemoteService)
usage.ts host: UsageService (TypertRemoteService, usagePanel ns)
typert.host.ts host-face TYPERT manifest for the typert-loader
types.ts terminal wire vocabulary (pure data)
usage-types.ts usage wire vocabulary (pure data)
usage-schemas.ts usage zod codecs (pure data)
client/
index.ts client plugin body (apply/inject)
remote.ts TYPERT_REMOTE contribution + ctx.remote typing
ConsoleHeaderActions.tsx three session-header icon toggles
ConsoleSidebar.tsx AI-output file viewer (details column)
TerminateDialog.tsx multi-tab xterm dialog (composer dock)
UsagePanel.tsx dual-dimension usage dashboard (modal overlay)
console-store.ts shared sidebar/dialog/usage snapshot store
console.css.ts injected stylesheet (style tag)
locales.ts zh / en dictionaries (namespace 'toolkit')
tests/
service.spec.ts TerminalPanelService behavior over a stub subprocess
usage.spec.ts usage collector/aggregator + service integration
apply.client.spec.ts client apply: slots, Remote mount, stylesheet
clear-repro.spec.ts UTF-8 chunk-split + clear escape-sequence regressions
terminate-reopen.spec.ts tab lifecycle: close-last-tab / reopen re-spawns
cordis.patch.yml bundle-row patch contributed to harness profiles
tsdown.config.ts two-face build (host ESM + client CJS closure bundle)
vitest.config.ts resolves @deepseek-ai/* to the harness source
pnpm build # tsc -p tsconfig.json && tsdown (host + client bundles)
pnpm typecheck # tsc --noEmit
pnpm test # vitest run
pnpm test:watch # vitest (watch mode)
Notes for contributors:
react, @deepseek-ai/* (and friends) external via CLIENT_EXTERNALS in tsdown.config.ts; they resolve through the module loader's injected require at runtime.src/client/remote.ts (browser descriptors) and src/typert.host.ts (host manifest) both hand-write what the generator would emit; their zod schemas and wire names must match the @Remote methods in src/index.ts.<style> tag (see console.css.ts), colored via the --dsw-* token layer with neutral fallbacks.clear-repro.spec.ts splits real prompt/clear byte sequences at every possible position to guarantee no U+FFFD mojibake.MIT — see LICENSE.
FAQs
DeepSeek Harness 开发者工具箱插件:侧边栏入口 + 底部终端面板,可开始/终止进程、手工输入命令,并浏览 AI 输出结果。
The npm package dsh-devpanel receives a total of 213 weekly downloads. As such, dsh-devpanel popularity was classified as not popular.
We found that dsh-devpanel demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.

Security News
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.