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

远程 SSH 工作区 chenqaq123/dsh-remote-ssh

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

在侧边栏连接服务器,直接打开远程项目目录

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · market
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 19 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件
查看扫描证据(共 71 处,展示前 49 条)
  • 读取本地文件
    scripts/profile.mjs:91
    const cli = candidates.find(path => existsSync(path) && lstatSync(path).isFile()
  • 读取本地文件
    scripts/profile.mjs:91
    const cli = candidates.find(path => existsSync(path) && lstatSync(path).isFile()
  • 读取本地文件
    scripts/profile.mjs:92
    || existsSync(path) && lstatSync(path).isSymbolicLink());
  • 读取本地文件
    scripts/profile.mjs:92
    || existsSync(path) && lstatSync(path).isSymbolicLink());
  • 写入本地文件
    scripts/profile.mjs:99
    try { writeFileSync(temporary, text, { mode: 0o600 }); renameSync(temporary, path); }
  • 写入本地文件
    scripts/profile.mjs:99
    try { writeFileSync(temporary, text, { mode: 0o600 }); renameSync(temporary, path); }
  • 删除本地文件
    scripts/profile.mjs:100
    finally { rmSync(temporary, { force: true }); }
  • 读取本地文件
    scripts/profile.mjs:105
    if (!lstatSync(path).isSymbolicLink()) throw new Error(`Refusing to replace a real directory: ${path}`);
  • 写入本地文件
    scripts/profile.mjs:131
    mkdirSync(destination, { recursive: true, mode: 0o755 });
  • 执行外部命令来自配置/变量
    scripts/profile.mjs:133
    const result = spawnSync(npm, ['pack', pluginDir, '--pack-destination', destination, '--json'], {
  • 读取本地文件
    scripts/profile.mjs:148
    if (!existsSync(tarball)) throw new Error(`npm pack did not create ${tarball}`);
  • 写入本地文件
    scripts/profile.mjs:184
    mkdirSync(backup, { recursive: true, mode: 0o700 });
  • 写入本地文件
    scripts/profile.mjs:186
    for (const [name, data] of saved) if (data !== undefined) writeFileSync(join(backup, name), data, { mode: 0o600 });
  • 删除本地文件
    scripts/profile.mjs:213
    if (previousLink !== undefined) rmSync(link);
  • 删除本地文件
    scripts/profile.mjs:218
    if (data === undefined) rmSync(join(dir, name), { force: true });
  • 删除本地文件
    scripts/profile.mjs:221
    if (!installed && existsSync(nativeLink) && lstatSync(nativeLink).isSymbolicLink()) rmSync(nativeLink);
  • 写入本地文件
    scripts/profile.mjs:223
    mkdirSync(dirname(nativeLink), { recursive: true });
  • 读取本地文件
    lib/host-modules.js:68
    if (!existsSync(scope)) continue;
  • 读取本地文件
    lib/mounts.js:83
    text = readFileSync(this.storageFile, 'utf8');
  • 写入本地文件
    lib/mounts.js:123
    mkdirSync(dirname(this.storageFile), { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/mounts.js:130
    writeFileSync(temp, `${JSON.stringify(body, null, 2)}\n`, { mode: 0o600 });
  • 写入本地文件
    lib/mounts.js:131
    renameSync(temp, this.storageFile);
  • 删除本地文件
    lib/mounts.js:132
    } finally { rmSync(temp, { force: true }); }
  • 读取本地文件
    lib/secrets.js:69
    text = readFileSync(this.file, 'utf8');
  • 读取本地文件
    lib/secrets.js:90
    if ((statSync(this.file).mode & 0o077) !== 0) {
  • 写入本地文件
    lib/secrets.js:91
    chmodSync(this.file, 0o600);
  • 写入本地文件
    lib/secrets.js:133
    mkdirSync(dirname(this.file), { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/secrets.js:136
    writeFileSync(temp, `${JSON.stringify(body, null, 2)}\n`, { mode: 0o600 });
  • 写入本地文件
    lib/secrets.js:137
    renameSync(temp, this.file);
  • 删除本地文件
    lib/secrets.js:138
    } finally { rmSync(temp, { force: true }); }
  • 读取本地文件
    lib/ssh-config.js:95
    if (!expanded.includes('*') && !expanded.includes('?')) return existsSync(expanded) ? [expanded] : [];
  • 读取本地文件
    lib/ssh-config.js:100
    names = readdirSync(directory);
  • 读取本地文件
    lib/ssh-config.js:128
    text = readFileSync(resolved, 'utf8');
  • 读取本地文件
    lib/ssh-config.js:215
    if (existsSync(main)) paths.push(main);
  • 写入本地文件
    lib/ssh-runner.js:44
    mkdirSync(directory, { recursive: true, mode: 0o700 });
  • 读取本地文件
    lib/ssh-runner.js:45
    const stat = lstatSync(directory);
  • 写入本地文件
    lib/ssh-runner.js:47
    chmodSync(directory, 0o700);
  • 读取本地文件
    lib/ssh-runner.js:118
    if (!this.helpers.has(path) || !existsSync(path)) {
  • 写入本地文件
    lib/ssh-runner.js:119
    writeFileSync(path, ASKPASS_SCRIPT, { mode: 0o700 });
  • 写入本地文件
    lib/ssh-runner.js:120
    chmodSync(path, 0o700);
  • 执行外部命令来自配置/变量
    lib/ssh-runner.js:222
    child = spawn(this.config.sshBinary, argv, { stdio: ['pipe', 'pipe', 'pipe'], env: this.spawnEnv(target) });
  • 执行外部命令来自配置/变量
    lib/ssh-runner.js:305
    const child = spawn(this.config.sshBinary, argv, { stdio: ['ignore', 'pipe', 'pipe'], env: this.spawnEnv(target) });
  • 执行外部命令来自配置/变量
    lib/ssh-runner.js:386
    const child = spawn(this.config.sshBinary, [...(this.config.sshConfigPaths?.length ? ['-F', this.config.sshConfigPaths[0]] : []),
  • 读取本地文件
    lib/shell-remote.js:131
    const spawn = super.spawnSpec({ ...spec, workdir: existsSync(spec.mount.localDir) ? spec.mount.localDir : process.cwd() }, argv, stdoutMaxBytes, signa
  • 读取本地文件
    lib/workspace-actions.js:19
    try { info = lstatSync(localDir); } catch (error) { if (error.code === 'ENOENT') return; throw error; }
  • 读取本地文件
    lib/workspace-actions.js:20
    if (!info.isDirectory() || info.isSymbolicLink() || readdirSync(localDir).length) {
  • 写入本地文件
    lib/workspace-actions.js:160
    mkdirSync(localDir, { recursive: true, mode: 0o755 });
  • 写入本地文件
    lib/workspace-actions.js:198
    mkdirSync(mount.localDir, { recursive: true, mode: 0o755 });
  • 读取本地文件
    lib/remote-protocol.js:16
    export const REMOTE_SCRIPT = readFileSync(new URL('./remote.sh', import.meta.url), 'utf8');
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
DeepSeek Harness · Remote SSH 在 DeepSeek Harness 桌面侧边栏中连接 SSH 服务器,浏览并选择远程项目目录,直接打开远程工作区。 远程工作区面板 目录选择 选择服务器 → 点击「选择服务器上的文件夹…」→ 打开项目文件夹 →「选择此目录」→「连接并打开」。 连接时可填写「工作区名称」,留空默认使用项目文件夹名。绿点标识远程工作区。 远程目录选择器 环境要求 本地支持 macOS 和 Linux,需要系统 OpenSSH。远端需要 POSIX sh、GNU/BSD stat、readlink、mktemp 等常见命令;执行远程终端命令还需要 bash。目前不支持 Windows/Pwsh。 先在终端确认可以登录服务器(需要密码的服务器也可以,见下文「密码认证」)。示例 ~/.ssh/config: Host dev-server HostName dev.example.com User demo IdentityFile ~/.ssh/id_ed25519 ssh dev-server 上面的服务器地址是示例,请替换为自己的配置。 密码认证 需要密码的服务器可以直接连接:在面板的「密码」里填一次,密码保存在本机,之后自动登录,不必每次输入。
展开完整文档(README 剩余 1 节)
DeepSeek Harness · Remote SSH

在 DeepSeek Harness 桌面侧边栏中连接 SSH 服务器,浏览并选择远程项目目录,直接打开远程工作区。

远程工作区面板

目录选择

选择服务器 → 点击「选择服务器上的文件夹…」→ 打开项目文件夹 →「选择此目录」→「连接并打开」。

连接时可填写「工作区名称」,留空默认使用项目文件夹名。绿点标识远程工作区。

远程目录选择器

环境要求

本地支持 macOS 和 Linux,需要系统 OpenSSH。远端需要 POSIX sh、GNU/BSD stat、readlink、mktemp 等常见命令;执行远程终端命令还需要 bash。目前不支持 Windows/Pwsh。

先在终端确认可以登录服务器(需要密码的服务器也可以,见下文「密码认证」)。示例 ~/.ssh/config:

Host dev-server
HostName dev.example.com
User demo
IdentityFile ~/.ssh/id_ed25519

ssh dev-server

上面的服务器地址是示例,请替换为自己的配置。

密码认证

需要密码的服务器可以直接连接:在面板的「密码」里填一次,密码保存在本机,之后自动登录,不必每次输入。选择远程目录时也会带上这个密码;如果还没填,目录选择器里会内联提示输入一次,保存后重试即可。

- 密码保存在 ~/.dsh/ssh-remote/secrets.json(0600,仅当前用户可读写),可用配置项 secretsFile 改路径;在面板中点「清除密码」即可删除。
- 认证走 OpenSSH 自己的 SSH_ASKPASS 机制:密码不会出现在命令行参数里,ssh 仍然自己完成认证。密码只在建立连接时用到,之后所有操作复用同一条多路复用连接,连接过期后也会用保存的密码自动重建。
- 需要 OpenSSH ≥ 8.4(依赖 SSH_ASKPASS_REQUIRE=force,否则从终端启动 Harness 时 ssh 会去读 /dev/tty)。
- 只有当服务器提供 password 或 keyboard-interactive 认证时才会要求密码;纯密钥服务器仍按原来的方式处理。
- 不支持需要多轮交互的二次验证(例如两次 keyboard-interactive 提示),因为 askpass 每次只回答同一个密码。
- 密码文件是本机凭据:不要提交到仓库或分享给他人,同机同用户下的其他进程理论上可以读取它。

安装

从 GitHub 安装(推荐)

先启动一次 Harness,使 desktop 配置目录存在。然后将插件克隆到希望长期保留的位置:

git clone https://github.com/chenqaq123/dsh-remote-ssh.git
cd dsh-remote-ssh
git checkout v0.5.0
node scripts/profile.mjs install desktop

完全退出并重新打开 DeepSeek Harness,侧边栏会出现「远程工作区」。

作为 npm 包安装

仓库包含完整 npm 包元数据和命令入口,可直接从 GitHub tag 安装,无需等待 npm registry 发布:

npm install -g --install-links git+https://github.com/chenqaq123/dsh-remote-ssh.git#v0.5.0
dsh-ssh-remote install desktop

更新与卸载

更新源码或全局 npm 包后,重新运行安装命令并重启 Harness。卸载 GitHub 源码安装:

node scripts/profile.mjs uninstall desktop

全局包安装可运行 dsh-ssh-remote uninstall desktop,然后再卸载 npm 包。卸载只移除配置区块与插件链接,不删除远程文件或已保存的挂载数据。

移除远程工作区

「移除工作区」会归档相关会话并移除分组和远程映射,保留历史记录及服务器文件。有任务运行时,请先结束任务。

许可证

MIT。社区插件,与 DeepSeek 官方无隶属关系。
预览分享卡片长什么样 ↓chenqaq123/dsh-remote-ssh
分享 · DeepSeek Harness Hub
chenqaq123/dsh-remote-ssh

在侧边栏连接服务器,直接打开远程项目目录

这是你的仓库?认领条目

回到顶部