dsh-remote-pure
Verifieddsh-remote-pure · v0.13.0 · MIT · Web UI
Control a remote DeepSeek Harness project over SSH: remote runtime, local panel, on-demand history.
Install
dsh plugin add dsh-remote-pure Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
- github/yingkesu/dsh-lab 0 0 archived
Tags
Creators
Readme
dsh-remote-pure
Control a remote DeepSeek Harness project over SSH from the local Web GUI.
- Remote runtime: the local host half opens
ssh <host> <dshCommand> --profile sdkand speaks the official newline-framed SDK JSON-RPC (initializecarries the remote project cwd; sessions are addressed by client-chosen ids). - Local panel: a sidebar entry (
Remote) opens a main panel where you pick a configured host, type a remote project path, and chat with the remote agent. - History on demand: session lists and logs are read from the remote
$DSH_HOME/sessionsstore when you select a session. Nothing is copied into the local session store.
Install
In the running Web GUI (desktop app): open the Plugins page, choose install bundle, and pass this directory's absolute path. The app installs it into its own profile and loads the panel after a refresh. The CLI path works for any non-desktop profile:
dsh plugin --profile web add /absolute/path/to/dsh-remote-pure
Then add hosts to the profile's cordis.patch.yml (the bundle row is remote-pure):
- id: remote-pure
name: 'dsh-remote-pure'
config:
hosts:
- id: macbook
label: MacBook
ssh: macbook # ssh target, as in ~/.ssh/config
dshCommand: 'PATH=/opt/homebrew/bin:$PATH node $HOME/labs/ds/deepseek-harness/apps/cli/lib/bin.js'
dshHome: '$HOME/.dsh' # optional; default
provider: deepseek-official # optional; default
model: deepseek-flash # optional; default
dshCommand is a shell command run on the remote host; the plugin appends --profile sdk.
The remote runtime needs its own model credentials, and non-interactive SSH must work
(key/agent). Linux and macOS are supported.
Remote dsh discovery: SSH's non-interactive shell usually misses the user's interactive
PATH, so a bare dsh can fail with command not found even where the terminal works. When a host
has no dshCommand (or it is exactly dsh), the plugin probes the remote host first: dsh on the
SSH PATH, ~/bin/dsh, Homebrew, /usr/local/bin, ~/.local/bin, then a developer checkout at
~/labs/ds/*/apps/cli/lib/bin.js invoked through an absolute node. The result is cached for five
minutes; an explicit dshCommand skips the probe, and autoDetectDsh: false turns it off. When
nothing is found the connection error names the host and asks for dshCommand.
Host dropdown: every Host <alias> in your local ~/.ssh/config is offered automatically,
and ssh <alias> reuses that entry's User/Port/IdentityFile/agent setup, so existing keys work
without extra configuration. Explicit hosts rows win over a discovered alias with the same id. Set
discoverSshHosts: false to turn discovery off, and use defaultDshCommand / defaultProvider /
defaultModel to change the fallbacks discovered aliases get. A per-host identityFile and
sshOptions list are also accepted.
How it works
| Host file | Role |
|---|---|
lib/sdk-client.js |
line-framed JSON-RPC over the SSH stdin/stdout; rejects pending calls on disconnect |
lib/manager.js |
one SDK runtime per (host, project); prompts, live events, remote session list/history |
lib/remote-log.js |
decodes concatenated zstd session-log frames and projects chat messages |
lib/http-api.js |
/remote-pure/api/* routes used by the panel |
client.js |
sidebar entry + main panel (React via the host module table) |
Remote DSH web page
The panel can open a remote host's own DSH Web UI without exposing its port:
- the Host half runs
<dshCommand> web --no-open --port 0on the remote host and captures the one-time token URL it prints (127.0.0.1only); - a supervised
ssh -N -L 127.0.0.1:<local>:127.0.0.1:<remote>tunnel is opened and the token URL is rewritten to the local port; the panel opens it in a new tab; - 关闭网页通道 closes the tunnel, stops the remote process, and kills its tmux session. An
already-running instance can be attached instead by posting its token URL as
attachUrlto/remote-pure/api/web-open; attaching never starts or stops a remote process.
tmux option: the tmux checkbox starts the remote server inside a tmux session
(dsh-remote-pure-<host>), so a transient SSH drop does not kill it; the tunnel is then re-established
on the same local port. When the remote host has no tmux the plugin falls back to nohup and reports
that in the panel. The remote dsh web must be able to start from the configured dshCommand.
Optional auto-update
config.autoUpdate controls a version check against npm:
| value | behavior |
|---|---|
notify (default) |
the panel shows a 新版本 x.y.z button; clicking copies dsh plugin --profile <profile> add dsh-remote-pure@latest |
auto |
the same check attempts the install through the Host's PluginManager; HMR-managed profiles may answer "restart required" and fall back to the copied command |
off |
no registry check at all |
The check reuses the Host PluginManager's registry access when present and falls back to a direct
registry.npmjs.org read, cached for one hour. It never installs silently without auto.
Panel
A sidebar entry (Remote, beside the other panel icons) opens the main panel:
pick a host, pick or type the remote project path, press 连接. The left column lists the remote
project's durable sessions (read from the remote store on demand), the right column shows the chat.
Selecting an old session resumes it by id through the SDK before its first prompt.
Project picker: 浏览 opens a remote directory browser (cd <path> && pwd && ls -1Ap over SSH),
with ~, .., "选择此目录", and "新建并进入" (creates the directory remotely with mkdir -p). The last
eight (host, path) pairs you connected to are kept in the browser's localStorage and shown as
one-click chips, so repeat projects need no typing; the last project is restored on reload. Browsing
works before any project is connected.
Remote terminal: the 终端 tab opens an xterm.js terminal on the selected SSH host. The Host
half bridges the browser WebSocket to ssh -tt <alias> running under DSH's own PTY primitive, so
resize, colors, and full-screen programs work while authentication stays with the local OpenSSH
config, keys, and agent — no ssh2 dependency and no stored passwords. ws, @xterm/xterm, and
@xterm/addon-fit are the terminal dependencies; their browser assets are served by the plugin.
Verification
node --test test/*.test.js # 10 tests, fake SSH runtimes
node scripts/remote-check.mjs # real host: connect, prompt, read back persisted history
Verified against a remote macOS host: connect ~0.7 s, prompt round-trip, live events, and persisted
history reads all work through the plugin routes inside a real dsh web runtime.