前言¶
DeepSeek Harness(DSH)要求工作区对应本机上一个真实存在的目录,而很多日常开发、运维任务实际跑在远端 Linux 上。若只靠本机 Shell 或单独开 SSH 客户端,agent 会话与「当前在哪台机器、哪个目录」容易脱节;同时连接多台服务器时,还存在命令误发到别的主机的风险。下面介绍社区插件 dsh-plugin-ssh(维护者 JeremyLyc,MIT 许可证,当前 package 版本 0.4.0),它用工作区绑定、原生会话工具与侧栏面板,在 DSH Host 与远端之间架桥。
这是什么¶
dsh-plugin-ssh 面向 DSH 桌面版:为 DeepSeek Harness 提供 SSH 远程工作区——会话级 agent 工具(ssh_exec / ssh_upload / ssh_download / ssh_workspace)、左侧「SSH 远程」面板、右侧「服务器文件」页签、目录选择与密码弹窗,并在输入框下方用 composer pill 显示 agent 实际工作的目录(例如 prod:/srv/app 或本地工作区路径)。
架构上,浏览器侧 lib/index.js 经 HTTP /ssh-panel/api/* 调用 Host 侧 lib/ssh.js(ssh2)连服务器;lib/tools.js 注册原生工具,按工作区绑定取主机。仓库在 GitHub:JeremyLyc/dsh-plugin-ssh;社区目录页:skillhub.cn 条目。分类为客户端插件。
核心功能¶
会话工具(无 host 参数)¶
模型可直接调用四个工具,均不接受 host 参数——目标主机只来自当前会话工作区下的 .dsh-ssh-workspace.json 绑定:
| 工具 | 作用 |
|---|---|
ssh_exec |
在绑定主机上执行命令,返回 stdout/stderr/退出码;可选 workdir、timeoutMs |
ssh_upload |
本地文件经 SFTP 上传到绑定主机(自动建父目录) |
ssh_download |
从绑定主机 SFTP 下载到本地 |
ssh_workspace |
回报当前绑定的主机、登录目录与远端工作目录 |
非零退出码以 [exit code: N] 返回,不算工具错误;超时会向远端发 KILL 并标 [timed out after Nms]。
隔离:一个会话只碰自己的服务器¶
插件在工具契约层面限制跨机误操作:工具签名里没有 host,也没有 defaultHost 兜底;每次调用由 exec.agent 读工作区目录下的 .dsh-ssh-workspace.json。未绑定的普通工作区会直接拒绝;绑定指向配置里不存在的主机会拒绝,不会回退默认主机。
README 说明:MCP 路径(server.mjs)拿不到会话身份,可能接受任意 host 别名,因此不要与原生工具同时启用 MCP 条目,否则可能绕过隔离。原生工具因能拿到 exec.agent 而适合做隔离。
侧栏与远程工作区¶
- 左侧栏「SSH 远程」:选主机、执行命令、传文件、一键创建远程工作区。
- 右侧栏「服务器文件」:浏览服务器任意目录、预览文本、切换工作目录。
- 远程工作区:本地占位目录 +
.dsh-ssh-workspace.json+ 自动生成的AGENTS.md;切换远端目录时只替换AGENTS.md里<!-- dsh-ssh:root -->标记块内的说明,不重复追加。 - 密码弹窗:主机未配置密钥或密码时才询问;密码经
setRuntimePassword只存在于 Host 进程内存,不写文件,DSH 重启后需重新输入。
HTTP 端点(面板用)¶
端点 kind: exact,仅接受本机/渲染进程请求,拒绝非回环地址。主要包括:GET /ssh-panel/api/hosts、POST /ssh-panel/api/connect、POST /ssh-panel/api/exec、上传/下载、建工作区、读绑定、切换 root、ls、read 等(下载 ≤64 MB,读文本 ≤512 KB)。
安装与启用¶
前置:DSH 桌面版(profile 目录 ~/.dsh/profiles/desktop)、Node.js 20+。
- 克隆插件并安装依赖:
git clone https://github.com/JeremyLyc/dsh-plugin-ssh ~/.dsh/plugins/dsh-plugin-ssh
cd ~/.dsh/plugins/dsh-plugin-ssh && npm install --omit=dev
- 让 desktop profile 链接该包:
cd ~/.dsh/profiles/desktop
pnpm add "link:$HOME/.dsh/plugins/dsh-plugin-ssh" --ignore-scripts
- 在 profile 的
package.json里把包名加入dsh.profile.bundles(包内cordis.patch.yml会插入ssh-panel条目,注册面板与四个会话工具):
{
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-plugin-ssh"]
}
}
}
- 日志出现
ssh-panel: workspace-scoped tools registered (…)与ssh-panel: endpoints registered at /ssh-panel/api即表示 Host 侧就绪;客户端 bundle 改动后需刷新 DSH 窗口。
兼容性说明:作者在 DSH Desktop 0.2.1-rc.3 上验证(依赖 sidebar.panellist、conversation.composer.dock 等 slot)。依赖包括 ssh2、@modelcontextprotocol/sdk、zod。
配置主机¶
配置文件默认路径 ~/.dsh/ssh-hosts.json,可用环境变量 DSH_SSH_HOSTS 指定;会与 ~/.ssh/config 合并。示例:
{
"defaultHost": "prod",
"hosts": {
"prod": {
"host": "10.0.0.10",
"port": 22,
"username": "deploy",
"privateKeyPath": "~/.ssh/id_ed25519",
"remoteRoot": "/srv/app"
},
"legacy": {
"host": "10.0.0.11",
"username": "ops",
"password": "${LEGACY_SSH_PASSWORD}"
}
}
}
常用字段:host / port / username(或 user)、privateKeyPath(支持 ~)、password / passphrase(支持 ${ENV})、hostKeySha256、strictHostKey、connectTimeoutMs(默认 10000)。未配私钥且无密码时会尝试 id_ed25519 → id_rsa → id_ecdsa。
配置里已有密钥或密码则连接时不弹窗;都没有则面板弹密码框。若在 JSON 里写密码,请注意文件权限。
典型用法¶
- 按上文安装并配置
ssh-hosts.json。 - 在「SSH 远程」面板选择主机、验连;必要时在弹窗输入密码。
- 使用「一键建远程工作区」:在本地生成占位目录与绑定文件,并在该工作区打开会话。
- 在对话中让 agent 调用
ssh_exec等工具;README 建议在AGENTS.md生成的远端目录块基础上,对ssh_exec显式传workdir与远端工作目录一致。 - 用右侧「服务器文件」浏览、预览、切换远端工作目录;输入框下方 pill 会跟随当前目录。
开发侧可运行仓库内测试,例如 node test/tools-isolation.mjs 校验隔离契约;需已配置主机时设置 DSH_SSH_TEST_HOST 等环境变量(见 README「开发」一节)。
适用场景与注意¶
适合:已在用 DSH 桌面版、需要在对话里操作固定远端 Linux(部署、查日志、传文件),且希望多台服务器之间由工作区绑定隔离的场景。
务必注意:
- 面板与工具能执行任意远端命令,能力等价于本机
ssh;HTTP 端点虽限制回环来源,仍应只在本机可信环境使用。 - 插件在 DSH Host 进程权限下运行;安装前请阅读源码与 MIT 许可证,自行评估风险。
- 命令输出与文件内容会进入模型上下文;上传/下载有体积上限(下载 64 MB、请求体 96 MB)。
- 社区目录 skillhub.cn 为独立生态站点,与 DeepSeek / 幻方无官方从属关系;插件星标等以 GitHub 页面为准(README 展示为社区 star 徽章)。
结尾¶
dsh-plugin-ssh 把「DSH 必须是本地目录」与「agent 在远端干活」统一到远程工作区绑定与无 host 参数的原生工具上,并辅以侧栏文件浏览与密码内存策略。需要细节、截图与 issue 时,见 GitHub 仓库 README 与 SkillHub 目录页。