Full sidebar workbench with file rendering and editing, terminal, Git, and subagents; third-party plugins can register new tabs.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:omdsh-dev/DSH-better-sidebar
GitHub-sourced plugins run build scripts on your machine at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).
README
https://github.com/user-attachments/assets/23187822-047e-45cc-b480-fe997bd55b86
🆕 Recent Updates
- Custom terminal fonts: font-family + 9–32px size settings on the terminal card, applied live
- Side card settings redesign: grouped container cards, count badges, custom toggles, wider settings dialog
- Fix: blank terminal after expanding the bottom panel on WKWebView (xterm initialized in a zero-size container, #25)
- Docs: client changes take effect on a hard refresh — no DSH restart needed
✨ Features
- 🗂️ File Explorer: lazy-loading directory tree (root = session cwd), click to open,
@filereference, right-click to copy path - 📝 Edit & Preview: CodeMirror 6 editing (Ctrl/Cmd+S atomic save, drafts survive tab switches); inline preview for images / Markdown / HTML / PDF / Word / Excel / PPT (HTML in a sandboxed iframe)
- ⚡ Client-side Lazy Loading: only ~325KB core at startup; heavy deps (terminal / editor) load on demand (see
docs/plans/2026-08-12-lazy-chunks-design.md) - 🌐 Browser: multiple embedded web tabs, back/forward/refresh; pages run in a sandboxed iframe (no access to UI data or local files, rejects local addresses), temporarily unlockable (red warning); sites refusing embedding show a reason panel; external links open in the sidebar by default
- 💻 Terminal: xterm.js + node-pty real shell, reconnect with transcript replay; optionally injects
terminal_*tools for the model; custom font (family + 9–32px size, applied live) - 🌿 Git Panel: real diff + VSCode-style diff tabs, history, right-click to stage/commit/revert etc.
- 🧩 Background Tasks: main-session agent topology with click-through to execution records; background tasks on the same page (type badges + exit codes, live-output peek, force-kill)
- 🪟 Bottom Panel: an independent second workbench that only squeezes the center output area; auto-opens a terminal on first expand (toggleable)
- 📱 Mobile: narrow viewports (<768px) merge into a full-width drawer with the bottom panel's tabs folded into the sidebar; files/links auto-expand the panel
- 🔧 Split-pane Workbench: drag tabs to split/merge panes (cross-panel supported), divider to adjust ratios; one-click collapse/expand both panels from the top-right buttons
- 🔁 Session Isolation: layout / tabs / panel states persisted per session, stale state auto-purged; "produced files" open in the sidebar
- ⚙️ Declarative Settings: the "Side Cards" settings section renders a registry-driven toggle grid, each item independently switchable; secondary settings (auto-expand, terminal tools, sandbox, etc.) edited in a native dialog via the gear button
- 🔌 Service API: exposes
ctx.betterSidebar— other plugins can register tabs and file viewers (the 7 built-in tabs + 9 viewers share the same service, see AGENTS.md and the external plugin guide) - ➕ Add Plugins: dashed cards at the end of both settings grids ("Sidebar content" / "File viewers") open tab / previewer plugin modals: the extension point declaration, a "Browse more plugins on GitHub" BUTTON, and the recommended plugin catalog ("Open" jumps to the repo, "Copy" puts the install command on the clipboard); no terminal is opened, nothing can fail — never blocking startup or the sidebar
- 🌏 i18n: UI text follows DSH's language setting (zh/en) with live switching, no refresh needed
🚀 Installation
Prerequisites: DSH installed (dsh web boots), Node.js ≥ 20, pnpm ≥ 10.
macOS / Linux (also works in Git Bash / WSL on Windows):
curl -fsSL https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.sh | bash
Windows (PowerShell 5.1+ / pwsh):
irm https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.ps1 | iex
Then hard-refresh the browser (Cmd/Ctrl+Shift+R) to see the sidebar (DSH hot-reloads client changes; only host-half updates need a restart).
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.sh | bash -s 0.11.0 --restart
# Windows PowerShell
& ([scriptblock]::Create((irm 'https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.ps1'))) -Version 0.11.0 -Restart
Not sure? Add --dry-run (-DryRun in PowerShell) to preview before running.
Equivalent to the one-click script. Step ③ is repeatable; ①② only need to run once.
macOS / Linux (bash):
cd ~/.dsh/profiles/web
# ① Allow node-pty / protobufjs build scripts (pnpm 11 blocks them by default; skip on pnpm 10)
pnpm approve-builds --all
# ② Allow versions published less than 24h ago (skip for older releases; if the key already exists, merge the line under it instead)
cat >> pnpm-workspace.yaml <<'EOF'
minimumReleaseAgeExclude:
- dsh-better-sidebar
EOF
# ③ Install and auto-mount (no @version = npm's latest; pin with dsh-better-sidebar@0.11.0)
npx -y --package @deepseek-ai/dsh dsh plugin --profile web add dsh-better-sidebar
Windows (PowerShell):
cd ~\.dsh\profiles\web
# ① Allow build scripts
pnpm approve-builds --all
# ② Allow fresh releases (once; if the key already exists, merge - dsh-better-sidebar under it instead)
Add-Content -Path pnpm-workspace.yaml -Value "`nminimumReleaseAgeExclude:`n - dsh-better-sidebar"
# ③ Install and auto-mount
npx -y --package @deepseek-ai/dsh dsh plugin --profile web add dsh-better-sidebar
The one-click script does four things, all idempotent (safe to re-run):
- Pre-writes
allowBuilds(node-pty / protobufjs) to dodge pnpm 11's build-script block; - Pre-writes
minimumReleaseAgeExcludeto allow versions younger than 24 hours; - Runs
dsh plugin --profile web add dsh-better-sidebar: registers the dependency → detectsdsh.bundle.patch→ auto-appends the plugin todsh.profile.bundles; - Removes any leftover hand-written mount line to avoid double-mounting (two sidebars on the page).
curl | bash / irm | iex executes remote code — the scripts are open source in the repo (scripts/install.sh / scripts/install.ps1); download and review them first if you prefer. The plugin ships as npm package dsh-better-sidebar@0.11.0 and mounts via dsh.bundle.patch (the shipped cordis.patch.yml), so the DSH source is never modified.
dsh plugin --profile web add dsh-better-sidebar
or re-run the one-click script; or bump the version in ~/.dsh/profiles/web/package.json (e.g. "^0.11.0") and run pnpm install. Then hard-refresh the browser (Cmd/Ctrl+Shift+R) — client changes do not need a DSH restart.
| Symptom | Cause & fix |
|---|---|
Ignored build scripts |
pnpm 11 blocked build scripts. Run pnpm approve-builds --all (the one-click script handles it). |
minimum release age / version < 24h |
The release is younger than 24 hours. Wait, or re-run once (pnpm auto-adds minimumReleaseAgeExclude); the one-click script handles it. |
| "profile directory not found" | Run dsh web once so it initializes ~/.dsh/profiles/web. |
| Two sidebars on the page | Double-mount: ~/.dsh/profiles/web/cordis.patch.yml still has the old hand-written - insert: ... better-sidebar ... line — delete it (the one-click script cleans it). |
| Terminal fails on Windows | node-pty relies on prebuilt binaries; if none match your Node version, install a build toolchain (VS Build Tools). Mainstream Node versions are usually covered. |
| No bash / curl on Windows | Use the PowerShell one-click command, or install Git Bash / WSL and run the bash commands. |
To debug local changes or track the dev branch, point the dependency at a local clone and build it yourself:
1. git clone https://github.com/omdsh-dev/DSH-better-sidebar.git ~/Code/DSH-better-sidebar
cd ~/Code/DSH-better-sidebar && pnpm install && pnpm build
2. In ~/.dsh/profiles/web/package.json dependencies write "dsh-better-sidebar": "link:<absolute path of the clone>"
3. Append this mount line to ~/.dsh/profiles/web/cordis.patch.yml:
- insert:
- id: better-sidebar
name: 'dsh-better-sidebar'
4. Run pnpm install in ~/.dsh/profiles/web
5. Restart DSH and hard-refresh
Update: git pull && pnpm install && pnpm build → just hard-refresh the browser (client changes hot-reload; only host-half changes need a DSH restart). To switch back to the npm channel, restore "dsh-better-sidebar": "^0.11.0" and re-run pnpm install.
Prerequisite: DSH with plugin-registry integrated (dsh registry available). Enabling both channels double-mounts (the Node half loads twice, the page gets two sidebars).
git clone https://github.com/omdsh-dev/DSH-better-sidebar.git && cd DSH-better-sidebar
pnpm install && pnpm build
node scripts/package-registry.mjs # assemble the registry/ staging (manifest + artifacts + README, not committed)
dsh registry install ./registry # install (disabled by default)
dsh registry enable dsh-external/dsh-better-sidebar
Update: git pull && pnpm install && pnpm build → node scripts/package-registry.mjs → dsh registry uninstall/install/enable. Remove the other channel's mount before switching.
⌨️ Keyboard Shortcuts
| Action | Keys |
|---|---|
| Save edits | Ctrl/Cmd + S |
| Git commit | Ctrl + Enter |
| Close tab | Middle mouse button |
| Split / merge panes | Drag tab to pane edge / middle |
| Reference file to input | Hover the @file button at end of line |
| Copy file path | Right-click row → copy relative/absolute path |
🔌 Service: register tabs & file viewers
Since v0.4.0 the plugin exposes the ctx.betterSidebar service — other plugins can register sidebar pages and file viewers (the 7 built-in tabs + 9 viewers go through the same service, eating our own dog food):
import type {} from 'dsh-better-sidebar' // triggers the ctx.betterSidebar type merge
export const inject = ['betterSidebar']
export function apply(ctx: Context) {
ctx.effect(() => ctx.betterSidebar.registerTab({
id: 'my-plugin:db', title: 'Database', component: ({ scope }) => <DbView sessionId={scope.sessionId} />,
}))
}
v0.12.0+ base capabilities: complete type exports (consumers can name SidebarTab/SidebarState etc.; the client declaration graph is Node-free), version/features capability detection, getSnapshot/subscribeState state subscription, tab badge, onOpen/onActivate/onClose lifecycle callbacks, updateTab/activateTab/openFile, targeted openTab(seed, scope), SidebarTab.meta persisted across reloads, and an opened settings seam (settings.pluginToggles / settings.render, stored in pluginSettings[id]).
Full integration docs:
AGENTS.md— the in-repo integration doc (full fields, matching algorithm, HMR pitfalls, declarative settings, version detection);docs/external-plugin-guide.md— the external-plugin guide (with a complete minimal example).
➕ Add Plugins (recommended plugin catalog)
The dashed card at the end of the "Sidebar content" grid in the "Side Cards" settings section opens the Add tab plugins modal; the one at the end of the "File viewers" grid opens the Add preview plugins modal. Each declares that its extension point is open to plugins (via the ctx.betterSidebar service), offers a "Browse more plugins on GitHub" button (opens the GitHub topic dsh-better-sidebar in a new tab), and lists the recommended catalog of its kind (name / repo URL / description / install script). Each entry has two buttons:
- Open: jumps to the plugin repo in a new browser tab;
- Copy: writes the install command (
cd ~/.dsh && dsh plugin --profile web add <package>) to the clipboard with a transient "Copied" feedback — paste and run it in a terminal where your DSH profile lives. The modal stays open; nothing is opened, nothing can fail.
Curating a new plugin: append a PluginEntry to src/client/plugins-tabs.ts (tab registrations) or src/client/plugins-viewers.ts (file-previewer registrations) — id = npm package name, name, url, description (i18n-friendly; add a pluginXxxDesc key in src/client/locales.ts if needed), install = the full install command — and tag your repo with the dsh-better-sidebar topic; data integrity is guarded by tests/plugin-list.spec.ts.
🛠️ Development & Build
pnpm install # @deepseek-ai/* resolved from npm (^0.1.0-rc.6, published) — no token needed
pnpm typecheck # tsc --noEmit
pnpm build # → lib/index.js + lib/invariant.js + lib/client.js + lib/client-registry.js + lib/types
pnpm test # vitest (includes manifest consistency guard; build first)
pnpm watch # tsdown --watch
Architecture: a single npm package with host/client halves — host (src/index.ts): /sidebar/api/* JSON API, /sidebar/file media route, /sidebar/html preview route, /sidebar/ws/terminal WebSocket (fs / git / pty / preview, all session-scoped with a trust fence); client (src/client/index.tsx): portal sidebar + views + interception; state persisted per session in localStorage. Organized per DSH official conventions (no default export, dual client bundles); no dependency on npm / checkout at runtime (@deepseek-ai/* provided by the web profile).
🔐 Security
- Routes protected by a Host-header trust fence (same as
/api);fs.writeis atomic; media/preview routes only serve files inside the session cwd; git only shells out to the CLI and never sets identity - HTML preview and browser tab content render in opaque-origin sandboxed iframes (no
allow-same-origin/allow-top-navigation,no-referrer, all permission policies disabled); the/sidebar/htmlroute carries a CSPsandbox+ size/path bounds; the address bar rejectsjavascript:/data:/file:and local addresses like localhost - The UI shows the sandbox status live (red warning when off) and can temporarily unlock the current page; the settings page can disable the sandbox per feature (disabled by default, with a warning) — when off, content shares the origin with the UI; only recommended for fully trusted content
⚠️ Known Limitations
- Git has no push/pull/fetch; no file watcher (manual refresh); tool inline file-open buttons cannot be intercepted
- Dragging a terminal tab to another pane remounts it (shell restarts)
- Office-suite preview (.docx/.xlsx/.pptx) moved to the recommended office plugin (see the "Add plugins" modals in settings); without it these files fall through to the code/download fallbacks
- Browser sandbox has no login state / third-party cookies are restricted; some sites need popup login; sites that refuse embedding via
X-Frame-Options/frame-ancestors(e.g. arxiv.org) show a reason panel (with "Open in browser"); in-iframe navigation does not enter the back stack - HTML preview renders the saved file (not unsaved drafts)
- No bottom panel on mobile (<768px): on narrow screens its tabs merge into the right sidebar once (after migrating back to desktop they stay in the right sidebar); the desktop bottom panel is only available on wide viewports; auto-open terminal on first bottom-panel expand does not trigger on mobile
🖥️ Platform Support
Windows / Linux / macOS (macOS validated daily; the rest covered by unit tests); node-pty prefers prebuilt binaries, otherwise a build toolchain is required (Windows VS Build Tools / Linux make+g+++python3 / macOS Xcode CLT).
🔗 Friends
- dsh-tianshu-tui: an interactive terminal UI plugin for DeepSeek Harness (its rendering core evolved from the self-developed harness agent Tianshu-Tui), adding TDD and evidence-gate workflows on top of the official harness
- dsh-TUI: a Claude Code-style fullscreen interactive TUI plugin — pixel-whale top bar, live working-status row, streaming thought expansion, double-Esc rollback, context progress bar + TPS meter; one-command npm install
- dshfind Plugin Market: a third-party plugin marketplace — a listing of public repos under the GitHub topic
dsh-plugin, with stars, contributors and growth data synced daily
Links
More in this category
zhu1090093659/dsh-web-ui★ 1766
Plugin and skin collection for the DSH Web UI: task board, Git graph, right-side panel, remote mobile UI, pet, live token stats, and a skin center.
ccch1mneyyy/dsh-TUI★ 829
Claude Code-style full-screen terminal UI: pixel-whale header, live status line, and streaming thought expansion.
huiliyi37/dsh-tianshu-tui★ 131
A terminal UI (TUI) for DeepSeek Harness.
omdsh-dev/dsh-at-file★ 117
Codex-style `@file` mentions: search workspace files in the composer and attach their contents to prompts.
Nagi-ovo/dsh-visualize★ 79
In-conversation generative UI: the model renders interactive HTML cards into the chat stream, with streaming preview and sandboxed rendering.
omdsh-dev/dsh-genui★ 72
Interactive UI components rendered inline in replies: layout, charts, forms, quizzes, mermaid, 3D scenes, and an action event loop back to the model.