← 返回列表
未验证
dsh-remote-ssh 插件
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/12 · 已提供中文文档
一个用于 DeepSeek Harness (DSH) 的社区插件:通过 SSH 连接服务器,在那里选择一个文件夹,并使用所有工具在其中工作。与 DeepSeek 无关联。
综合分
29.5
GitHub 分
29.5
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add cmukanisa/dsh-remote-ssh该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-remote-ssh 插件
一个用于 DeepSeek Harness(dsh)的社区插件:
远程 SSH 工作区。
与 DeepSeek 无关联,未获其认可,也未受其支持。“DeepSeek Harness”是
DeepSeek 的商标,此处仅用于说明本插件所基于的技术。
连接一次服务器,选择其中的一个文件夹,然后就在里面工作:智能体在远端使用它已有的
每一个工具来读取、写入、编辑、列出、搜索并运行 shell 命令。连接由每个会话共享,
可以同时连接多台服务器,而这一切都从 设置 → 插件 中开启。
┌──────────────────────── 你的机器 ────────────────────────┐
│ dsh(Web UI、智能体、工具) │
│ ctx.fs ─┐ │
│ ctx.shell ├──► remote-ssh 路由器 ──► ssh (ControlMaster) ──┼──► 服务器
│ ctx.subprocess ┘ │ │
│ └─ 本地路径保留随附的 │
│ 沙箱化提供程序,原样不变 │
└──────────────────────────────────────────────────────────────┘
界面提供 英语、法语和中文,并跟随你的浏览器语言。
用户指南也以同样的三种语言发布。
安装
curl -fsSL https://raw.githubusercontent.com/cmukanisa/dsh-remote-ssh/main/install.sh | sh
或者从克隆安装:
git clone https://github.com/cmukanisa/dsh-remote-ssh
cd dsh-remote-ssh
node install.mjs # 检查、安装、验证、激活
安装即激活插件,并且整个运行是一个事务:它首先检查每一项
要求,然后安装、验证,并且如果任何环节未通过,就回滚到之前的精确状态。
一个安装了一半的插件比没有还糟——加载器要么无法启动该配置,要么启动时
使用一种组合,既禁用了随附的提供程序,又从未注册替代品。
checking
✓ node ·························· v24.14.0 (the harness requires >= 22.19)
✓ ssh ···································· OpenSSH_10.3p1, LibreSSL 3.3.6
✓ tailscale ················ 1.102.3 — the Tailscale SSH transport is available
✓ harness ················································· /Users/you/.dsh
✓ writable ··································· profiles/plugins accepts writes
✓ modules ················· profiles/node_modules/@deepseek-ai/cordis present
installing
✓ copied ········ dsh-remote-ssh → profiles/plugins/dsh-remote-ssh (8 files)
✓ copied ·· dsh-remote-ssh-ui → profiles/plugins/dsh-remote-ssh-ui (4 files)
✓ patched ···································· cordis.patch.yml (8 rows)
✓ enabled ····························· settings.yaml remote-ssh.enabled = true
verifying
✓ 文件 ······················································ 12 个文件已就位
✓ 组合 ·············································· 8 个预期行
✓ 设置 ····································· remote-ssh.enabled = true
✓ 模块 ············· registry.js 导入并导出 RemoteRegistry
──────────────────────────────────────────────────────────────────────────────
0.1 秒内完成。重新加载 harness 页面,然后点击工作区 “+” → “Serveur distant (SSH)”。
三项持久性变更,每次重新运行都保持幂等:
1. 将软件包复制到 $DSH_HOME/profiles/plugins/;
2. 替换 $DSH_HOME/cordis.patch.yml 中它自己管理的块(home 级层,因此每个 profile 都会获得这些行);
3. 写入 $DSH_HOME/settings.yaml,内容为 remote-ssh.enabled: true。
| 标志 | 效果 |
|---|---|
| --keep-off | 以休眠状态安装——适用于激活需单独审计的发布 |
| --enable | 即使上一次运行将其关闭也强制激活 |
| --link | 以符号链接方式引用软件包,而非复制(开发用) |
| --dry-run | 运行检查、报告变更,但不写入任何内容 |
| --no-color | 纯文本输出(同样遵循 NO_COLOR) |
| --uninstall | 移除软件包、组合行以及该设置 |
| --dsh-home DIR | 指定不同的 harness home 目录 |
重新安装绝不会自行翻转已有的 remote-ssh.enabled:该值是你的决定,只有 --enable 才能覆盖它。
要求
- 已安装 dsh(npm install -g @deepseek-ai/dsh),任意 profile 均可。
- Node 22.19+ 或 24+——与 harness 本身要求的范围相同。
- 运行 dsh 的机器上需有 OpenSSH 客户端(ssh -V)。Windows OpenSSH 可作为客户端使用,但不支持连接复用。
- POSIX SSH 服务器(Linux、macOS、BSD)。Windows OpenSSH 服务器会被拒绝并给出明确提示——参见限制。
- 推荐使用基于密钥的认证。仅当配置密码时才需要 sshpass。
- 可选:服务器上的 ripgrep,用于 glob 和 grep 工具。
文档
用户指南以三种语言发布——English、Français、中文——页面会跟随浏览器的语言:
相同内容也以纯 HTML 形式存放在本仓库的 docs/ 中,无需构建步骤。
CONTRIBUTING.md 介绍了如何开发该插件本身。
激活
安装后它已处于激活状态。该开关仍可用于将其关闭:设置 → 插件 → “Workspaces distants (SSH)”。
它控制的是是否提供远程工作区(选择器和侧边栏启动器)。它从不控制路由:已存在于镜像中的会话会持续连接到其服务器,因为静默回退到空的本地镜像比任何错误都更糟。
然后重新加载页面。
使用
1. 点击侧边栏工作区标题中的 +(或侧边栏中的 🖥 按钮
1. 脚,它总是打开同一个对话框)。
2. 选择 Serveur distant (SSH)。
3. + Serveur 并填写连接信息:名称、主机、端口、用户、私钥
路径,或密码。你的 ~/.ssh/config 别名、ProxyJump 和 SSH agent
都能正常工作,因为该插件驱动的是真正的 ssh 二进制文件。
4. 浏览到该文件夹,然后点击 Utiliser ce dossier。
该文件夹会显示为一个普通工作区。在那里打开的会话会在服务器上读取、写入、
编辑、列出、搜索并运行命令。
可以同时连接多个服务器;每个服务器都有自己的镜像,并且
配置文件标签可在同一对话框中切换它们。
比 harness 更持久的工作
agent 循环运行在 harness 内部,因此关闭它会结束该轮次。能够继续工作的是
命令,而将其分离就是全部诀窍:插件会在服务器上写入一个小型启动器,在它自己的会话下启动
它(setsid,或在不可用时使用 nohup),并将其输出发送到那里的日志
文件。
- 随时关闭 harness。 远程进程会继续运行。
- 回来查看它。 设置 → 插件会列出每次运行及其实时状态——正在运行、已结束
并带有其退出码,或已消失——以及其最新输出。
- 想停就停。 正在运行的条目有一个 Stop 按钮;整个进程组都会
收到信号,因此子进程也会随之停止。Forget finished 会清除记录。
每次运行的一条持久记录保存在 $DSH_HOME/remotes-sessions.json 中,由每个会话共享,因此
重新启动的 harness 会重新附加到它从未监视过的工作。
面板读取的内容,从服务器的角度来看
ls ~/.dsh-remote/run/ # 每次运行一个 .sh、.pid、.started、.log、.status
更新
重新运行安装程序。它会重写自己的组合块,其结尾行
会说明正在运行的 harness 需要以下两件事中的哪一件:
- 当只有 浏览器部分 发生变化时,重新加载页面:该 bundle 由
dsh-client-hmr 轮询的字节提供,因此新的 bundle 就是新的修订版;
- 当 宿主部分(lib/.js)发生变化时,重启 harness(dsh web)——
Node 的 ESM 加载器会保留它启动时加载的模块——或者当 包被
重命名* 时:dsh-client-modules 以其启动时读取的名称作为表的键,并
继续以旧 id 提供新的 bundle,因此每次页面加载都会失败并显示
loaded without registering。安装程序会检测到这两种情况并说明。
node install.mjs # 或再次使用 curl 一行命令
配置
设置($DSH_HOME/settings.yaml)
remote-ssh:
enabled: true # 设置 → 插件开关
connectTimeoutMs: 20000 # 每次 ssh 调用
strictHostKeyChecking: accept-new # accept-new | yes | no
accept-new 是默认值:新主机在首次使用时被信任,而 已更改 的
主机密钥始终会被拒绝。
配置文件($DSH_HOME/remotes.json,权限 0600)
由安装程序的对话框写入。它保存连接详细信息,包括一个
如果你提供了密码——这就是文件以 0600 创建的原因。
镜像($DSH_HOME/remotes//…)
真实的空本地目录。删除一个,远程文件夹不受影响;镜像会在下一次列出或采用时重新创建。
组合行
参见 patch/remote-ssh.patch.yml.tpl。它们指向绝对路径,因为行的相对说明符是相对于 profile 目录解析的,而这一层由每个 profile 共享。
Tailscale
有两件不同的事情都被称为“通过 Tailscale 连接”,插件有意将它们区分开来。
通过 tailnet 使用 OpenSSH——无需配置。 将 profile 指向 MagicDNS 名称(build-a.example-tailnet.ts.net)或 100.x.y.z 地址,真正的 ssh 二进制文件就会通过 WireGuard 连接。你的密钥、你的 ~/.ssh/config 和你的 known_hosts 仍然是权威。这是默认行为,且保持不变。
tailscale ssh——按 profile 选择启用。 在连接表单中选择 Tailscale SSH。Tailscale 客户端随后会包装系统 ssh,这带来三个好处:
- 即使使用 --accept-dns=false 也能进行 MagicDNS 解析;
- 通过 tailscaled 可达,因此在用户空间网络模式下也能工作;
- 目标主机密钥会与协调服务器为该节点公布的主机密钥进行验证,这在你正常的主机密钥策略之上。
访问随后由 tailnet ACL 和身份控制,而不是由磁盘上的 SSH 密钥控制。适配器从不自行切换传输方式:看起来像 MagicDNS 的主机会被报告为 tailnet 目标(profile 标签上的 🌐),但除非 profile 指定 tailscale(⚡),否则会通过普通 OpenSSH 连接。
连接表单还会列出你 tailnet 的对等节点,读取自 tailscale status --json:点击一个即可填入 MagicDNS 名称、tailnet 用户,以及——当该对等节点公布 SSH 主机密钥并因此运行 Tailscale SSH 服务器时——Tailscale SSH 传输方式。Tailscale 报告为离线的对等节点会在尝试前被指出,而不是在二十秒后以连接超时的形式出现。
插件读取的内容,如果你想自己查看
tailscale status --json | jq '.Peer[] | {HostName, DNSName, Online, sshHostKeys}'
要求:运行 dsh 的机器上要有 tailscale CLI(可用 DSH_TAILSCALE_BIN 覆盖)。没有 Tailscale 的机器会将 tailnet 报告为不可用,其他一切照常工作。
路径如何路由
| 输入 | 世界 | 备注 |
|---|---|---|
| /srv/app/x.ts | 远程 | 日常情况:会话 cwd 及其文件 |
| ssh:///srv/app/x.ts | 远程 | 显式 URI,可在任何接受路径的地方使用 |
| /srv/app/x.ts | 本地 | 远程路径绝不会根据其形态被猜测 |
| 其他任何内容 | 本地 | 随附的提供程序,保持不变 |
包含关系遵循本地沙箱:read-only 拒绝所有远程变更,而 workspace-write 拒绝任何规范镜像路径不属于以下范围的远程目标
在每次调用的工作区根目录下。该检查是对远程 realpath 进行规范化后再做包含判断,因此它保持了与本地围栏相同的保证。
为什么这样构建
dsh 中的工作区是一个真实的本地目录:会话头携带规范的本地 cwd,工作区注册表在创建时对路径执行 realpath,侧边栏通过该规范路径解析会话。与其为所有这些再教一套路径词汇,远程文件夹获得一个本地镜像——位于 $DSH_HOME/remotes// 的一个真实但为空的目录——文件系统提供程序将其下的每个路径转换为其所镜像的远程路径。
因此,文件系统之上的所有内容都保持不变地继续工作,包括那些绕过 ctx.fs 的部分。
该插件替换了三个能力提供程序,每个都用一个子类,对本地路径逐字保留出厂行为:
| 提供程序 | 本地行为 | 远程行为 |
|---|---|---|
| ctx.fs | dsh-fs-sandbox(读/写/编辑/列表/状态,策略围栏) | 通过 SSH 进行读取、原子写入、字面编辑、列表、字节窗口 |
| ctx.shell | dsh-bash-sandbox(超时、输出上限、溢出文件、后台范围) | 相同的生命周期,以 ssh 作为程序 |
| ctx.subprocess | dsh-subprocess-local | 相同的受管范围,经过路由——这正是让 glob/grep 能远程工作的原因 |
限制
- 仅支持 POSIX 服务器。 远端使用 POSIX shell 源码驱动(sh -c、stat、realpath、mv、head/tail)。Windows OpenSSH 服务器会被拒绝,并给出明确说明的消息,而不是半可用地运行。
- 远程命令不受限制。 ctx.shell 的限制(bwrap、Seatbelt)是同内核设施;通过 SSH 时,账户自身的权限就是边界。远程运行不会报告任何沙箱事实,因为没有应用任何沙箱。上文描述的文件系统围栏确实会被强制执行。
- glob 和 grep 需要服务器上有 ripgrep。 当它缺失时,工具会以可操作的消息失败,而不是返回错误结果。
- 没有文件监视。 侧边栏的文件树在导航时刷新,而不是在远程变更时刷新。
- 镜像目录可能遮蔽同名的本地路径。 $DSH_HOME/remotes/ 下的路径始终属于其配置文件。
- process.cwd() 相对的工具在智能体的 shell 内可以工作,但那些在 ctx.fs 之外硬编码本地文件系统访问的工具(例如读取文件的钩子)看到的是空镜像。
故障排除
| 症状 | 原因和修复 |
|---|---|
| does not answer as a POSIX host | 一个 Windows SSH 服务器。请使用 Linux/macOS 主机,或将该机器的 WSL sshd 暴露在其自己的端口上。 |
| ControlPath too long | 通过插件不会发生(它会缩短路径),但 ~/.ssh/config 中手写的 ControlPath 仍可能触及 104 字节的 AF_UNIX 限制。 |
| Permission denied (publickey) | 先手动运行 ssh ;插件使用相同的客户端、代理和配置。 |
| 主机密钥已更改 | 插件会拒绝,这是正确的。确认无误后,从 known_hosts 中删除过时的行。 |
| glob/grep 提示程序不可用 | 在服务器上安装 ripgrep(apt-get install ripgrep、dnf install ripgrep、apk add ripgrep)。 |
| 在仅本地工具中工作区不显示任何文件 | 该工具绕过了 ctx.fs,因此它看到的是空镜像。 |
| 更新后出现 Failed to load plugins … loaded without registering "…dsh-remote-ssh-ui" | 正在运行的 harness 仍持有它在启动时读取的包标识。重启 dsh web;仅重新加载页面是不够的。 |
测试
npm run deps # 符号链接 harness 包(一次)
npm run check # 解析器 + 打包包装器检查
npm run test:unit # 无需 SSH
npm run test:harness # 针对正在运行的 harness
npm run ssh:up # 在 127.0.0.1:2223 上的 docker OpenSSH 目标
npm run test:e2e # 通过真实 SSH 测试文件系统、shell 和子进程
npm run ssh:down
CI 矩阵在 Linux、macOS 和 Windows 上跨受支持的 Node 版本范围(22.19+ 和 24+;harness 不支持 Node 20)运行单元测试套件;针对 Alpine 服务器、Debian 服务器、macOS 服务器和 Windows 服务器(其拒绝行为会被断言)运行端到端测试套件;以及一次完整的 harness 启动,其中会演练浏览器包和 Remote 命名空间。参见
CONTRIBUTING.md。
Guide rapide (français)
Installer — curl -fsSL .../install.sh | sh,或 node install.mjs。
Activer — Paramètres → Plugins → « Workspaces distants (SSH) » → cliquer
« Désactivé »。然后重新加载页面。
Utiliser — 侧边栏的 + 按钮 → « Serveur distant (SSH) » →
+ Serveur(主机、端口、用户、私钥或密码)→ 浏览 →
Utiliser ce dossier。该文件夹会成为普通工作区:读取、写入、编辑、搜索和 shell 命令都在服务器上执行。
多个服务器可以同时连接,并对所有会话保持可用。
作者
由 Christian Kasse(@cmukanisa)构建——请参阅
贡献者
了解所有提供过帮助的人。欢迎贡献;请从
CONTRIBUTING.md 开始。
许可证
MIT。扫码进群