DeepSeek Harness 插件

dsh-plugin-ssh

dsh SSH remotes: manage remote harnesses over SSH and use the local machine as a thin client (codex-remote style). Ships a standalone dsh-ssh CLI plus a dsh profile bundle that adds an SSH Remotes(英文原文)

跳到安装方式

来源信息

GitHub 仓库
ArcherLyu/dsh-plugin-ssh
最近更新
2026年8月17日
分类
工具与能力
GitHub stars
0
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/ArcherLyu/dsh-plugin-ssh
插件名:dsh-plugin-ssh
作者:ArcherLyu

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器3 个文件
README.md来源说明 · 只读预览

dsh-plugin-ssh

Manage remote DeepSeek Harness instances over SSH, with the local machine as a thin client — the same model as Codex Remote.

A remote harness runs on an SSH host (agents, bash/fs tools, sessions, and the workspace all live there). The local machine only:

1. opens an SSH tunnel to the remote harness (ssh -L), and 2. shows the remote harness's own web GUI in the browser at http://127.0.0.1:<local-port>.

Nothing heavy runs locally — the browser is the client, exactly like Codex Remote. This works out of the box because dsh's web surface is already a browser → harness client-server architecture (/api over HTTP/WS), and dsh deliberately refuses --host 0.0.0.0, so the SSH tunnel is the sanctioned way to reach a harness from another machine.

The plugin ships two halves:

PieceWhat it does
dsh-ssh CLI (bin/dsh-ssh.js)Standalone command: add/list/status/connect/disconnect/open/setup/start/stop/logs
dsh profile bundle (lib/index.js + lib/client.js)Installed into the local web profile; adds an SSH Remotes panel to Settings and an /ssh-remotes HTTP route

Both halves share the same logic (lib/config.js, lib/tunnel.js, lib/remote.js, lib/browser.js).

---

Install

Prerequisites: dsh ≥ 0.1.0-rc.6 (the web profile), ssh on PATH, and pnpm (npm i -g pnpm if dsh plugin reports pnpm missing).

Install the plugin into your local web profile (takes effect on the next dsh web start):

dsh plugin --profile web add /path/to/dsh-plugin-ssh

For the standalone CLI without a profile, run bin/dsh-ssh.js directly (node /path/to/dsh-plugin-ssh/bin/dsh-ssh.js ...) or symlink it:

ln -s /path/to/dsh-plugin-ssh/bin/dsh-ssh.js ~/.local/bin/dsh-ssh

---

Quick start

# 1. Configure a remote (hostname or ~/.ssh/config alias)
dsh-ssh add prod --host my-server --user deploy --workspace /srv/app

# 2. Provision the remote: check node, install dsh, create the workspace,
#    copy local LLM credentials (settings.yaml), and launch the harness
dsh-ssh setup prod --copy-settings

# 3. Connect: tunnel to the remote harness and open it in the browser
dsh-ssh connect prod          # adds --no-open to skip the browser
dsh-ssh open prod             # re-open the browser at the existing tunnel

# 4. Inspect / manage
dsh-ssh status prod           # tunnel + remote process + harness health
dsh-ssh logs prod             # tail the remote harness log
dsh-ssh stop prod             # stop the remote harness process
dsh-ssh disconnect prod       # tear down the tunnel

Then, in the local web GUI: Settings → SSH Remotes lists every configured remote with live status and Connect / Open / Disconnect / Start / Stop / Logs buttons.

On the new-session screen, an SSH 远端 chip sits beside the "选择工作区" chip: click it to list configured remotes and pick one to connect — the current page then navigates to that remote's harness GUI, so your workspace becomes the remote's (the local page is replaced). The same in-place navigation applies to Connect / Open in the Settings → SSH Remotes panel.

---

CLI reference

dsh-ssh add <name> --host <host> [options]   add/update a remote
dsh-ssh rm <name>                            remove a remote
dsh-ssh list                                 list remotes with a short status
dsh-ssh status [name]                        detailed status (all by default)
dsh-ssh connect <name> [--no-open]           tunnel + open the remote GUI
dsh-ssh disconnect <name> | --all            stop the tunnel
dsh-ssh open <name>                          open the browser at an existing tunnel
dsh-ssh setup <name> [--copy-settings]       provision the remote and launch
dsh-ssh start <name>                         (re)start the remote harness process
dsh-ssh stop <name>                          stop the remote harness process
dsh-ssh logs <name> [--lines N]              tail the remote harness log

