多机远程工作区:管理多台 SSH 主机,在原生「添加工作区」流程里选本机系统文件夹或远程目录,把远程工作区镜像成真实本地文件夹并用 rw_* 工具操作。选择器是居中弹窗,默认落在本机页签,远程路径自动预填 `/` 并逐级自动补全目录。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-remote
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:flymysql/dsh-remote
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English · 中文
dsh-remote
由 @flymysql 维护 · 博客 · 讨论区 · Issue · English
官方 Desktop 兼容适配(实验性,尚未发布)
本分支增加对 DeepSeek 官方 Desktop
的适配,以 0.1.5-rc.2 Host 通信协议验证,不修改 Harness 核心:
- 通过
ctx.connection.fetch注册/api/dsh-remote/*,由 Desktop 的dsh-app:通道承载请求,鉴权仍由宿主负责,不启动 Web Server。 - 通过
sidebarRightTabs和sidebar.right.pane.tab提供原生“远程文件”入口, 复用原来的文件树与编辑器,不把远端路径传给本地文件预览器。 dsh-better-sidebar不再内置;Web 版可以单独安装,官方 Desktop 则使用 原生右侧栏集成。
已验证 Host 启动、IPC 请求、真实 SSH 的只读连接/目录列表/文本读取,以及设置页和
测试 SSH 配置的导入。v0.8.19 起侧栏 /ls /read /write /fs 在请求带
sessionId 时按该会话的镜像绑定选机(与 rw_* 同一套),不再落到「当前机器」
连接池;宿主侧测试覆盖双机会话路由与编辑 409/重读/保存。原生文件标签的完整 GUI、
失败/取消交互、非 macOS 宿主以及旧 Web 版完整 UI 回归仍属实验性。
Desktop 安装器还可能要求明确配置 ssh2 / cpu-features 可选构建脚本策略。
隔离验证中禁用了这些可选脚本;本改动不放宽应用的构建白名单,也不自动批准脚本。

为 DeepSeek Harness(DSH)打造的远程工作助手。
维护多台 SSH 机器,然后在「选择工作区」时选一个远程工作区(或本地工作区),Agent 就能在不离开 harness 的情况下直接操作——列文件、读代码、在远程主机上跑构建/命令,并把远程目录镜像成一个真实的本地工作区对象。
DSH 的 Web 界面刻意只监听 127.0.0.1(CLI 为安全拒绝 --host 0.0.0.0)。本插件反过来:由你主动连出到你维护的机器,选一个工作区,然后通过 DSH 原生的工作区 + 文件流来工作——不改动 dsh-workspace 核心。
界面预览
设置 → 远程工作区 —— 多机 SSH 列表(增/删/改/设为当前,密码本地保存、不回显):
原生 「Add workspace / 选择工作区」 流程 —— 居中弹窗、两个 tab,默认落在「本机」;切到 「远程」:
- 远程 —— 一个机器下拉;路径输入框自动预填
/并实时补全目录(点选一个目录后立即列出它的下一级,像系统/VSCode 逐级选目录);另外有**「浏览…」浮窗**,选中仅回填到输入框(不直接提交),你复核 / 修改后点「设为远程工作区」。
真实截图(机器已打码为占位):
功能
- 多机 SSH —— 可存任意多台主机(host/port/user + 私钥或密码)。密码只存在本地,界面不回显;在设置里一键切当前机。每机可配 passphrase / 主机指纹策略 / SSH agent / keyboard-interactive(OTP)/ 跳板机,以及可选的 系统钥匙串加密密码。
~/.ssh/config别名(实时解析,不存副本) —— 机器可以只保存一个 Host 别名(useSshConfig):主机名/用户/端口/私钥/跳板机每次连接都从~/.ssh/config实时解析,改配置立刻生效、无需重新导入;注册表里不存这些值的副本(私钥只引用路径,永不读内容)。支持 OpenSSH 语义:Host a b多别名、*/?通配、!取反、Include(含通配、相对~/.ssh)、行尾\续行、以及 ssh_config(5) 的首个取值优先**规则。设置页「从 ~/.ssh/config 导入」列表里点别名即按别名保存(也可以「复制字段」成普通机器);列表与机器行都会显示 别名 → 实际解析到哪台机,ProxyJump多跳、ProxyCommand等插件无法照做的事会显式告警**而不是静默降级。- 双 tab 工作区选择器(填充原生「Add workspace」流程):
- 本机 —— 走 host 端原生系统文件夹对话框选本地目录(或直接输入本地路径)→ 直接成为普通 DSH 本地工作区(与本地工作区共存)。优先用 DSH 的
directoryPicker服务,服务缺失时回退到插件自持的原生选择器(macOSosascript/ Linuxzenity→kdialog)——桌面启动路径上框架服务不注册也能用。 - 远程 —— 选择器是居中弹窗(窄侧边栏也不会被挤压)。先选机器 → Windows 主机根级显示 「此电脑」多盘视图(
C:\、D:\、E:\…,而不是 Git Bash 的 MSYS 根),路径框实时补全目录(支持C:\Users\…或/c/Users/…任意写法,Windows 路径在底层自动改写为 Git Bash 形式);选中一个目录立即列出它下一级(OS/VSCode 式级联)。另有 「浏览…」文件选择式浮层(Windows 面包屑此电脑 / C:\ / Users / dev可点击跳级、驱动器行、大小/时间、跟随软链),选中回填输入框不提交**,你复核/修改后再确定;「回上一级」任意深度可用(包括浮层直接打开在路径栏当前路径时)。最近工作区快捷入口、~主目录、新建目录一键可达。确定会创建真实本地镜像($DSH_HOME/remote-workspaces/<host>-<user>-<port>/<basename>;仅当同主机上别的远端路径已占用同名 basename 时才追加短路径 hash)→ harness 把它当真实工作区收养,同时 dsh-remote 通过 SFTP 保持同步。所选工作区会持久化到该机器**,重启不丢。
- 本机 —— 走 host 端原生系统文件夹对话框选本地目录(或直接输入本地路径)→ 直接成为普通 DSH 本地工作区(与本地工作区共存)。优先用 DSH 的
- Git Bash 默认终端(Windows 主机) —— 自动探测远程平台(
cmd /c ver,附uname -s的 MINGW/MSYS 探测兜底);Windows 机器自动定位 Git Bash(config.shell可显式指定或native关闭),所有命令经bash -s从 SSH 通道 stdin 管道执行,不依赖 cmd/PowerShell,也不受引号/反斜杠转义困扰;rw_exec默认在 Git Bash 形式的 cwd(/c/Users/…)下执行。/dsh-remote/status、rw_info、设置页「测试连接」都会报告检测到的平台与 shell。 - Windows 路径自动改写 —— 用户输入
C:\Users\dev\project(或C:/…、/c/…、/C:/…)时底层自动规范为 Git Bash 形式/c/Users/dev/project执行;工作区存储与展示为 Windows 形式C:\Users\dev\project。模型工具全部接受并展示两种写法;SFTP 访问使用 Win32-OpenSSH 的/D:/…形式(见toSftpPath)。 - 远程
@补全(issue #39) —— 远程会话里输入@会列出远端目录树(走 SFTP 实时读,不是本地镜像)。目录逐级下钻、无斜杠时在整棵树上模糊匹配,候选是相对远程工作区根的路径(@src/main.c),与本地会话的写法一致;rw_*工具接受这种相对路径并自动拼到远程工作区根上。索引有预算保护(条目/目录/时限 + 缓存 + 失败熔断),远端不可达时自动回退到本地镜像(不会静默变成空列表)。本地会话完全不受影响。 - 双向 SFTP 同步(三路冲突检测) ——
rw_sync(远程→镜像)、rw_push(镜像→远程)。两边都改过的文件会列出冲突、绝不静默覆盖(force=true覆盖)。默认 深度 8 / 2000 文件,触顶会标明TRUNCATED。支持 dry-run、后台任务、gitignore 风格 ignore 规则。 - 模型工具(20 个) ——
rw_info、rw_connect、rw_pick_workspace、rw_list_dir、rw_stat、rw_read_file(utf-8/gbk)、rw_write_file、rw_edit(字面替换 + mtime 乐观锁)、rw_append、rw_mkdir、rw_remove、rw_move、rw_exec、rw_search(POSIX 优先 rg/grep,否则 SFTP 遍历)、rw_download/rw_upload、rw_forward、rw_sync、rw_push、rw_disconnect。 - 端口转发面板 —— 设置页或
rw_forward创建/启停本地与反向隧道。 - 侧栏远程编辑 —— 远程文件 tab 可编辑并保存到远端(mtime 乐观锁)。v0.8.19 起文件操作按会话绑定机器。
- 命令审计 ——
rw_exec/写/删/移动/转发写入audit.log;设置页显示最近 30 条。 - 连接体检 —— 设置页「测试连接」按类别提示(认证 / 网络 / 主机指纹 / 超时)。
- 当前
user@host:/path会注入每次系统提示,让 Agent 明确自己的工作根。 - 远端跨平台 —— 文件访问走 SFTP 协议(不依赖 POSIX shell),Linux/macOS/Windows 远端都能列/读/写/搜索/同步。
- 主机指纹校验(TOFU) —— 每次 SSH 连接都校验主机密钥(
hostKeyMode: accept-new):首次连接记录,之后密钥一旦变化立即拒绝(防中间人)。verify模式还会拒绝从未见过的机器;off关闭校验。指纹存于$DSH_HOME/remote-workspaces/known_hosts.json;误判可用/remote forget-key重置。 - 数据跟随 Harness 根目录 —— 机器清单与镜像放在
$DSH_HOME/remote-workspaces(桌面版即userData/harness下);0.6 之前落在~/.dsh/remote-workspaces的数据首次启动自动迁移,不丢失。 - 不改任何
dsh-workspace官方代码 —— 全部作为普通插件实现(client 半以priority -100填充 directory-flow holes)。
安装
dsh plugin add dsh-remote # 添加 bundle
从 v0.8.18 起,dsh-remote 只安装并挂载自身。Web 侧边栏
(dsh-better-sidebar)
改为可选,不再是依赖,也不会被自动挂载。这样 SSH 工具和设置页不再被某个侧边栏
实现的版本/API 变化拖垮。
如需 Web 版远程文件浏览/编辑,请显式安装两个 bundle:
dsh plugin add dsh-remote
dsh plugin add dsh-better-sidebar
独立侧边栏 service 存在时,dsh-remote 会动态发现它并注册远程文件 tab;
不安装时,rw_* 工具、设置页、同步、审计日志和端口转发均照常工作。
官方 Desktop 使用原生右侧栏,不需要安装 dsh-better-sidebar。
从 0.7.2–0.8.17 升级: 升到 0.8.18 后,内嵌侧边栏依赖和挂载会消失。 只有仍需要 Web 侧边栏 UI 时才单独安装
dsh-better-sidebar。旧 profile 里针对id: dsh-remote-sidebar的覆盖可以删除,因为这行已不存在。
(或 npm install dsh-remote,再在 cordis.patch.yml 加 - id: dsh-remote / name: dsh-remote。)
快速上手
- 加一台机器 —— 设置 → 远程工作区 → 填 host/port/user + 密码或 key →(可选)设为当前。
保存 ≠ 激活(v0.8.8+):保存的机器只是备用连接,不会自动进入任何 session 的 remote context。只有「设为当前」(或 Agent 显式调用
rw_connect)才激活当前机器; 「取消设为当前」可回到active remote = none。 - 选工作区 —— 点侧边栏/会话的 Add workspace:
- 本机 → 系统文件夹选择(或输入本地路径)→ 本地工作区。
- 远程 → 选机器 → 浏览到远程目录(或输入
/path)→ 「设为远程工作区」⇒ 创建并收养一个本地镜像工作区。
- 让 Agent 工作 —— 把它当普通工作区用:
rw_list_dir(path?)/rw_read_file/rw_stat—— 查看远程文件rw_write_file/rw_edit/rw_append—— 创建、补丁、追加远程文件rw_mkdir/rw_remove/rw_move—— 管理远程路径rw_search(pattern, path?)—— 远程 greprw_exec(command, cwd?)—— 在远程执行命令(默认在工作区目录)rw_forward—— SSH 隧道rw_sync/rw_push—— 冲突感知的镜像拉取/推送
Remote context 是 session 级的(v0.8.8+):system prompt 只会在当前 session 的 cwd 位于某个远程 mirror 内(即你把远程目录选成了这个 session 的工作区)时注入 「Remote workspace」段落;普通本地 session 不注入、侧边栏「远程文件」也不显示任何 机器默认目录,模型不会主动调用
rw_*。混合访问(本地 + 远程同屏比较)请通过显式 选择远程工作区进行。
可选:CLI 默认机
可在 cordis.patch.yml 提供默认机:
# 示例:请换成你自己的机器
- id: dsh-remote
name: dsh-remote
config:
host: 203.0.113.10 # 或你的真实主机 / hostname
port: 22
username: dev
privateKeyPath: ~/.ssh/id_rsa
# 或用密码登录:
# password: '…'
workspace: ~/project
若 host 为空,插件启动时处于断开状态,在 UI 里配置机器即可。
常用命令(安装 / 查看 / 启动)
DSH 的 dsh 可能不在某些 shell 的 PATH(比如 Windows PowerShell 里在某个仓库目录下),所以同时列出 dsh 与 npx 两种写法。操作都要用 --profile <name> 指定 profile(一般 web):
# 安装(从 npm 拉到 profile)
dsh plugin --profile web add dsh-remote
# 同一效果:当 `dsh` 不在 PATH 时用 npx
npx --yes @deepseek-ai/dsh plugin --profile web add dsh-remote
# 确认已装
dsh plugin --profile web list
npx --yes @deepseek-ai/dsh plugin --profile web list
# 启动 web 界面(重载 profile,新插件在启动时生效)
dsh --profile web
npx --yes @deepseek-ai/dsh --profile web # 访问 http://127.0.0.1:3080
# 迭代用本地源码替换 npm 版(便于改 dsh 插件代码后即测)
npx --yes @deepseek-ai/dsh plugin --profile web add D:/path/to/dsh-remote
npx --yes @deepseek-ai/dsh plugin --profile web remove dsh-remote # 恢复用发行版
启动成功后,设置 →「远程工作区」会出现;「Add workspace」流程会带「本机 / 远程」两个 tab(见上方效果图)。
开发(沙箱优先,勿改产品)
迭代一律在沙箱里做,绝不手工改产品 profile——产品 profile 由插件管理器重管, 重装会把手工部署的文件还原掉。用仓库内的辅助脚本:
scripts/dev-run.sh --restart # 启动 / 重启隔离沙箱
scripts/dev-run.sh --stop # 停止
scripts/dev-run.sh --status # 是否在运行
- 自带一套独立 DSH 实例(仓库内
dev-harness/harness),把lib/复制进沙箱 profile——与桌面 App 走同一条bin.js web --patch启动路径,沙箱即产品启动行为。 - 沙箱 web UI 在
http://127.0.0.1:50599,插件路由立即可见(如GET /dsh-remote/machines)。 - 宿主半改动(
lib/index.js)需重启沙箱(--restart);客户端半改动 (lib/client.js)只需刷新页面。 - Node ESM 按导入文件的真实路径解析依赖,脚本用硬链接拷贝(
cp -al)把lib/复制进沙箱 profile,而不是软链——软链会破坏@deepseek-ai/*的解析。 - 每次提交前跑
scripts/check.mjs(静态框架约束闸门:命令名正则等);scripts/boot-smoke.sh用隔离实例证明插件仍能启动。 - 完整规则见
scripts/dev-standards.md(命令名、cordis 服务只许ctx.get()、 可选框架服务可能压根不注册、三方库回调契约以真实运行为准等)。
部署到产品 profile 是单独的受控动作(./sync.sh),只在确定要发布时做。
配置
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
host |
string | '' |
默认 SSH 主机(空=断开) |
port |
int | 22 |
默认 SSH 端口 |
username |
string | '' |
默认 SSH 用户 |
password |
string | '' |
默认 SSH 密码(非空覆盖 key) |
privateKeyPath |
string | '' |
私钥路径(仅在显式提供时使用) |
workspace |
string | '' |
默认远程工作区路径 |
shell |
string | '' |
远程命令终端策略:''=自动检测(Windows 找 Git Bash)、'git-bash'=优先 Git Bash、'native'=不包装、其他=显式 bash.exe 路径(如 C:\Program Files\Git\bin\bash.exe) |
commandTimeoutMs |
int | 20000 | 单条远程命令超时 |
connectTimeoutMs |
int | 15000 | SSH 连接超时 |
maxFileBytes |
int | 52428800 | 镜像同步时跳过超过该大小的文件(0=不设上限) |
hostKeyMode |
string | accept-new |
主机指纹策略:accept-new(首次信任)、verify(拒绝未知主机)、off(跳过校验) |
fileReference |
bool | true |
远程 @ 补全:远程会话的 @ 列出远端目录树(issue #39);关闭则只有本地镜像 |
fileReferenceMaxResults |
int | 20 |
一次 @ 查询最多返回多少候选 |
fileReferenceMaxEntries |
int | 3000 |
一棵远程工作区索引最多保留多少条目 |
fileReferenceExcludedDirectories |
string[] | [.git, node_modules, dist, build, out, coverage, target, .next, .nuxt, .turbo, .venv, __pycache__, .pytest_cache, .mypy_cache, .gradle] |
远程 @ 遍历跳过的目录名 |
fileReferenceTimeoutMs |
int | 4000 |
一次远程索引遍历的墙钟预算(超时用已扫到的部分结果,不让光标等) |
安全提醒
把机器凭据交给插件,等于允许 Agent 以你的用户身份在主机上执行 shell 命令。只添加你可信的机器。密码保存在本机文件里,请当作敏感数据处理(可收紧文件 ACL)。
License
MIT
参与贡献
欢迎贡献,请先阅读 CONTRIBUTING.md。使用问题、环境配置、「支持 XX 吗」这类讨论请走 讨论区;可复现的缺陷请提 Issue。
感谢以下已合并 PR 的贡献者:
@dahaipeng (#31) · @YiHui-Liu (#28) · @nekomona (#24) · FoolishWiser (#17) · @jace1cch (#16) · @Minggle (#10) · 4FMTWRV (#6) · glzhangzhi(per-session SSH 连接池修复)
变更记录
见 CHANGELOG.md。
链接
同类插件
Tencent/WeKnora#dsh-weknora★ 30675
把 WeKnora 知识库接入 dsh 的四个只读工具:列出知识库、混合检索原文片段、按顺序还原单篇文档,以及直接取用 WeKnora 自己带引用的 RAG 或 ReAct agent 回答(含可续聊的 session id)。
superdesigndev/treg★ 3596
给 Agent 的工具目录:按「要做的事」检索约 2,600 个外部接口(SEO 与 SERP、外链、社交、人物与公司信息补全、广告库、抓取),查看参数与单次调用价格后直接调用,凭据由服务端注入。附带技能,MCP 行在未设置 TREG_TOKEN 前保持禁用。
TencentCloudBase/CloudBase-AI-Toolkit#dsh-plugin★ 1126
把腾讯云 CloudBase 后端接入 DeepSeek Harness——在对话里搭好并部署全栈应用,查询结果渲染为表格卡片(分页、排序、导出 CSV),部署后可预览真实域名,并提供 CloudBase MCP 工具集(`mcp__cloudbase__*`),登录走 device-code 流程。
gitroomhq/postiz-agent#dsh-postiz★ 496
通过 MCP 将 DeepSeek Harness 连接到 Postiz:列出已连接的社交媒体渠道、获取各平台发帖规则,并向 X、LinkedIn、Instagram、Facebook、Threads、TikTok、YouTube、Reddit、Bluesky、Mastodon、Discord、Slack、Telegram 等平台排期、存草稿或发布帖子;附带 postiz 工作流技能。
EthanYoQ/Invoice-Downloader#dsh-invoice-downloader★ 446
面向 DeepSeek Harness 的本地 IMAP 发票下载、OCR 识别、归档与 Excel 报销汇总。
anysearch-team/anysearch-dsh★ 430
基于 AnySearch 的实时网页与垂直搜索插件,为 DeepSeek Harness 提供搜索工具。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。