dsh-plugin-remote-ssh
Manifest validDeepSeek Harness plugin: manage SSH hosts, open official dsh-ssh remote windows, and mount remote workspaces into the current window
@junjiangao/dsh-plugin-remote-ssh
English version: README.en.md
在 DeepSeek Harness Web UI 左侧栏管理 SSH 主机,并把远端工作区以两种方式接入:
- 独立远端窗口:每台主机可打开一个基于官方
dsh-ssh的远端工作窗口,文件、命令和终端都跑在远端; - 同一窗口混合模式:不新开窗口,直接把远端目录登记为当前桌面窗口的一个 Workspace,本地会话与远端会话同时存在(由插件内置的执行路由器按路径分派
fs/subprocess/sandbox)。
这个插件不再注册任何模型工具。它只负责“主机管理 + 远端窗口编排”,真正的 SSH 能力由官方 provider 家族提供:
@deepseek-ai/dsh-ssh:每台主机一个 helper 连接@deepseek-ai/dsh-fs-ssh:把远端文件系统接成fs@deepseek-ai/dsh-subprocess-ssh:把远端进程/终端接成subprocess@deepseek-ai/dsh-sandbox-ssh:远端沙箱
功能
- 侧栏入口:Web/桌面端左侧栏出现「远程 SSH」,主区展示主机列表。
- 主机来源:默认读取
~/.ssh/config,导入的条目只读;插件自己托管的主机可添加、编辑、删除。 - 添加/编辑共用一个表单:别名、显示名、HostName、User、Port、IdentityFile、ProxyJump、ProxyCommand、IdentitiesOnly、ForwardAgent、KeepAlive、StrictHostKeyChecking、UserKnownHostsFile、ConnectionAttempts、ConnectTimeout、任意额外指令、远端工作目录、远端 helper 目录。
- 先检查再安装:打开主机前检查 SSH、远端平台、Node/npm、helper、工作目录和本地 runtime;helper 缺失或版本不匹配时先弹出确认对话框,确认后才在远端执行 npm 安装。
- 独立远端窗口:每次打开使用官方 SSH provider 启动一个独立的 DSH Web 实例(独立 profile、独立端口、隔离的 DSH home),在浏览器新标签页打开带鉴权的 URL。
- 远端工作区与
@文件:远端窗口不再显示本机项目列表,默认工作区直接指向远端路径;@文件候选由插件通过官方fs-ssh读取远端目录,而不是扫描本机。 - 远端目录选择器:远程窗口里点「添加工作区」浏览的是 SSH 主机上的目录,而不是本机文件夹;新建目录也在远端执行。
- 「远程工作区」侧栏:主界面侧栏新增一个只读聚合面板,按「远程机 + 工作区」列出各主机隔离 home 中的远端工作区与会话,可直接打开/停止窗口。
- 会话深链:在「远程工作区」面板点某个会话,会打开对应远端窗口并直接定位到该会话(基于隔离 home 中的短期标记,不依赖 URL 参数)。
- 同窗口混合模式:「远程工作区」面板的「在此窗口打开」把远端目录登记为普通 Workspace;新会话的 Bash、读写文件、列目录走 SSH 世界,本地 Workspace 不受影响。
- 不使用模型工具:不向
ctx.tools注册ssh_exec/ssh_upload等工具,避免和官方 agent 能力重复。
系统要求
- DeepSeek Harness
>= 0.2.1-rc.2 < 0.3.0,Node.js^22.19.0 || >=24.0.0。 - 本机:Linux 或 macOS;OpenSSH 客户端(
ssh),且~/.ssh/config支持Include(OpenSSH 7.3+)。 - 远端:Linux 或 macOS;
/bin/sh;Node.js^22.19.0 || >=24.0.0;npm;可写的远端工作目录。 - 远端 helper 安装需要访问 npm registry(或配置镜像);本机 runtime profile 安装需要访问 npm registry。
Windows 客户端暂不支持(官方 dsh-ssh provider 只面向 POSIX 客户端)。
安装
通过插件管理器(推荐)
插件清单声明了 dsh.bundle.patch。为了接管本地/远端执行,补丁先禁用基础 provider 行,再插入一个 Host 行:
- id: subprocess
disabled: true
- id: sandbox
disabled: true
- id: fs-sandbox
disabled: true
- insert:
- id: remote-ssh
name: '@junjiangao/dsh-plugin-remote-ssh'
config: {}
被禁用的三行由插件的执行路由器重新提供:本地世界仍挂载官方 dsh-fs-sandbox / dsh-subprocess-local / dsh-sandbox-local,因此本地行为不变;远端世界按需挂载 SSH provider。
该行以空配置激活,全部默认值见配置项。安装/启用后需要重启 Harness Host 或重新加载 profile 才能加载新的 Host 模块。
本地开发
在 profile 的 package.json 中把包指向本地目录,并加入 bundle 列表:
{
"dependencies": {
"@junjiangao/dsh-plugin-remote-ssh": "link:/absolute/path/to/dsh-plugin-remote-ssh"
},
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@junjiangao/dsh-plugin-remote-ssh"]
}
}
}
然后在该 profile 中安装依赖并重启 Host。插件自身只有 @deepseek-ai/schemastery 一个 peer 依赖,其余 Node 内置模块和 Harness 提供的能力不需要额外安装。
快速使用
- 重启后打开 Harness Web UI,点击左侧栏「远程 SSH」。
- 列表分为两组:
- 托管主机:插件写入
~/.dsh/remote-ssh/ssh_config的主机,可编辑/删除。 - 来自 ~/.ssh/config:只读导入条目,可「复制为托管」后再改。
- 托管主机:插件写入
- 点击「添加主机」,填写别名和主机名即可保存;
~/.ssh/config顶部会自动出现一个受管理的Include块。 - 点击某台主机的「测试」验证 SSH 连通性;点击「打开」进入准备流程。
- 首次打开时如果远端没有匹配版本的 helper,会先显示安装确认和将要执行的 npm 命令;确认后等待安装、runtime 准备和窗口启动。
- 窗口启动后点击「打开窗口」在浏览器新标签页打开远程工作区;「停止」结束该主机的实例。
- 侧栏「远程工作区」按「远程机 + 工作区」汇总已打开的远端工作区与会话;点击会话会自动打开对应窗口并定位到该会话。
- 想在当前窗口同时使用本地和远端时,在「远程工作区」点「在此窗口打开」,详见混合模式。
同一台主机同时只保留一个远端窗口实例。重复点击「打开」会复用已运行的实例。在远程窗口内点「添加工作区」时,目录浏览器读取的是远端文件系统;首次选择新目录后,插件会按 mirrorWorkspace 在本机创建同路径空目录以通过工作区 realpath 校验。
存储与 ssh_config
| 路径 | 内容 |
|---|---|
~/.dsh/remote-ssh/hosts.json | 插件托管的 host 记录(0600) |
~/.dsh/remote-ssh/ssh_config | 由 host 记录生成的 OpenSSH 片段;不要手改 |
~/.dsh/remote-ssh/instances/<id>.yml | 每次打开时生成的该主机 Loader overlay |
~/.dsh/remote-ssh/instances/<id>.pid | 正在运行的远端窗口进程记录,用于崩溃恢复 |
~/.dsh/remote-ssh/homes/<host-id>/ | 每台主机的隔离 DSH home;只继承凭据/设置文件,工作区登记指向远端路径 |
~/.dsh/remote-ssh/homes/<host-id>/storages/pending-session.json | 主界面点会话时写入的待定位会话标记(0600,TTL 5 分钟,远端窗口读取后删除) |
~/.dsh/remote-ssh/mixed/workspaces.json | 混合模式登记表:主机、远端路径与本地镜像路径(0600) |
~/.dsh/remote-ssh/mixed/mounts/<host-id>/ | 混合模式的本地镜像目录,只用于 Workspace realpath,不复制远端文件 |
~/.dsh/remote-ssh/mixed/runtime/<version>/tree/ | 混合模式的私有模块树(官方本地 provider + SSH 包),保证模块身份一致 |
~/.ssh/config | 顶部插入受管理的 Include 块;首次修改前备份为 config.dsh-remote-ssh.bak |
~/.dsh/profiles/dsh-remote | 插件准备的本地远端运行时 profile |
生成的 ~/.ssh/config 片段大致如下(Include 指向托管文件):
# BEGIN dsh-plugin-remote-ssh (managed; do not edit)
Include /home/me/.dsh/remote-ssh/ssh_config
# END dsh-plugin-remote-ssh
被托管的每个 Host 默认写入 StrictHostKeyChecking yes。首次连接由插件用 accept-new 完成引导并把主机密钥写入 known_hosts,之后官方 provider 使用严格校验。可以按主机把该值改为 accept-new 或 no。
删除全部托管主机后,Include 块会保留但指向空片段,这是有意为之,避免频繁改写用户配置。
配置项
在 profile 的 cordis.patch.yml 中按行 id 覆盖。行覆盖会替换整个 config,因此只写需要的键也可以,其余键会取 Config 默认值;如果你依赖旧值,请显式写全。
- id: remote-ssh
config:
profileName: dsh-remote
inheritDesktopSettings: true
sshPackageVersion: 0.2.1-rc.2
remoteNode: /usr/bin/node
| 键 | 默认值 | 说明 |
|---|---|---|
sshExecutable | ssh | 引导和诊断使用的 OpenSSH 客户端 |
sshConfigPath | ~/.ssh/config | 读取主机并维护受管理 Include 的用户配置 |
dataDir | ~/.dsh/remote-ssh | 插件数据目录 |
profileName | dsh-remote | 准备并启动的本地 runtime profile 名 |
sshPackageVersion | 当前 DSH 版本 | 官方 SSH 包版本;为空时使用运行中的 Harness 版本 |
helperPackage | @deepseek-ai/dsh-ssh | 远端安装的 helper npm 包 |
helperRoot | ~/.dsh-remote-ssh/helper | 远端 helper 父目录,按版本分子目录 |
npmRegistry | 未设置 | 远端 helper 安装使用的 npm registry |
remoteNode | 自动发现 | 远端 Node 绝对路径;默认先查 SSH PATH,再探测 fnm/nvm/volta 等常见安装目录 |
connectTimeoutMs | 15000 | 单次 SSH 连接超时 |
commandTimeoutMs | 30000 | 单条远端诊断命令超时 |
installTimeoutMs | 600000 | 远端 helper 或本地 runtime 安装超时 |
openTimeoutMs | 90000 | 等待远端窗口打印 URL 的截止时间 |
inheritDesktopSettings | true | 把桌面 profile 的用户补丁应用到远端窗口(沿用模型/UI 设置) |
mirrorWorkspace | true | 在本机创建与远端同路径的空目录,绕过工作区 realpath 校验 |
permissionMode | workspace-write | 远端窗口的沙箱模式:workspace-write / read-only / danger-full-access |
主机表单还支持以下按主机字段(保存到 hosts.json 并写入 ssh_config):
alias、displayName、description、hostname、user、port、identityFile、proxyJump、proxyCommand、identitiesOnly、forwardAgent、serverAliveInterval、serverAliveCountMax、strictHostKeyChecking、userKnownHostsFile、connectionAttempts、connectTimeout、extraOptions、remoteWorkspace、remoteHelperRoot。
extraOptions 不接受 Host、Match、Include,并且拒绝重复指令。
打开流程
openHost 在 Host 侧按以下阶段执行,并把阶段写回快照供面板轮询:
checking:doctor检查 SSH、远端平台、Node/npm、helper 版本、工作目录、主机密钥和本地 profile。installing-helper:如果 helper 缺失或版本不匹配,且调用方传了allowInstall: true,在远端执行 npm 安装并计算入口文件 sha256;会优先使用 doctor 探测到的绝对 npm,并把 Node 目录加入安装命令的 PATH(兼容 fnm/nvm 不在非交互 SSH PATH 的情况)。preparing-runtime:在本地准备dsh-remoteprofile(首次安装 4 个官方 SSH 包)。starting:准备隔离的 DSH home,并用该主机的 overlay 启动独立 Web 实例,等待它打印dsh web: http://127.0.0.1:<port>/?<token>。overlay 同时挂载远端目录选择器与会话深链插件。running:URL 可用;openUrl把 URL 返回给浏览器,由面板window.open打开。failed/stopping/idle:失败、停止和空闲状态。
启动前插件会准备独立的 DSH home:把 profiles/dsh-remote 链接进去,继承 .credentials.yaml、.env、settings.yaml 和 AGENTS.md,并写入一条指向远端 workspace 的工作区记录。这样远端窗口不会复用桌面的本机项目/会话列表,默认工作区就是远端目录。
overlay 会关闭本地的 subprocess、sandbox、fs-sandbox,插入官方 SSH 的四行,并把 sandbox-policy.workspaceRoot 改成远端工作目录;同时关闭本机的 file-reference-local,插入跟随 fs-ssh 的远端文件引用提供者。默认的 directory-picker(桌面端会弹本机原生文件夹对话框)也会被替换为插件的远端浏览后端;另挂一个小的会话深链插件,用来领取主界面投递的待定位会话。官方 provider 是单例:一个远端窗口只服务一台主机,因此每台主机使用独立实例和独立 overlay。
混合模式(同一窗口)
除了独立远端窗口,插件还支持把远端目录直接放进当前桌面窗口:
- 打开侧栏「远程工作区」,在某台主机的远端工作区或主机标题旁点「在此窗口打开」。
- 插件会检查该主机、展开
~、确认远端目录可写、确认 helper 已安装并准备好dsh-remoteprofile;首次会创建本地镜像目录~/.dsh/remote-ssh/mixed/mounts/<host-id>/<name>-<hash>。 - 面板用普通 Workspace API 登记镜像目录并跳转到它;新建会话的 cwd 就是这个镜像路径。
- 在该会话里执行 Bash、读写文件、列目录时,路由器按路径把调用分派到该主机的 SSH 世界;其他本地 Workspace 的会话仍走本机执行。
路由优先级:镜像挂载前缀 → 当前工具会话的远端环境(tools/execute 的 session cwd)→ cwd 所在镜像 → 本地。远端会话里的绝对路径(如 /etc/hostname)按远端解释,不会误读本机文件。
注意:混合模式只接管 fs、subprocess、sandbox 三个服务。内容搜索仍使用打包的本地 ripgrep(镜像目录没有远端文件),@ 文件候选、LSP、open-in-app、spill 等仍按本机实现;需要完整远端语义时请使用独立远端窗口。
登记信息存放在 ~/.dsh/remote-ssh/mixed/workspaces.json;RPC removeMixedWorkspace 可移除登记并断开该主机世界,但不会删除普通 Workspace 记录。
安全
- 不在
hosts.json、ssh_config、overlay 或日志中保存 SSH 密码、token;认证完全交给 OpenSSH(密钥、agent、ProxyCommand)。 ssh/scp不经过本地 shell 拼接;参数以 argv 传递。远端命令通过明确的/bin/sh -c执行。- 浏览器和 Host 之间使用 Harness Connection 自带的鉴权 Fetch 通道,每个端点一条精确路由。
- 远端窗口 URL 中的 token 只在
openUrl返回值中使用;实例日志和错误详情会脱敏后再返回浏览器。 hosts.json、生成的ssh_config、overlay 和 pid 记录都以 0600 写入;~/.ssh/config首次修改前会备份。- 官方 provider 启动 helper 时使用
BatchMode=yes、StrictHostKeyChecking=yes、ForwardAgent=no、ClearAllForwardings=yes;插件不会绕过这些限制。
已知限制
- 一台主机一个远端窗口:官方
dsh-ssh在单个 composition 中是单例,不能在同一窗口切换多台主机。 - 不是完整 VS Code Remote:
@文件引用和目录选择器已经改为读取远端文件系统,但 workspace changes、open-in-app、spill、skill filesystem 等仍按本机工作区实现,可能不可用或行为不一致;目前通过同路径本地镜像缓解工作区 realpath 校验。 - PTC 不可用:node-script helper 没有可执行 bootstrap,overlay 会关闭
ptc-runtime和workflow-ptc。 - globs/grep:远端
glob/grep可能依赖远端 ripgrep;没有安装时相关工具会失败或回退。 - 没有文件 watch:远端文件变化不会通过本机 fs watch 推送。
- 端口转发/agent 转发:官方 provider 固定
ClearAllForwardings=yes、ForwardAgent=no;需要转发请在~/.ssh/config的ProxyCommand/ProxyJump层解决。 - helper 安装依赖 npm 和网络:npm 12 会提示
install-scripts被阻断,但node-pty自带 prebuilds,通常不影响 helper 运行。Node/npm 由 fnm、nvm、volta 等管理时,插件会探测其常见目录;也可用remoteNode指定绝对路径。 - 本地镜像副作用:
mirrorWorkspace: true会在本机创建与远端同路径的目录(只建目录,不建文件);如果远端路径在本机不可创建(如/root),添加工作区会失败而不是登记一个不存在的路径。 - 会话深链是尽力而为:标记 5 分钟过期、读取即删;远端会话已删除或客户端过慢时只打开远端窗口,不会定位到会话;在面板点击会话时若 helper 尚未安装,会先显示失败与安装提示。
- 混合模式不覆盖所有子系统:只有
fs/subprocess/sandbox被路由;搜索用本地 ripgrep、@候选按本地镜像扫描、LSP/open-in-app/spill 仍按本机实现。需要完整远端语义请用独立远端窗口。 - 混合模式的 cwd 是镜像路径:模型看到的工作目录是本地镜像路径,绝对远端路径在同一会话内仍可用;排查时注意区分两个命名空间。
故障排查
| 现象 | 排查 |
|---|---|
| 侧栏没有「远程 SSH」 | 确认 bundle 已加入 profile、Host 已重启;浏览器强刷一次客户端资源 |
| 导入列表为空 | 检查 ~/.ssh/config 的 Host 是否含通配符(通配符不会导入)、ssh -G <alias> 是否成功 |
| 保存主机失败 | 检查别名是否重复、端口/路径是否合法;服务端会回滚并保留原文件 |
| 测试连接失败 | 先用终端执行 ssh -v <alias>;注意 ProxyCommand 中的代理是否可用 |
| 提示 helper 未安装 | 确认远端 Node/npm 可用、npm registry 可达;fnm/nvm/volta 安装会自动探测,仍失败时设置 remoteNode 或按对话框命令手动执行 |
| 窗口启动超时 | 查看「详情」中的日志尾部;常见原因是远端 helper 崩溃、官方 SSH 行未激活或 Host 密钥校验失败 |
| 远端窗口能打开但文件/终端不可用 | 检查远端 workspace 是否可写;查看日志中 ssh、fs-ssh、subprocess-ssh 是否 pending/报错 |
| 主机密钥严格校验失败 | 先让插件用 accept-new 完成首次连接,或手动 ssh <alias> 写入 known_hosts |
开发与验证
npm test # 单元测试 + sshd 夹具集成测试
npm run verify:static # 静态结构/清单/语法检查
npm run verify:client # 客户端契约与 locale 一致性
npm run verify:docs # README/架构文档一致性
npm run verify:e2e # 使用测试夹具的端到端编排检查
node verification/live-e2e.mjs --alias <alias> --version 0.2.1-rc.2 # 可选:真实 SSH 主机的完整打开流程
node verification/live-remote-window.mjs --alias <alias> --version 0.2.1-rc.2 # 可选:真实远端窗口 UI(目录选择器 + 会话深链 + 复用窗口)
实现细节见 docs/architecture.md。测试夹具见 tests/rig/README.md。
许可
本项目使用 MIT 许可证,版权归 junjiangao 所有。
Comments
Loading…
Similar plugins
by telagod
dsh-plugin: SSH hosts, workspace bindings, and remote exec/sync/compose for DeepSeek Harness
★ 0
MIT
JavaScript
Sep 11, 2026
dsh plugin --profile web add dsh-ssh-workspace-managerby ZhangFengshun
DSH web plugin: VSCode Remote-SSH-like remote development (SSH, remote workspace, file explorer, integrated terminal)
★ 48
↓ 2.1k/wk
MIT
JavaScript
Nov 3, 2026
dsh plugin --profile web add @zhangfengshun/dsh-remote-sshby yh4922
A remote workspace plugin for DeepSeek Harness (DSH). It manages SSH hosts inside DSH, opens remote terminals, lets you browse and edit remote files and inspect remote Git, and adds remote directories as workspaces, so the Agent's file operations and commands run on the remote machine.
★ 13
NOASSERTION
TypeScript
Oct 30, 2026
dsh plugin --profile web add @yh4922/dsh-workspaceby hcyinnn
SSH tools plugin for DeepSeek Harness (dsh): run remote commands and transfer files via OpenSSH. dsh 插件——让 Agent 通过 SSH 在远程主机执行命令、上传/下载文件。
★ 0
MIT
TypeScript
Sep 1, 2026
dsh plugin --profile web add dsh-tool-sshby hehehe1234567894
DeepSeek Harness (DSH) SSH 远程工作插件 — 纯远程模式:多机管理、工作区选择、远程文件读写工具
★ 0
JavaScript
Sep 1, 2026
dsh plugin --profile web add deepseek-harness-sshby lance-kanglu
Local SSH bridge plugin for DeepSeek Harness (DSH) — password via browser page, agent exec via localhost API, OpenWrt router management
★ 0
MIT
JavaScript
Aug 16, 2026
dsh plugin --profile web add dsh-ssh-bridge