add options:

OptionMeaningDefault
--host <host>SSH host or ~/.ssh/config alias (required)
--user <user>SSH usernamessh config
--port <port>SSH port22
--identity <path>private key path (~ expanded)ssh default
--jump <host>jump host for -J
--workspace <path>remote working directory for the harness
--remote-port <p>port the remote harness listens on3080
--local-port <p>local tunnel port; 0 = auto-pick0
--launch <cmd>override launch command; {dsh}/{port} placeholders{dsh} web --port {port} --host 127.0.0.1
--ssh-args <a>extra ssh option (repeatable)

Global flags: --json (list/status), --home <dir> (override DSH_HOME).

---

Configuration

Remotes live in $DSH_HOME/remotes.json (default ~/.dsh/remotes.json):

{
  "remotes": {
    "prod": {
      "host": "my-server",
      "user": "deploy",
      "port": 22,
      "identity": "~/.ssh/id_ed25519",
      "jump": null,
      "workspace": "/srv/app",
      "remotePort": 3080,
      "localPort": 0,
      "launch": null,
      "sshArgs": []
    }
  }
}

Runtime tunnel state is kept per remote in $DSH_HOME/remotes-state/<name>.json so a later disconnect/status can find the spawned ssh process.

On the remote, the plugin records its own state at ~/.dsh/remotes/<name>.json (pid, log path, port) and writes the harness log to <workspace>/.dsh-ssh.log.

---

How it works

Remote side (provisioned by dsh-ssh setup)

1. Ensures a compatible Node (dsh needs Node ≥ 20.12). If the system node is too old and ~/.nvm exists, it installs Node via nvm (--node-major, default 22) — user-local, no sudo. 2. Locates dsh; if absent, runs npm install -g @deepseek-ai/dsh under the active node. 3. Creates the workspace directory. 4. Optionally copies your local ~/.dsh/settings.yaml (LLM provider config) to the remote — or keep the remote's credentials managed independently. 5. Launches dsh web --port <remote-port> --host 127.0.0.1 inside the remote workspace with nohup, records the pid, and detaches. When dsh runs under nvm, the launch activates that runtime so the shebang's node resolves correctly.

The remote harness binds only to the remote's own 127.0.0.1, so it is never exposed to the network; the only way in is your SSH tunnel.

> LLM credentials on the remote: the harness reads $DSH_HOME/settings.yaml > and the .env file in its working directory (dsh loads .env from cwd). > Set the API key on the remote (e.g. write ARK_PLAN_API_KEY=… into > <workspace>/.env, or put the value in ~/.dsh/settings.yaml on the remote) > so agents can run there.

Local side (the thin client)

dsh-ssh connect picks a free local port, spawns

ssh -N -L <local-port>:127.0.0.1:<remote-port> [-p P] [-i key] [-J jump] user@host

as a detached background process, then polls http://127.0.0.1:<local-port>/ until the dsh boot marker (window.__DSH_BOOT__) appears. Because the browser talks same-origin /api, a page served over the tunnel is automatically a full client of the remote harness — including all tools, sessions, and jobs, which execute on the remote.

GUI panel

The bundle adds an sshRemotes host service and, when the web profile is composed, an /ssh-remotes HTTP route (loopback-origin only). The browser half registers a Settings → SSH Remotes section that lists remotes and drives the same operations the CLI does.

---

Security notes

  • Tunnels run with BatchMode=yes — set up key-based auth or an ssh agent;

interactive password prompts are intentionally not supported.

  • StrictHostKeyChecking=accept-new keeps first connects painless without

weakening existing known_hosts.

  • The remote harness binds 127.0.0.1 on the remote and is reached only

through your tunnel.

  • The local /ssh-remotes route rejects non-loopback Origin headers. It is

not a security boundary — the whole local harness already trusts 127.0.0.1 — but it prevents cross-site calls from a remote page.

Limitations / roadmap

  • Remote provisioning assumes a POSIX shell on the remote and key-based SSH.
  • Windows remotes are not targeted.
  • The GUI panel currently lists and drives remotes; per-remote session browsing

inside the panel is a future step (the browser tab remains the working surface today).

License

MIT