🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

异地机器工作区 tangwenhao616-netizen/dsh-anywhere

DeepSeek Harness
tangwenhao616-netizen78 天前有提交已提供中文文档扫描:含敏感能力

把 NAT 后的异地机器接入,让 agent 直接读写执行

27.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/16 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add tangwenhao616-netizen/dsh-anywhere
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · dev
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/09/26·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/03·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 78 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 37 处,展示前 37 条)
  • 读取本地文件
    lib/fleet.js:32
    if (!existsSync(p)) return ''
  • 读取本地文件
    lib/fleet.js:33
    const m = readFileSync(p, 'utf8').match(/publicBaseUrl: *( +)/)
  • 读取本地文件
    lib/fleet.js:46
    cloudflaredBin: existsSync(cfBin) ? cfBin : 'cloudflared',
  • 读取本地文件
    lib/fleet-store.js:41
    if (!existsSync(this.path)) return emptyFile()
  • 读取本地文件
    lib/fleet-store.js:43
    const parsed = JSON.parse(readFileSync(this.path, 'utf8'))
  • 写入本地文件
    lib/fleet-store.js:51
    try { renameSync(this.path, `${this.path}.corrupt-${process.pid}-${process.hrtime.bigint()}`) } catch { }
  • 读取本地文件
    lib/fleet-store.js:59
    if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    lib/fleet-store.js:59
    if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    lib/fleet-store.js:61
    writeFileSync(tmp, JSON.stringify(file, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    lib/fleet-store.js:62
    renameSync(tmp, this.path)
  • 读取本地文件
    lib/provisioner-ssh.js:31
    if (!existsSync(this.keyDir)) mkdirSync(this.keyDir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    lib/provisioner-ssh.js:31
    if (!existsSync(this.keyDir)) mkdirSync(this.keyDir, { recursive: true, mode: 0o700 })
  • 读取本地文件
    lib/provisioner-ssh.js:33
    if (!existsSync(opPrivKeyPath)) {
  • 读取本地文件
    lib/provisioner-ssh.js:36
    const operationPublicKey = readFileSync(opPrivKeyPath + '.pub', 'utf8').trim()
  • 读取本地文件
    lib/routes.js:209
    if (!existsSync(file)) return writeJson(res, 404, { error: 'frpc binary not bundled on hub' })
  • 读取本地文件
    lib/routes.js:210
    const buf = readFileSync(file)
  • 读取本地文件
    lib/routes.js:213
    'content-length': statSync(file).size,
  • 读取本地文件
    lib/ssh-host-writer.js:26
    if (!existsSync(path)) return { version: FORMAT_VERSION, hosts: [] }
  • 读取本地文件
    lib/ssh-host-writer.js:27
    const parsed = JSON.parse(readFileSync(path, 'utf8'))
  • 读取本地文件
    lib/ssh-host-writer.js:36
    if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    lib/ssh-host-writer.js:36
    if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    lib/ssh-host-writer.js:38
    writeFileSync(tmp, JSON.stringify(file, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    lib/ssh-host-writer.js:39
    renameSync(tmp, path)
  • 读取本地文件
    lib/ssh-host-writer.js:72
    if (!existsSync(abs)) return
  • 执行外部命令来自配置/变量
    lib/launcher.js:118
    const cf = spawn(bin, ['tunnel', '--url', `http://127.0.0.1:${port}`, '--protocol', 'http2', '--no-autoupdate'],
  • 写入本地文件
    lib/launcher.js:171
    writeFileSync(patchPath, buildWorldPatch(desc, port, url.replace(/^https?: /, ''), mnt))
  • 执行外部命令来自配置/变量
    lib/launcher.js:174
    const dsh = spawn(cmd, [...baseArgs, '--profile', 'web', '--patch', patchPath, '--port', String(port)],
  • 删除本地文件递归
    lib/launcher.js:199
    try { rmSync(w.patchDir, { recursive: true, force: true }) } catch { }
  • 删除本地文件递归
    lib/launcher.js:211
    try { rmSync(w.patchDir, { recursive: true, force: true }) } catch { }
  • 发起网络请求
    lib/launcher.js:249
    const r = await fetch(url, { redirect: 'manual', signal: AbortSignal.timeout(8000) })
  • 写入本地文件
    lib/ssh-conn.js:24
    try { mkdirSync(dir, { recursive: true, mode: 0o700 }) } catch { }
  • 执行外部命令固定命令
    lib/ssh-conn.js:99
    const child = spawn('ssh', [...ttyArgs, ...this._mux(opts.fresh ?? true), this.login, `${envCmd}${cwdCmd}exec ${parts}`],
  • 执行外部命令固定命令
    lib/ssh-conn.js:137
    return spawn('ssh', [...ttyArgs, ...this._mux(opts.fresh ?? true), this.login, cmd], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    lib/ssh-conn.js:142
    const child = spawn('ssh', args, { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    lib/ssh-conn.js:156
    try { spawn('ssh', ['-o', `ControlPath=${this.controlPath}`, '-O', 'exit', this.login], { stdio: 'ignore' }) } catch { }
  • 执行外部命令来自配置/变量
    lib/mount.js:70
    const child = spawn(bin, sshfsArgs(desc, mnt), { stdio: ['ignore', 'pipe', 'pipe'] })
  • 写入本地文件
    lib/ssh-subprocess-core.js:33
    spillStream = createWriteStream(spillPath)
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-fs@deepseek-ai/dsh-subprocess
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 异地机器批量纳管
  • SSH执行环境
  • agent读写执行

把 dsh(DeepSeek Harness)工作区装到任意机器上——一个插件两种模式:NAT 后面的异地机器批量纳管 + SSH 执行环境

README

由 DeepSeek 最新模型翻译生成
dsh-anywhere CI npm version npm downloads license node 把你的 DeepSeek Harness 工作区落在_任意_一台机器上。 把异地机器(哪怕在 NAT 后)拉上线,让 agent 的 read / write / edit / bash / grep 原生作用在那台机器上,而模型、记忆、agent-loop 全留在 hub。 English · 简体中文 flowchart LR subgraph HUB["🧠 dsh hub —— 你的笔记本 / 服务器"] A["模型 · 记忆 · agent 循环"] end subgraph RELAY["☁️ 你的中继 VPS"] R["环回会合点"] end subgraph REMOTE["💻 任意机器 —— 哪怕在 NAT 后"] F["文件 + 进程"] end A -- "① fleet:一次性 token + 反向隧道" --> R R -. "ProxyJump" .-> F A == "② world:ctx.fs + ctx.subprocessread · write · edit · bash · grep 落这里" ==> F 一个插件,两种可组合的模式: - ① fleet —— 够得着。
展开完整文档(README 剩余 1 节)
dsh-anywhere

CI
npm version
npm downloads
license
node

把你的 DeepSeek Harness 工作区落在_任意_一台机器上。 把异地机器(哪怕在 NAT 后)拉上线,让 agent 的 read / write / edit / bash / grep 原生作用在那台机器上,而模型、记忆、agent-loop 全留在 hub。

English · 简体中文

flowchart LR
subgraph HUB["🧠 dsh hub —— 你的笔记本 / 服务器"]
A["模型 · 记忆 · agent 循环"]
end
subgraph RELAY["☁️ 你的中继 VPS"]
R["环回会合点"]
end
subgraph REMOTE["💻 任意机器 —— 哪怕在 NAT 后"]
F["文件 + 进程"]
end
A -- "① fleet:一次性 token + 反向隧道" --> R
R -. "ProxyJump" .-> F
A == "② world:ctx.fs + ctx.subprocessread · write · edit · bash · grep 落这里" ==> F

一个插件,两种可组合的模式:

- ① fleet —— 够得着。 用一次性 token + 反向隧道,把 NAT 后的机器拉进你的 dph,连到_你自己的_中继 VPS。它作为一条 fleet- 的 dsh-ssh 主机出现,用现成的 ssh_exec / ssh_upload 工具操作。
- ② world —— 变工作区。 把任意可达机器变成会话的 ctx.fs + ctx.subprocess,agent 的原生文件/命令工具就作用在它上面。与 dsh 的 E2B 集成同构,只是远端换成任意 SSH 可达的机器。

旗舰组合(就是"异地电脑当工作区"这件事): 先用 fleet 把 NAT 后的机器拉进来,再用 world(-o ProxyJump=)把它升格为整会话工作区。目标本就可达(公网云主机 / 局域网)时,直接用 world、跳过 fleet。

演示

一段真实 agent 会话(经已发布的包驱动),在一台远程机器上干活 —— 命令在那台机器上跑、文件写在那台机器上:

$ dsh --profile headless --patch ./workspace-on-machine.patch.yml \
"跑 'uname -n' 并把 MERGED-WORLD-OK 写进 /tmp/selftest.txt"

▸ bash uname -n
VM-0-16-ubuntu ← 远程主机,不是你的笔记本 ▸ write /tmp/selftest.txt ← 落在远程机器上 MERGED-WORLD-OK

$ ssh you@remote 'cat /tmp/selftest.txt' # 独立核验
MERGED-WORLD-OK

📹 欢迎补一段 /fleet 申请-批准流程的录屏 —— 见 CONTRIBUTING。

快速开始(约 5 分钟)

前置: 可用的 dsh、hub 上有系统 ssh。world 模式还需要一台你已经能 ssh 上去的机器(局域网、云主机,或 fleet 入网的机器)。

1. 安装(peer @deepseek-ai/dsh-fs / dsh-subprocess 由 dsh 提供):

dsh plugin --profile add dsh-anywhere

2a. world 模式 —— 把工作区落到一台可达机器。 复制 examples/workspace-on-machine.patch.yml,填好目标机的 login / sshArgs / cwd,然后:

DSH_PERMISSION_MODE=danger-full-access \
dsh --profile --patch ./workspace-on-machine.patch.yml "在这台机器上干活"

此时 read / write / edit / bash / grep 全部落在那台机器。

2b. fleet 模式 —— 把 NAT 后机器拉上线。 装上即挂载 /fleet 面板。指向你的中继(在 VPS 上跑一次 scripts/relay-init.sh 再登记),点「加机器」,在目标机跑那行命令,回面板批准。详见下方 fleet 模式。

⚠️ 务必正式安装,别 link:。 boot 时 --patch 里的 name: 是相对 profile 目录解析的。用 link: 开发装会让 world 半边因 @deepseek-ai/dsh-fs peer 从仓库 realpath 解析不到而报 ERR_MODULE_NOT_FOUND。用正式安装(dsh plugin add / npm i,peer 由运行时提供),或把真实目录 dsh-anywhere 放进 /node_modules/ 并把 @deepseek-ai/dsh-fs、dsh-subprocess 软链进 /node_modules/@deepseek-ai/(同一 realpath,extends FileSystem 才是同一个类)。fleet 半边零依赖,link: 可用。

两种模式一张表

| | fleet(组网层) | world(执行世界层) |
| 职责 | 让 NAT 后的机器够得着 | 把可达机器变成整个工作区 |
| 机器呈现为 | 一条 dsh-ssh 主机(fleet-) | 会话的 ctx.fs + ctx.subprocess |
| 操作方式 | ssh_exec / ssh_upload / ssh_download / ssh_tunnel | 原生 read / write / edit / bash / grep,落远程 |
| 挂载 | 装插件即常驻(dsh.bundle → cordis.patch.yml) | 每会话 --patch workspace-on-machine.patch.yml |
| 入口 | dsh-anywhere | dsh-anywhere/world |

- 零外部 npm 依赖 —— 文件/进程/隧道都走系统 ssh CLI(路径与内容 base64 进远程脚本,无引号/注入)。@deepseek-ai/dsh-fs、@deepseek-ai/dsh-subprocess 是 peerDependencies,由 dsh 运行时提供。
- 快 —— world 复用一条 OpenSSH ControlMaster 连接,fs 微操作 ≈40ms(不是每次重握手)。这正是让"经隧道在异地机器上干活"流畅可用的关键。
- 可取消 —— 长命令用专用连接,terminate() 断连即由 sshd SIGHUP 远端命令。

fleet 模式 —— 把机器拉上线

1. 配中继(插件不硬编码你的 VPS):在中继 VPS 跑 scripts/relay-init.sh,再经 POST /api/fleet/relay(或 /fleet 面板)登记。
2. 加机器: 面板「加机器」给一行命令 —— 目标机跑 curl /join | bash(Windows:irm '/join?os=win' | iex)。机器显示配对码并挂起。
3. 批准: 核对配对码后在 /fleet 点「通过」(只认本机来源)。机器 sshd 经反向隧道映射到中继环回口,hub 经 ProxyJump 够到它,作为 fleet-* dsh-ssh 主机上线。
4. 列表/吊销:GET /api/fleet/list、POST /api/fleet/approve|reject|revoke。

安全: token 一次性 + 可过期 + 可单台吊销;每台机器独立隧道密钥;机器 sshd 只绑中继环回口、不暴露公网;审批只认本机来源。

world 模式 —— 把机器变工作区

见快速开始 2a。world 提供:

| 能力 | 实现 |
| ctx.fs(FileSystem) | fs-ssh:resolve / stat / lstat / readText / streamText / readBytes / listDir / writeText / editText;版本守卫、原子写、二进制/UTF-8 |
| ctx.subprocess(SubprocessRuntime) | subprocess-ssh:resolveExecutable / spawn(stdin · collect · 退出码 · cwd · env · terminate)/ spawnTerminal(基础 PTY,ssh -tt) |
| bash / grep / 终端 / LSP | 无需改动 —— 它们是 ctx.fs+ctx.subprocess 的 provider-neutral consumer,自动落远程 |

一世界不变式: fs.cwd == subprocess.cwd(补丁 config.cwd)== sandbox-policy.workspaceRoot == 会话工作区,必须同指一个远程目录;否则相对路径与命令 cwd 会落到远端不存在的路径而报 spawn 失败。

Windows 远端: 远端是 Windows(OpenSSH + PowerShell)时,给 ssh-world config 加 platform: windows——fs/subprocess 改走 PowerShell 后端(全 base64、二进制安全)——并把 cwd / workspaceRoot 用 Windows 路径(如 C:\Users\you\work)。默认 platform: posix(Linux/macOS)。已对真实 Windows 主机端到端验证。注意:Windows OpenSSH 会把非零退出码塌掉,精确码经带外标记还原;远端有 rg 才能让 grep 满速。

每实例,非每会话: dsh 执行世界是每实例的(ctx.fs/ctx.subprocess 非 scope-aware)。要同时用本地与远程工作区,就跑两个 dsh 实例(一个本地 profile、一个 world profile)。fleet 模式不受此限 —— 入网机器是 dsh-ssh 主机,可与本地工作区并存。

已知限制(POC 阶段)

- spawnTerminal 为基础 PTY;远端前台进程组精确查询/信号、TERM→KILL 完整静默尚未实现。
- 每次 fs 操作是一次远程往返(ControlMaster 已消掉握手;超大量微操作仍有 per-op ssh 进程开销)。
- 远程需有 rg(ripgrep)才能让 agent 的 grep/glob 满速;缺则降级 grep/find。
- world 的 ctx.fs 未接 dsh 沙箱围栏(用 danger-full-access;围栏交给远端账号本身)。

参与贡献

欢迎 issue / PR —— 见 CONTRIBUTING.md。测试:node --test(集成测试在未设 DSH_ANYWHERE_RELAY=user@host 时自动跳过)。

许可

MIT
预览分享卡片长什么样 ↓tangwenhao616-netizen/dsh-anywhere
分享 · DeepSeek Harness Hub
tangwenhao616-netizen/dsh-anywhere

把 NAT 后的异地机器接入,让 agent 直接读写执行

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部