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

远程 SSH 工作区 Very12345/dsh-ssh-workspace

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

通过 SSH 在远程电脑上打开并编辑 DSH 项目

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

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

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

状态速览

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

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

验证判据与等级说明 →

可信度证据

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 48 处,展示前 44 条)
  • 写入本地文件
    src/index.js:22
    case 'local-mkdir':{validateFolderName(input.name);if(typeof input.path!=='string'||!isAbsolute(input.path))throw new Error('Select an absolute local
  • 读取本地文件
    src/index.js:53
    const directory=await opendir(path);let truncated=false;
  • 读取本地文件
    src/index.js:55
    if(!entry.isDirectory()&&!(entry.isSymbolicLink()&&(await stat(resolve(path,entry.name)).catch(()=>null))?.isDirectory()))continue;
  • 发起网络请求
    src/client.js:1079
    const rpc=async (input,signal)=>{let r;try{r=await fetch('/plugins/ssh-workspace',input?{method:'POST',headers:{'Content-Type':'application/json'},bod
  • 读取本地文件
    src/provider/config.js:27
    source = await readFile(absolute, "utf8");
  • 写入本地文件
    src/provider/config.js:176
    await mkdir(dirname(absolute), { recursive: true });
  • 读取本地文件
    src/provider/config.js:179
    const current = await readFile(absolute);
  • 写入本地文件
    src/provider/config.js:192
    await appendFile(absolute, lines.join("\n"), "utf8");
  • 读取本地文件
    src/remote-sandbox.js:46
    const binary=await readFile(new URL('./assets/linux-'+arch+'/landlock-run',import.meta.url));
  • 发起网络请求
    src/client-source.js:58
    const rpc=async (input,signal)=>{let r;try{r=await fetch('/plugins/ssh-workspace',input?{method:'POST',headers:{'Content-Type':'application/json'},bod
  • 写入本地文件
    src/provider/manager.js:160
    if (this.mapper !== void 0) mkdirSync(this.mapper.localWorkspace, { recursive: true });
  • 执行外部命令来自配置/变量
    src/provider/manager.js:272
    const child = spawn(this.config.sshExecutable, [
  • 执行外部命令来自配置/变量
    src/provider/manager.js:301
    const tunnel = spawn(this.config.sshExecutable, [
  • 执行外部命令来自配置/变量
    src/provider/manager.js:328
    const child = spawn(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
  • 读取本地文件
    src/provider/manager.js:525
    async lstat(path, opts, signal) {
  • 发起网络请求
    src/provider/manager.js:1009
    await client.request("createTerminal", {
  • 发起网络请求
    src/provider/manager.js:1034
    if(spec.signal?.aborted) {await client.request("disposeTerminal",{channel:terminalUri}).catch(()=>{});terminalCreated=false;return finish({exitCode:nu
  • 发起网络请求
    src/provider/manager.js:1043
    await client.request("disposeTerminal", { channel: terminalUri }).catch(() => {
  • 发起网络请求
    src/provider/manager.js:1103
    if (terminalCreated) await client.request("disposeTerminal", { channel: terminalUri }).catch(() => {
  • 读取本地文件
    src/provider/manager.js:1314
    const stored = JSON.parse(await readFile(resolve2(this.entry.aliasRoot, "..", "catalog.json"), "utf8"));
  • 读取本地文件
    src/provider/manager.js:1327
    const names=await readdir(directory).catch(error=>{if(error.code==="ENOENT")return [];throw error;}),removed=[];
  • 读取本地文件
    src/provider/manager.js:1328
    for(const file of names){if(!/^[a-f0-9]{64} json$/.test(file))continue;const value=JSON.parse(await readFile(resolve2(directory,file),"utf8"));if(typ
  • 读取本地文件
    src/provider/manager.js:1460
    try{const info=await lstat(target);if(info.isSymbolicLink() || !info.isDirectory())return false;await rmdir(target);return true;}
  • 删除本地文件
    src/provider/manager.js:1460
    try{const info=await lstat(target);if(info.isSymbolicLink() || !info.isDirectory())return false;await rmdir(target);return true;}
  • 读取本地文件
    src/provider/manager.js:1468
    else {try{await lstat(alias);retained++;}catch(error){if(error.code!=="ENOENT")throw error;}}
  • 写入本地文件
    src/provider/manager.js:1608
    await mkdir(resolve2(tmpdir(), "dsh-ssh"), { recursive: true });
  • 写入本地文件
    src/provider/manager.js:1616
    await mkdir(aliasPath, { recursive: true });
  • 写入本地文件
    src/provider/manager.js:1836
    await mkdir(directory,{recursive:true});
  • 写入本地文件
    src/provider/manager.js:1838
    const pending=file+"."+randomUUID3()+".tmp";await writeFile(pending,JSON.stringify({aliasPath})+"\n",{mode:0o600});await rename(pending,file);
  • 写入本地文件
    src/provider/manager.js:1838
    const pending=file+"."+randomUUID3()+".tmp";await writeFile(pending,JSON.stringify({aliasPath})+"\n",{mode:0o600});await rename(pending,file);
  • 执行外部命令来自配置/变量
    src/provider/manager.js:1888
    const child = spawn2(transport.executable, [...transport.args, "-O", "exit", target], {
  • 写入本地文件
    src/provider/spill.js:144
    if (this.mapper !== void 0) mkdirSync(this.mapper.localWorkspace, { recursive: true });
  • 执行外部命令来自配置/变量
    src/provider/spill.js:237
    const child = spawn(this.config.sshExecutable, [
  • 执行外部命令来自配置/变量
    src/provider/spill.js:266
    const tunnel = spawn(this.config.sshExecutable, [
  • 执行外部命令来自配置/变量
    src/provider/spill.js:293
    const child = spawn(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
  • 写入本地文件
    src/provider/subprocess.js:146
    if (this.mapper !== void 0) mkdirSync(this.mapper.localWorkspace, { recursive: true });
  • 执行外部命令来自配置/变量
    src/provider/subprocess.js:239
    const child = spawn(this.config.sshExecutable, [
  • 执行外部命令来自配置/变量
    src/provider/subprocess.js:268
    const tunnel = spawn(this.config.sshExecutable, [
  • 执行外部命令来自配置/变量
    src/provider/subprocess.js:295
    const child = spawn(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
  • 执行外部命令来自配置/变量
    src/provider/subprocess.js:478
    spawn(spec) {
  • 发起网络请求
    src/provider/subprocess.js:690
    await client.request("createTerminal", {
  • 发起网络请求
    src/provider/subprocess.js:718
    await client.request("disposeTerminal", { channel }).catch(() => {
  • 发起网络请求
    src/provider/subprocess.js:755
    await this.client.request("disposeTerminal", { channel: this.channel }).catch(() => {
  • 发起网络请求
    src/provider/subprocess.js:787
    await this.client.request("disposeTerminal", { channel: this.channel }).catch(() => {
扫描于 2026/11/5(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

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

DeepSeek Harness 的远程 SSH 工作区,支持发现 SSH 配置并选择项目

README

由 DeepSeek 最新模型翻译生成
DSH SSH Workspace 通过 SSH 在远程 Linux/macOS 电脑上使用 DSH 项目。本机负责界面和会话,远端负责项目文件、搜索和 Bash 命令。 使用 在 DSH 插件页面用 GitHub 地址安装: https://github.com/Very12345/dsh-ssh-workspace 也可以用官方 CLI 向指定配置档安装: dsh plugin --profile desktop add github:Very12345/dsh-ssh-workspace 包里已提交可运行的 JavaScript,用 Git URL 安装不需要 prepare、postinstall 或构建脚本。最低宿主接口为 DSH 0.2 系列,Node.js 22.15 及以上。 1. 在系统终端确认 ssh 你的别名 可以免交互登录,主机密钥已确认;加密密钥需要先加入 ssh-agent。 2. 打开 设置 → 远程工作区,从 SSH config 添加电脑,或者手动填写地址、用户名、端口。支持密钥文件路径和跳板机。 3. 首次连接点击 初始化环境。
展开完整文档(README 剩余 1 节)
DSH SSH Workspace

通过 SSH 在远程 Linux/macOS 电脑上使用 DSH 项目。本机负责界面和会话,远端负责项目文件、搜索和 Bash 命令。

使用

在 DSH 插件页面用 GitHub 地址安装:

https://github.com/Very12345/dsh-ssh-workspace

也可以用官方 CLI 向指定配置档安装:

dsh plugin --profile desktop add github:Very12345/dsh-ssh-workspace

包里已提交可运行的 JavaScript,用 Git URL 安装不需要 prepare、postinstall 或构建脚本。最低宿主接口为 DSH 0.2 系列,Node.js 22.15 及以上。

1. 在系统终端确认 ssh 你的别名 可以免交互登录,主机密钥已确认;加密密钥需要先加入 ssh-agent。
2. 打开 设置 → 远程工作区,从 SSH config 添加电脑,或者手动填写地址、用户名、端口。支持密钥文件路径和跳板机。
3. 首次连接点击 初始化环境。插件从微软官方下载固定版本 VS Code CLI 1.140.0,保存到远端 ~/.dsh-ssh-workspace,运行 Agent Host;无需安装 VS Code 桌面界面,也无需在远端安装 DSH。下载及运行环境遵循 Microsoft VS Code Server 条款。
4. 新建项目时,在 选择工作区目录 标题旁的下拉框中选择 本机电脑 或 SSH 电脑,沿用原有目录浏览器浏览目录并点击 打开。本机和 SSH 使用同一个界面,不再弹出选择电脑的中间窗口。
5. 远程项目使用 Bash,并沿用 DSH 原生的 只读 / 工作区内修改 / 完全访问 会话权限。普通项目操作无需切换到完全访问;超出权限的操作仍走工具层原生审批,单次批准不修改会话默认值。标准/创造/PTC 使用原生 Bash 提权参数;极简沿用官方持久终端的会话权限切换机制。

SSH config 由系统 OpenSSH 解释连接选项,包含 Host、Include、IdentityFile、ProxyJump。通配符不会作为可选电脑;未找到的别名可手动添加。可以在设置页指定另一份配置文件。插件只读 SSH config,不写回它,不读取私钥内容,不保存密码。

目录浏览器沿用官方 DSH 的双栏布局、面包屑、路径编辑、新建文件夹和隐藏文件开关。插件只在标题旁加电脑下拉框;SSH 电脑名称后的状态点以灰色表示未连接或未知、黄色表示连接中、绿色表示已连接、红色表示断开,悬停可查看状态说明。打开列表不会主动连接,选择 SSH 后才按原有逻辑连接并浏览目录。手动添加与初始化电脑在设置页完成。

行为与边界

- 标准、创造/cordis、PTC 和极简模式均提供远程 Bash;PTC 保持 run_code 工具呈现方式,极简模式保留持久 Shell 状态。
- 文件读写和原生 glob / grep 在远端执行。远端需要 Bash、curl、tar 和 rg;Linux x64/arm64、macOS Intel/Apple Silicon 是初始化支持的架构。
- 本机项目继续调用 DSH 原有沙箱执行器。只给远程会话安装工具覆盖,其他工具、原生审批及本机目录选择保留。
- 原生终端面板在远程会话中启动远端 Bash,支持输入、输出和窗口尺寸调整;本机会话保留原有 Shell。AHP 无法完整观察后台作业,远程终端活动状态保守报告为未知,不根据输出或静默推断空闲。
- 远程文件与 Bash/持久终端执行同一会话策略。只读禁止写入;工作区内修改允许项目目录和远端临时目录;完全访问按 SSH 账户权限执行。会话切换及单次原生审批的范围保持不变。
- Linux 在远端探测 Bubblewrap,不可用时使用随包提供、经过摘要校验的 DeepSeek 官方 Landlock runner 0.1.2;macOS 使用 Seatbelt。runner 上传到远端插件缓存,不需 sudo 或修改系统安全设置。沙箱不可用时受限命令会明确报错,不会自动升级权限。旧内核的部分隔离状态沿用官方探测结果,并通过命令结果报告。
- 远程项目的 AGENTS.md / CLAUDE.md 规则发现以所选远端项目目录为边界,不沿本机占位目录向上查找项目根;本机项目继续使用原有发现规则。
- 每个远程项目对应一个本机占位目录。它用于 DSH 工作区身份和会话记录,不会把远程文件同步到本机。项目显示名称包含电脑名称。
- 侧栏删除远程工作区时,会同步移除 SSH 目录映射并保存删除标记,刷新或重启不会重新注册该项目。远端项目文件和 DSH 会话日志保留;插件仅移除本机空占位目录,非空目录和自定义目录不会递归删除。
- 移除电脑会停止其连接并撤销工作区执行路由,保留 DSH 项目/会话历史与占位目录;以后访问这些项目会明确报错,不会转为本机执行。
- 已维护的 Git Bash 开关仅作用于本机项目,远程项目由本插件接管,避免两个插件注册同名工具。
- 桌面操作和浏览器插件仍控制 DSH 所在的本机。远端 Windows、文件实时监听、SSH 密码弹窗和远程桌面不在本版本范围内。
- Agent Host 采用 AHP 0.9 协议;自带其他版本的运行环境遇到不兼容会报错。初始化使用已验证的固定 CLI 版本。

连接和映射保存在 DSH home 的 ssh-workspace/catalog.json,占位目录位于 ssh-workspace/projects/。独立删除标记保存在 ssh-workspace/deleted-projects/,即使旧进程把目录配置写回旧快照,也不会在下次启动时恢复已删除的项目。这些属于本地用户数据,不进仓库。

设置页的“远程项目”可以移除单个项目;“清理本机残留”只尝试删除已撤销映射的空占位目录。目录视图和工具输出里的本地占位路径是远端文件的地址映射,不代表项目文件已复制到本机。附件、预览及会话日志属于宿主管理的数据,不由此按钮清除。

远程工作区的文件夹图标右上角显示连接状态:灰色未连接、黄色连接中、绿色已连接、红色已断开。悬停状态点可查看说明。本机工作区不加标记。状态每 5 秒自动刷新,请求最多等待 4 秒,超时后显示状态未知并继续重试。窗口恢复显示或重新获得焦点时立即刷新,不需点击工作区;旧请求的迟到结果不会覆盖新状态。已有 AHP 连接每 15 秒做一次只读心跳,心跳最多等待 4 秒;状态查询不启动新的 SSH 连接,也不等待卡住的初始化任务。断开后,下次项目操作会按原有连接逻辑尝试恢复。
从 0.1.11 起,连接优先复用插件目录中已验证的 VS Code Server 1.140.0 缓存,再尝试已有的其他兼容缓存;只有缓存不可用时才进入在线 CLI 启动,单次最多等待 45 秒。自定义 CLI 路径仍优先使用用户配置。普通 SSH 登录成功并不代表 Agent Host 就绪:远端 DNS 或微软下载站不可用也会阻止新环境启动,但不应阻止兼容缓存的使用。不会修改系统 DNS、关闭主机密钥校验或中断其他 SSH 会话。

开发与验证

这是独立仓库,不属于父目录 npm workspace。

npm ci --ignore-scripts
npm run setup-sdk
npm test
npm run build:client
npm run smoke:ui
npm pack --dry-run

setup-sdk 临时安装测试用 DSH SDK 并恢复清单,运行依赖和锁文件保持独立。UI 测试在 Windows 默认使用已安装 Edge;其他平台先运行 npx playwright install chromium。也可以设置 DSH_UI_BROWSER_CHANNEL。截图只保存于忽略的 .tmp/ui/。

经明确授权后可运行真实 SSH 测试(只在随机 /tmp 目录写入并清理):

$env:DSH_SSH_TEST_TARGET='你的测试别名'
node test/live-smoke.mjs

实现与验证记录 包含传输来源、路由设计、维护修改及联调范围。

许可

本插件的原创代码为 MIT。src/provider/ 中的传输代码基于 Yan-Zero/dsh-remote-ssh 的 Apache-2.0 源码快照;目录浏览器组件来自 DeepSeek 官方 DSH 0.2.0-rc.2,MIT 许可见 DIRECTORY-BROWSER-LICENSE。原始版本、修改范围及许可见 NOTICE 和 PROVIDER-LICENSE。Linux Landlock 预编译 runner 的许可见 LANDLOCK-LICENSE,配套审计源码许可见 LANDLOCK-SOURCE-LICENSE。不分发 Microsoft VS Code 二进制文件。

设置页采用紧凑的行间距与分区留白,保持原生正文字号。侧栏及页面标题使用独立 SVG 图标,并随深浅色主题显示。当前宿主的固定齿轮通过插件内、仅限自身导航项的样式适配替换;卸载时恢复,不修改宿主文件。
预览分享卡片长什么样 ↓Very12345/dsh-ssh-workspace
分享 · DeepSeek Harness Hub
Very12345/dsh-ssh-workspace

通过 SSH 在远程电脑上打开并编辑 DSH 项目

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