Back to home

yu2025-luo

dsh-file-panel

Right-side file panel for DeepSeek Harness — auto-popup when the agent creates or downloads files, with image/text preview, reveal-in-folder and open actions. Bilingual · MIT

Stars
2
Language
JavaScript
Created
Aug 14, 2026
Updated
Aug 14, 2026

Introduction

dsh-file-panel

CI License: MIT

A plugin for DeepSeek Harness (dsh web GUI) that watches what the agent creates and downloads during a session, and shows it in a right-side popup panel — like the file viewer in Codex.

When a file or image is written to disk during a session, the panel pops up automatically on the right. Every row lets you:

  • 👁 Preview — images render inline; text files show their first 256 KB; other types show metadata.
  • 📂 Show in folder — opens the OS file manager with the file selected (explorer.exe /select on Windows, open -R on macOS, xdg-open on Linux).
  • Open — opens the file with the OS default application (via the harness's built-in host.openPath RPC).
  • 📋 Copy path — copies the absolute path to the clipboard.

Also ships a workspace folder shortcut at the bottom of the panel.

中文说明

Screenshots

Add screenshots after running it locally (see Development).

Installation

Requires DeepSeek Harness dsh CLI (npm package @deepseek-ai/dsh) and pnpm.

From a local checkout

cd dsh-file-panel
npm install          # installs esbuild (dev-only)
npm run build        # produces lib/index.js + lib/client.js (committed)

# register in the web profile (link: tracks your checkout live)
dsh plugin --profile web add link:.

From GitHub

dsh plugin --profile web add github:yu2025-luo/dsh-file-panel

The built artifacts are committed, so no build step runs during install.

Activate

Restart the dsh web server (plugin sets take effect on restart), then refresh http://127.0.0.1:3080. That's it — no configuration required.

Remove with:

dsh plugin --profile web remove dsh-file-panel

Usage

GestureResult
Agent creates/downloads a filePanel pops up automatically (newest files carry a NEW chip)
Click a rowInline preview (image / text / metadata)
Row hover actionsPreview, open, show in folder, copy path
🔔 bellToggle auto-pop for new files
/ ×Collapse to a floating launcher button (with new-file badge) or hide
Bottom "open workspace folder"Opens the session's working directory

Panel state (open/collapsed) and the auto-pop preference persist in localStorage. The auto-pop baseline is per session: files that already existed when the panel first saw the session do not re-trigger a popup.

How it works

One npm package with two halves, registered as a single loader row (cordis.patch.yml → row file-panel):

Host half (src/index.js)                     Browser half (src/client.jsx)
────────────────────────                     ──────────────────────────────
ctx.on('fs/observed')          ──┐
  write/edit tools report        │            shell.overlay slot entry:
  files (precise, attributed     │            a right-docked floating panel
  to the session)                ├──▶ FileTracker (per-session lists,
recursive fs.watch per           │      ignore rules, caps, fence)
  session working directory       │                │
  (catches shell downloads:    ──┘                ▼
  curl, Invoke-WebRequest, …)          RPC channel /file-panel
                                        authority: 'loopback'
                                        list · readText · readImage
                                        reveal · describe
                                                  ▲
                                                  │ poll every 1.5 s
                                        client: ctx.connection.rpc.call()
                                        open file: built-in api.host.openPath

The client half registers into the shipped shell.overlay slot (additive, frame-wide floating layer), reads the current session through the standard useSessions prop, and polls the plugin's own loopback-only RPC channel. The channel is registered with ctx.connection.rpc.handle, the sanctioned static-package RPC seam.

Security

  • The /file-panel channel is registered with authority: 'loopback', so only pages served from 127.0.0.1 can call it. When the GUI is accessed over the network (--trusted-host), the panel shows a notice and stays inactive.
  • Every read/reveal endpoint only accepts absolute paths that the tracker has actually seen (a tool write or a watcher event under a watched working directory) — the RPC can never be used as a generic file-read/reveal primitive.

Project layout

src/
  index.js      host half: tracker wiring + /file-panel RPC endpoints
  tracker.js    pure-Node file tracker (fs/observed ingestion, recursive
                watcher with debounce, ignore rules, caps, RPC fence)
  client.jsx    browser half: the right-side panel UI (React, JSX)
build.mjs       esbuild build for both halves
cordis.patch.yml  the bundle patch inserting the loader row
tests/          node:test unit + host-half smoke tests
lib/            built artifacts (committed, so installs need no build step)

Development

npm install
npm run build   # rebuild lib/index.js and lib/client.js
npm test        # node --test

For a fast client-side iteration loop after changing src/client.jsx:

npm run build

then hard-refresh the GUI page (lib/client.js is served with cache-control: no-cache; plugin sets only change on restart, but bundle content re-hashes per request — see dsh-client-modules). During active UI development you can also run pnpm run dev:web from the harness checkout to rebuild client bundles on change.

Compatibility

Built against the public seams of @deepseek-ai/dsh 0.1.0-rc.x:

  • host: ctx.connection.rpc.handle / ctx.on('fs/observed')
  • client: shell.overlay slot, useSessions standard prop, ctx.connection.rpc.call, ctx.locale

DeepSeek Harness is pre-release: those seams may move. If the panel stops working after a dsh upgrade, check the pinned version in package.json and re-run the build.

Known limitations

  • The recursive watcher uses fs.watch({ recursive: true }) (Node ≥ 20). On platforms where that is unavailable, the panel still tracks everything the harness write/edit tools produce, but shell-side downloads may be missed.
  • The panel is process-local: it starts empty after a restart (it only records files it actually observed; it does not scan history).
  • node_modules, .git, and temporary-file noise are ignored by design.
  • reveal on headless Linux reports canReveal: false and hides the button (no desktop to open).

Publishing to GitHub / npm

  1. Create a GitHub repo and push (the repo is already a git repository with a v0.1.0 tag):

    git remote add origin https://github.com/yu2025-luo/dsh-file-panel.git
    git push -u origin main --tags
    
  2. Add the dsh-plugin topic on the repo page (About → gear icon → Topics) together with deepseek-harness, dsh, deepseek, and file-preview. The repo then appears on the public plugin topic page automatically.

  3. Users install with dsh plugin --profile web add github:yu2025-luo/dsh-file-panel#v0.1.0.

  4. Optionally publish to npm (npm publish) — then install with dsh plugin --profile web add dsh-file-panel.

Community catalogs that sync from the dsh-plugin topic: Oh-My-DSH (auto-synced) and awesome-deepseek-harness (PR-based).

Remember to bump the version and re-run npm run build before releasing.

License

MIT