dsh-plugin-remote-access
只把本机 DSH 网页界面开放给指定的一个网段(默认 Tailscale 100.64.0.0/10),不绑 0.0.0.0:网段外的对端一律拒绝,进入方式可选带票网址或 4–12 位数字/字母访问密码;远程页面可强制手机布局而不动本机界面,官方「通用设置」里的外观 / 字号大小 / 工作步骤展示 / 显示代码工作视图 / 性能与用量可存进本插件配置,并在每次打开远程页面时重新套用。
安装
dsh plugin --profile web add dsh-plugin-remote-access
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-plugin-remote-access
[English](README.en.md) · 中文
给 DeepSeek Harness(DSH)桌面版用的插件:把本机 DSH 的网页界面只开放给你指定的网段
(默认 Tailscale 的 100.64.0.0/10),于是手机或另一台电脑也能用上它。
- 不绑
0.0.0.0:只监听「允许网段」里属于本机的地址,网段外的对端一律403。 - 不写死地址:网段、监听地址、端口、上游、落地文件全是配置项。
- 两种进入方式:复制带令牌的网址;或者设一个密码,手机开裸地址输一次(之后 30 天免密)。
- 手机界面能看:手机布局只作用于远程页面,本机界面一个像素都不动。布局本身交给 DSH 官方的
dsh-client-ui-layout(窄屏时它自己就是「无轨道 + 模态抽屉 + 右栏全屏浮层」),插件只补手势、
返回键与输入区样式。
- 手机上的外观/字号只改手机:「UI 设置」把外观与字号存进本插件配置,每次打开远程页面只投影到本页 DOM,
不写电脑的设置文档。DSH 0.2.1 起官方设置会跨端写宿主,因此「工作步骤展示 / 显示代码工作视图 / 性能与用量」
不再由本插件远程覆盖(它们跟随电脑设置),设置页里会如实写明。
- 适配 DSH 0.2.1:
engines.dsh = ^0.2.1-rc.1;上游地址自动读webServer.getOrigin(),
跟随桌面端系统分配端口与原生 HTTPS;Host/Origin 改写在两种协议下都正确。
- 在设置页里改:保存即热重载(原地关掉旧监听、按新参数重开),不用重启 DSH。
- 配置只有一个来源(1.5.0 起):只认本用户的
$DSH_HOME/remote-access-config.json。
插件不读也不写共享 profile 的 cordis.patch.yml;设置页走本插件自己的
/__remote_access__/config 端点读写这份 JSON。多个用户共用一份 profile 时端口各用各的,
被占用还会自动换一个空闲端口并记住。
- 失败可见:无论成功失败都会写一份自诊断文件,看不到 DSH 日志时也能定位。
安装
三种方式,选一种即可;装完重启一次 DSH。
版本要求:本版(1.4.0 起)只适配 DSH 0.2.1+(engines.dsh = ^0.2.1-rc.1,
覆盖0.2.1-rc.1/0.2.1-rc.2与后续 0.2.x)。DSH 0.2.0 及更早版本请用1.3.8。
dshmarket 会按这个字段显示「支持/不兼容」,安装前也能看到。
发布记录:GitHub Releases
(每个版本的说明与 APK)· npm
(插件包,latest 就是当前版本)· [更新日志](#更新日志)。
① 插件页(推荐) —— 打开 DSH →「设置 → 插件 → 添加插件」,填下面任一:
填什么 · 从哪里装
dsh-plugin-remote-access · 从 npm(1.2.0 起已发布,装起来最快)
github:Mzy123l/dsh-plugin-remote-access · 直接从 GitHub(要与仓库同步的最新代码时)
本机某个目录的绝对路径 · 自己 clone / 下载下来时
⚠️ npm 上那两个旧名字 —— dsh-remote-access-cidr(我们自己发的,停在 1.0.0)和
dsh-remote-access(别人的包)—— 都别再用来安装。当前名字是dsh-plugin-remote-access:
<https://www.npmjs.com/package/dsh-plugin-remote-access>。
(页面上那个0.0.0-stage是 npm 给新包名自动建的占位版本,latest才是当前版本,不用管它。)
📛 改名(1.2.0):dsh-remote-access-cidr→dsh-plugin-remote-access。
bundle 的插件行是按包名装载的,所以旧来源装的那份不会自己跟过来:到「设置 → 插件」里把旧条目
移除,再按新名字添加一次。移除有可能一并清掉 profile 里cordis.patch.yml中id: remote-access-cidr
那一行的 config:(网段 / 密码 / UI 设置都在里面)—— 想留参数,先把它抄下来,装好再粘回去。
⚠️ 1.4.1 的 id 迁移(重要):DSH 0.2.1 自己新增了一个 loader 行
id: remote-access(@deepseek-ai/dsh-api-remote-access)。本插件 1.4.0 的行 id 也是
remote-access,两者重名会让官方的remoteAccess服务不挂载,桌面壳启动时报
desktop welcome: Web request failed。1.4.1 起插件行与设置命名空间改为
remote-access-cidr。升级后把旧cordis.patch.yml里id: remote-access的整段
config:挪到id: remote-access-cidr下面(或者到设置页重新填一遍参数)。
② 命令行(等价于插件页那一步;DSH 正在运行时 profile 写锁会占住):
dsh plugin --profile desktop add dsh-plugin-remote-access # 想跟仓库最新代码:dsh plugin --profile desktop add github:Mzy123l/dsh-plugin-remote-access # CLI 若不认这两种写法,就填本机目录的绝对路径
③ GitHub 一键取代码 —— 想把源码放到本机再装:
irm https://raw.githubusercontent.com/Mzy123l/dsh-plugin-remote-access/main/install.ps1 | iex
脚本只负责把代码取到一个固定目录(默认 %LOCALAPPDATA%\dsh-plugins\dsh-plugin-remote-access),
装的动作仍然交给 DSH 自己(插件页填那个目录)。需要代理时:
$s = irm https://raw.githubusercontent.com/Mzy123l/dsh-plugin-remote-access/main/install.ps1 & ([scriptblock]::Create($s)) -Proxy http://127.0.0.1:7890
为什么不一步装完:DSH 的插件安装(写 profile 的package.json/cordis.patch.yml、跑包管理器)
只能由 DSH 自己做(插件页,或让 agent 用 plugin_manager 工具),手工改 profile 容易把它弄坏。
之后改参数都是热重载。改代码分两种:client.js(浏览器半区)刷新页面就会重新拉取;
index.js(宿主半区,含新增配置字段)要重启一次 DSH 才会加载。
安卓 App(APK,可选)
不想在手机浏览器里手打地址的话,可以用配套的外壳 App:
(全部 Release · 源码在 [android/](android/) · 说明见 [android/README.md](android/README.md))
链接指向 Releases 而不是某个固定文件名:APK 名形如 dsh-plugin-remote-access-<版本>.apk,
每抬一次版本都会换名字,钉死某个文件名迟早会落后。要装具体某一版,进 Release 页挑。
APK 与插件不总是同一个号:APK 只在「动了外壳代码」的那一版重发。
当前插件是 1.4.4,APK 仍是 1.4.1(versionCode 16;这一版只有宿主/网页半区改动,
外壳代码没动,不用重装 APK)。
App 名字就叫 DSH,装完图标是那个蓝色看板娘(自适应图标,圆形/方形启动器都正常)。
- 首屏就是地址页:只填
IP或域名:端口(不用写协议,例100.64.0.3:19388),HTTPS 一个勾决定; - 连不上 / 填错 / 电脑没开时自动退回地址页,网页上左侧那枚小胶囊里永远有「设置」——断网也改得回来;
- 返回键整个归外壳管:先关网页里的抽屉 / 右栏 / 设置面板,再网页后退,最后退到后台(不退出 App ——
退到后台才有下面那条「模型提问时提醒你」;真要退出,从最近任务里划掉即可。
细节见 [android/README.md](android/README.md#返回键));
- 模型提问 / 一轮结束都从屏幕顶部弹出来(横幅 / heads-up,像收到一条微信):App 退到后台后由一条
前台服务盯着,只在「电脑上的 DSH 窗口不可见(收进托盘 / 最小化 / 页面已关)」且你不在看 App 时才弹;
见下面「手机通知(提问 / 一轮结束)」;
- 网页仍是电脑上那份 DSH:手机布局、
UI 设置全由本插件的配置决定; - 只申请
INTERNET/ACCESS_NETWORK_STATE/POST_NOTIFICATIONS/FOREGROUND_SERVICE(_SPECIAL_USE),
自签(CN=DSH Remote),同签名的后续版本可直接覆盖安装。
装的时候要允许「安装未知应用」。电脑那端仍然是本插件在监听(默认 19388),App 只是把网页装进壳里。
手机通知(提问 / 一轮结束)
两类通知,各有一个开关、各走一条通道,互不影响(都在「设置 → 远程访问 → 手机通知」里):
通知 · 什么时候响 · 开关 · 通道
模型提问 · 模型问你「要用哪个方案?」这类选择(ask_user_question,计划审阅也在内),且没人回答 · notifyOnChoice · 「模型提问」
一轮结束 · 这一轮跑完了,或者异常结束(模型输出格式错 / 余额、额度不足 / 网络连不上 / 被限流 / 凭据失效 / 上下文超长 / 服务端错误…) · notifyOnFinish · 「任务结束」
两类共用的触发条件与原来一致:电脑上的 DSH 窗口不可见(收进托盘 / 最小化 / 页面已关,
由电脑上那一页自己回报,25 秒心跳)且你没在看手机 —— 两个条件都满足才弹,屏幕上从顶部弹出横幅
(heads-up,像收到一条微信:会响、会震、几秒后收进状态栏),点通知回到 DSH。
- 「跑完了」那条的正文只写结论与用时;异常那条写分类 + 原因是哪个错误(把 DSH 自己的错误码
翻成人话,例如 余额 / 额度不足:insufficient balance),绝不带模型的回答内容
(可能很长,也不该出现在锁屏上)。
- 子任务(subagent)跑完不打扰你:只有「这一轮」的主流程结束才算数。
- 结束的判定走 DSH 自己的事件(
agent/status的running → idle),并带 2 秒防抖 ——
循环里的中间态(维护 / 压缩)不会被误报成「跑完了」。
- 刚跑完那一条有 5 分钟的新鲜窗口:你「在页面上看着它跑完、然后切出去」,照样能收到。
要弹出横幅,Android 那边有四件事必须同时成立,这一版都落实了(细节见
[android/README.md](android/README.md#模型提问时的通知)):通道是 IMPORTANCE_HIGH、
通知本身是高优先级、每次都发一条新通知(更新旧通知不保证再弹),
而常驻的「后台待命」那条故意留在低重要性(它
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:17,最后更新 2026-11-05