DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

zhexuany /

zhexuany/dsh-remote-access

Verified

DSH Harness Desktop plugin: expose the local Web GUI to another machine through a secure tunnel (Cloudflare quick/named, SSH) with a tokenised link.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@2b164f50

远程协作 · dsh-remote-access

把这台机器上 DSH Harness Desktop 的 Web GUI(同一批会话、同一个工作区)通过隧道暴露到公网, 在另一台机器上用浏览器打开一条带令牌的链接即可操作,不需要公网 IP、不需要端口转发、不需要改动路由器。

另一台机器的浏览器 ──https──▶ Cloudflare 边缘 ──隧道──▶ 本机 cloudflared ──▶ 127.0.0.1:<Desktop 端口>
                                                                              (DSH Desktop 的 Host 进程)

默认通道是 Cloudflare 快速隧道(cloudflare-quick):免登录、免费、随机域名,每次重启域名都会变。 需要固定域名时用 cloudflare-named(要自己的 Cloudflare 账号 + tunnel token),也可以接 ssh / 自定义 command 通道。 网络互通的场景还可以完全不开隧道,只用 ssh -L(见 §3.3)。

⚠️ 分享链接等同于这台机器的控制权。 链接里带着本进程的 launch token,谁拿到谁就能操作这台机器上的 DSH(跑命令、改文件、读会话)。不要贴到群里、不要提交进 git。不用的时候点「停止」。

源码仓库:https://github.com/zhexuany/dsh-remote-access(问题反馈走 GitHub Issues)。


0. 快速开始(3 步)

插件装进 profile 后(见 §2),运行中的 Desktop 会热加载它,不用重启应用:

  1. 打开 设置 → 远程协作 → 点 启动;或者命令行: ./bin/dsh-remote-access start --home ~/.dsh
  2. 等链接出现 → 点 复制 → 在另一台机器的浏览器里打开。 那里之后 30 天免令牌(cookie 与域名绑定,域名一换就得重新点新链接)。
  3. 不用时点 停止(旧域名立刻失效)。

不需要再在 Desktop 里找「允许在浏览器中打开」这类开关。DSH Desktop 0.2.1-rc.3 已经把它删了 (Host 上不再有 webServer.setBrowserAccess(),desktop-preferences.json 里的 browserAccess 也没人读)。 现在普通浏览器能不能进来只由两件事决定:隧道域名在 connection.trustedHosts 里(插件在隧道就绪时 自动发布、停止时移除),以及链接里带着本进程的 launch token(GET /?token=… 换成 30 天 cookie)。 这两件事插件都替你做了,所以「链接复制出去就能打开」就是这个版本的正常状态。

链接同时落在 <DSH_HOME>/remote-access/link.txt,./bin/dsh-remote-access link 也直接打印它 (同一份输出里还有 本机链接,给 ssh -L 用)。

1. 前置条件

  1. macOS,DSH Desktop 已安装(默认 /Applications/DeepSeek Harness.app)。
  2. DSH Desktop 0.2.1-rc.2 及以上(0.2.1-rc.3 实测)。不再需要任何 Desktop 侧开关:0.2.1-rc.3 移除了 「允许在浏览器中打开」(内部名 browserAccess)和 webServer.setBrowserAccess(),跨机访问改由 connection.trustedHosts(信任隧道域名)+ 链接里的令牌负责,插件已经把这两件事包了。 如果你是从旧插件升级上来的,面板/CLI 里可能还留着一行 browser-access switch failed: …—— 那是旧 Host 进程缓存的历史错误,重启一次 Desktop 就没了(新版本不再记这个错)。
  3. 网络允许出站 443/TCP。如果本机网络屏蔽 UDP/QUIC,保持默认的 protocol: http2; 能走 UDP 时也可以改成 quic / auto。(只走 ssh -L 的话连这条也不需要。)

2. 安装

2.1 GitHub 插件安装(推荐)

先通过官方 Desktop 的 Manage dsh Command… 安装随应用分发的 dsh 命令,然后完全退出 Desktop:

dsh plugin --profile desktop add git+https://github.com/zhexuany/dsh-remote-access.git

插件需要 cloudflared。可以任选一种方式提供:

brew install cloudflared
# 或把二进制放到 <DSH_HOME>/remote-access/bin/cloudflared

重新打开 Desktop,在 设置 → 远程协作 里启动隧道。共享安装默认 autoStart: false,不会自动开公网隧道。

通过 GitHub 安装时,插件源码在 profile 的 node_modules 里;不要再用下面的 bin/install 复制一份。

2.2 本地安装器(开发/离线)

cd /path/to/dsh-remote-access
./bin/install --dry-run     # 先看它会做什么,不写任何东西
./bin/install               # 装进 ~/.dsh/profiles/desktop(默认复制一份快照)

(bin/install 会自动用 DSH Desktop 自带的 Node 运行 bin/install.mjs,没有系统 node 也能用。 写 ~/.dsh 在 workspace 之外,第一次执行需要授权一次全盘访问。)

安装做了五件事:

# 动作 位置
1 把插件目录复制(或软链)进 profile <profile>/node_modules/dsh-remote-access
2 dependencies["dsh-remote-access"] = file:<源目录>(默认 --copy)或 link:<源目录>(--link),并把插件名加入 dsh.profile.bundles <profile>/package.json(先备份成 package.json.bak-<时间戳>)
3 放一份 cloudflared <DSH_HOME>/remote-access/bin/cloudflared
4 (可选,--enable-browser-access)把 browserAccess 置 true——只有 0.2.1-rc.2 及更旧的 Host 会读它,0.2.1-rc.3 已无此开关 <DSH_HOME>/desktop-preferences.json
5 写一段受管的「mux 心跳覆盖」进 profile 补丁(把 Remote-stream 的 2s ping 放宽到 15s,见 §5.1) <profile>/cordis.patch.yml(先备份成 cordis.patch.yml.bak-<时间戳>)

常用选项:

--home <dir>              DSH_HOME(默认 ~/.dsh)
--profile <name>          profile 名(默认 desktop)
--copy | --link           复制(默认,快照)或软链(改代码即生效,适合开发)
--enable-browser-access   顺手在 desktop-preferences.json 里置 browserAccess: true(0.2.1-rc.3 已无人读取,只为旧版本兼容)
--no-cloudflared          不放置 cloudflared(用 PATH 里的或 Homebrew 的)
--heartbeat-ms <ms>       写进 profile 补丁的 mux 心跳间隔(默认 15000;宿主默认 2000 对丢包的公网路径太紧)
--no-heartbeat            不写(或删掉)那段受管心跳覆盖
--uninstall               卸载(只删自己那一条依赖/一个软链,并删掉受管心跳覆盖)
--dry-run / --json

装完怎么生效(2026-10-04 实测):

  • 运行中的 Desktop 会热加载新装好的 bundle:写进 dsh.profile.bundles 后大约 2 秒,Host 就把插件装上了 (日志里直接出现 state dir … / starting cloudflare-quick …),不用重启。
  • 网页界面需要刷新一次才会出现 设置 → 远程协作 面板(面板来自客户端的 client.js,页面已经加载过就不会再拿新 bundle)。
  • 隧道就绪时插件把域名推进 connection.trustedHosts(内存里的围栏,不改写 Desktop 配置),停止时移除; 这一步在任何版本的 Host 上都是热生效的。只有改端口(port)才会触发 「应用访问设置并重启 Host?」并中断正在运行的任务。
  • --copy(默认)装的是快照:改完源码要重跑 ./bin/install;想边改边生效就用 ./bin/install --link。 替换已经装载过的插件代码要重启一次 DSH Desktop——Host 不会重新 import 已经加载过的模块。

3. 使用

3.1 GUI:设置 → 远程协作

面板显示:状态灯(未启动/启动中/已就绪/失败)、本地地址、隧道方式、隧道地址、连接链接(复制 / 打开)、 启动 / 停止 / 重启、「详情」(状态目录、cloudflared 路径、trustedHosts、访问方式 / 探测结果 / Desktop 开关)、日志。

  • 首次使用:点 启动 → 等 5–20 秒出现链接 → 复制 → 到另一台机器浏览器打开 → 该浏览器之后 30 天内免令牌。
  • 面板另有一块 本机链接:配合 ssh -L 用(见 §3.3),复制按钮一键拿走。
  • 面板里有一段常驻说明:这个版本的 Desktop 没有「允许在浏览器中打开」开关,分享链接本身就够用。 它不会给你一个点了也没用的按钮。
  • 每次拉状态时插件会顺手探一次本机端口(带 sec-fetch-site: same-origin 的 GET /):401 = 健康 (Host 只认带令牌的请求)、200/303 = 端口直接放行、403 = 连隧道域名都被拒。出现 403 时面板顶部 会给出红色提示,让你先看 trustedHosts、重启一次隧道再分享;探测结果在「详情」里(access)。

3.2 CLI

./bin/dsh-remote-access status          # 状态、公网地址、分享链接、本机链接
./bin/dsh-remote-access link            # 只打印链接(方便 pbcopy)
./bin/dsh-remote-access link | pbcopy
./bin/dsh-remote-access start|stop|restart
./bin/dsh-remote-access logs            # 最近 200 行(含 cloudflared 自己的输出)
./bin/dsh-remote-access open            # 用本机浏览器打开链接
./bin/dsh-remote-access browser-access             # 兼容入口:说明这个版本的 Host 没有开关、链接已可直接打开
./bin/dsh-remote-access browser-access --enable    # 同上;--enable/--disable 仍然接受,但不再改变任何东西
./bin/dsh-remote-access status --json   # 完整状态 JSON

CLI 通过回环控制套接字(<DSH_HOME>/remote-access/control.json,0600,带进程内令牌)操作正在运行的 Host; Host 不在时退回读取落盘的 state.json / link.txt。 browser-access 保留为兼容入口:0.2.1-rc.3 的 Host 没有开关可翻,所以它只打印「链接已可直接打开」的说明并返回 0 (以前它必须连着 Host,因为那时真的要改 Host 内存里的状态)。

3.3 不想暴露到公网:走 ssh -L

只要两台机器网络互通(同一局域网,或者你能 ssh 到本机),可以完全不开隧道:

# 在另一台机器上执行(8080 换成那台机器上任意空闲端口)
ssh -N -L 8080:127.0.0.1:61733 user@192.168.1.10

然后在那台机器的浏览器里打开面板给出的 本机链接(http://127.0.0.1:<Desktop 端口>/?token=…, 端口看面板「本地地址」)。它不经过 Cloudflare,流量只在 SSH 里。

为什么可行:转发到 Host 的请求是 Host: 127.0.0.1:8080,Origin 与它一致,回环地址本来就在信任围栏里 (connection.trustedHosts 的豁免),而 0.2.1-rc.3 没有别的门槛了——带令牌的链接直接就能打开。 注意 cookie 是按 host:port 绑定签名的:换了 -L 端口就要重新复制一次本机链接;-L 端口的 cookie 和隧道域名的 cookie 互不通用。

4. 安全模型

两层,缺一不可——隧道域名本身不是凭证:

  1. API 信任围栏 connection.trustedHosts:Host 头不在白名单 → 403。Desktop 每次启动都会重写 desktop-next.runtime.patch.json(里面只有回环 + 局域网 IP),所以插件在隧道就绪时把域名推进 内存里的 API 围栏和 Web 运行时围栏;停止时两处都移除;不改写 Desktop 的配置文件。 这一步同时保护 DSH 自带的 Session 文件预览器、/api/file 和侧边栏的 /sidebar/file、/sidebar/html 路由。
  2. 令牌 → Cookie:GET /?token=<进程令牌> 由 Desktop 换成 HttpOnly; SameSite=Strict 的签名 cookie, cookie 名与签名绑定域名。所以隧道域名一变,旧 cookie 自动失效,必须重新打开新链接。

老版本还有第三层:Desktop 的「允许在浏览器中打开」开关,关闭时非 renderer 请求一律 403 Browser access is disabled。0.2.1-rc.3 把这层删掉了(Host 上已经没有 setBrowserAccess(), 这个 403 也不会再出现),所以插件不再去翻它,也不再把它当成一条错误记下来。

通过 DSH 文件树打开文件时,客户端使用 Session-scoped 资源地址和现有侧边栏预览器;不会把本机目录挂成公网静态目录, 也不会依赖远程浏览器的 file:// 访问。直接请求未认证的文件路由仍返回 401,不受隧道域名本身授权。

插件不提供任何绕过上面两层的开关:能让浏览器进来的只有「域名在围栏里」和「链接带令牌」, 前者由插件在隧道就绪时自动发布、停止时收回,后者由进程内的 launch token 决定。

另外,插件自己的接口(/remote-access/status|start|stop|restart|link|logs|browser-access)同样先过这两层: 没有 cookie → 401,Host 不信任 → 403。也就是说,只知道域名的人既看不到 GUI,也控制不了这条隧道。

5. 配置

改本仓库 cordis.patch.yml 里 - id: dsh-remote-access 那一行的 config:,然后重启 Desktop。 (也可以在 profile 的 cordis.patch.yml 里用同一 id 覆盖:patch 的 config 是整体替换,不做深合并。)

键 默认 说明
enabled true 关掉后插件不注册任何路由
autoStart false 共享安装默认不自动开公网隧道;设为 true 后 Host 启动即开。面板点一次「停止」会记住 desired: stopped
provider cloudflare-quick cloudflare-quick / cloudflare-named / ssh / command
protocol http2 http2 / quic / auto(本机必须 http2,UDP 被屏蔽)
cloudflaredPath 自动探测 指定二进制;顺序:本项 → <DSH_HOME>/remote-access/bin/cloudflared → 包内 vendor → Homebrew → PATH
hostname — cloudflare-named 用,例 dsh.example.com
tunnelToken — cloudflare-named 用(cloudflared tunnel run --token)
publicUrl — 手动指定公网地址(不自动探测时用)
sshDestination / sshRemotePort — ssh -R 反向前向通道
command / urlPattern — 自定义通道:命令数组 + 从输出里提取公网地址的正则
urlPattern quick 隧道内置 覆盖默认的 URL 探测正则
extraTrustedHosts [] 额外要塞进围栏的域名
maxRestarts 5 隧道异常退出后的重启次数(退避 1s→2s→…→30s 封顶)
startTimeoutMs 60000 等待隧道就绪的上限
portWaitMs 内建 等待 Desktop 端口开始监听的上限
logLines 200 内存日志环形缓冲行数
keepAliveMs 65000 把 Host 的 node:http keepAliveTimeout 抬到多少毫秒(0 = 不动)。见 §5.1
proxyKeepAliveMs keepAliveMs - 5000 传给 cloudflared 的 --proxy-keepalive-timeout;必须短于 origin keep-alive,避免代理池复用已被 Node 回收的连接
tunnelLogLevel info 传给 cloudflared 的 --loglevel(debug 能看清边缘连接的重连细节)
tunnelLogBytes 1000000 日志超过这个字节数就滚成 tunnel.log.1
home 自动探测 强制指定 DSH_HOME

enabled / autoStart 只影响隧道本身;临时开关不走配置(它是运行中的一次性动作,故意不落盘)。

5.1 稳定性:为什么页面会显示「重新连接中」

浏览器不是轮询,而是靠一条 WebSocket(/api/remote.mux)跟 Host 通信。Host 每 2 秒 ping 一次, 连续两次没收到 pong 就 terminate() 掉这条 socket(MAX_MISSED_HEARTBEATS = 2),前端于是进入 重新连接中 并按 0.5s→10s 退避重连。任务都在 Host 上跑,断开只是界面闪一下,不会丢任务。

实测(2026-10-04,本机 → Cloudflare 快速隧道):socket 回得及时时能撑满 300s (149/149 ping 全部答复、间隔精确 2.00s、无 FIN/close);回环臂同样 300s 满勤。也就是说链路本身不总是坏的—— 真正的杀手是「pong 迟到」:浏览器标签页被节流、VPN 切换路由、边缘连接被回收,两次 tick 就够杀。

于是插件做了三件事降低概率(前两项要重启一次 DSH Desktop 才生效):

  1. 放宽心跳:安装器往 profile 补丁写一段受管的 typert-gateway 覆盖 (websocketHeartbeatIntervalMs: 15000)。间隔 15s 后,要连丢两次包得跨 30s 才致命。
  2. 让代理池先过期:cloudflared 默认会把 origin 连接保留约 90s,而 Host origin keep-alive 是 65s;插件默认传 --proxy-keepalive-timeout 60s,确保 cloudflared 不会在 Node 回收连接后继续复用它。
  3. 抬高 origin 的 keep-alive:插件把 webServer.server.keepAliveTimeout 抬到 keepAliveMs(默认 65s),并把 headersTimeout 提到至少 70s。
  4. 日志落盘:cloudflared 输出与插件日志都追加进 tunnel.log(超限滚成 .1),这样「边缘连接有没有在重连」才有证据可查,而不是只有一个 200 行的内存环。

6. 运行时文件

<DSH_HOME>/remote-access/
├── state.json      # desired / state / url / pid / target / provider / attempts(stopped 时不自动启动)
├── link.txt        # 纯文本分享链接(公网隧道那条)
├── control.json    # 控制套接字端口 + 令牌(0600)
├── tunnel.log      # 隧道输出 + 插件日志(0600;超过 1MB 滚成 tunnel.log.1)
└── bin/cloudflared # 安装时放的二进制

日志同时进内存环(面板 / logs 可见)和 tunnel.log(面板「详情」里会显示它的路径)。

7. 排查

现象 原因 / 处理
面板顶部红字「探测被 403 拒绝了」 隧道域名没在 connection.trustedHosts 里(围栏没发布或已被清掉)。点一次 重启,再看「详情」里的探测结果;健康时 access.state 是 token-required
403 host not trusted 隧道域名没进围栏。看面板「详情」里的 trustedHosts,或重启一次隧道(停止→启动)
链接打开 401 dsh web authentication required 用了旧的链接/书签。每次开隧道域名都会变,重新复制最新链接
刚看到域名,本机 curl 解析不了 新域名的 NXDOMAIN 被本机 DNS 缓存了(公网 DNS 正常,实测 1.1.1.1/8.8.8.8 → 104.16.230.132)。等 1 分钟或换 DNS;curl --resolve <域名>:443:104.16.230.132 可绕过验证
一直「启动中」 logs 里若是 failed to dial to edge with quic: timeout,说明 UDP 被屏蔽 → 用 protocol: http2
页面反复显示 重新连接中 / connected reconnecting Host 2 秒一次心跳、连续两次没答复就杀 socket(见 §5.1)。先看 tunnel.log:Unable to reach the origin service … EOF = origin keep-alive 太短;边缘重连另有 Registered tunnel connection/Retrying。安装器写的心跳覆盖(15s)和 keepAliveMs 都要重启一次 Desktop 才生效。回得及时的客户端实测能撑满 300s,所以偶发是正常的
端口不对 Desktop 的端口来自 desktop-preferences.json 的 port(0 = 随机);插件直接读 Host 正在监听的端口,通常不用管
想彻底关掉自动开隧道 默认就是关的;如果 profile 覆盖成了 true,面板点一次「停止」(记住 desired: stopped),或改回 false 后重启 Desktop
ssh -L 打开了却 401 本机链接是按 host:port 签发的。换 -L 端口后要用面板/CLI 重新复制一次本机链接
改了插件源码但界面没变化 ./bin/install 重装:面板(client.js)会被 Host 的 HMR 在约 0.5 秒内推到已打开的页面(刷新即最新);Host 侧改动(新的 HTTP action、新的 webServer API)必须重启 DSH Desktop,因为 Host 不会重载已 import 的模块
面板/CLI 还显示 browser-access switch failed: … 正在跑的 Host 还是旧版插件,那条错误是旧进程缓存下来的。重启一次 DSH Desktop;新版本不再记这个错,/remote-access/status 里也不再有 supportsBrowserSwitch
设置里的「远程协作」整块空白 已修(2026-10-04):button() 曾在渲染中途调用 useState,按钮数量随数据变化 → React 报 Rendered more hooks than during the previous render. 并卸载整个 slot。现在 button() 无 hook,test/client-react.mjs 用真 React 守住这条不变量

8. 验证记录(2026-10-04 实测)

  • test/service-unit.mjs(Host 侧单测,无 Host 进程、无网络):本机链接按端口签发、无端口时为 null; 访问探测把 401/200/303/403/连不上 分别归成 token-required/open/open/refused/unknown 并记下 checkedAt; refused 时只写一条 warn 日志、不把错误挂到 status.error 上(旧版本的 lastError 会一直显示); browser-access 这个旧入口返回 unsupported: true + 原因,且一次都不碰 webServer.setBrowserAccess(); link / logs / 未知 action 的行为;keepAliveMs 真的写到 webServer.server.keepAliveTimeout/ headersTimeout(0 = 不动、没有 server 句柄时报原因)、隧道日志文件同时收到 cloudflared 原始行与插件日志。PASS。
  • test/installer-unit.mjs:临时 DSH_HOME + 假 profile,跑真安装器,断言 bundle 进了 node_modules 与 dsh.profile.bundles、 清单先备份、受管心跳块写进 cordis.patch.yml 且手写的 preference: zh 不被破坏、重复安装字节不变(mux heartbeat already 15000ms)、 --heartbeat-ms 5000 会替换、--no-heartbeat 只删自己那段、--dry-run 不写任何东西、--uninstall 只回收自己的痕迹。PASS。
  • test/client-smoke.mjs:无头加载 client.js,装假 __ModuleLoader__/DOM,验证「不 import Harness Client 包、不用 iframe、只 require react、 注册 settings.section / id 与包名一致、能渲染、请求打到 <baseURI>/remote-access/status、链接进复制框、本机链接进复制框、 详情可展开」,并且面板里没有任何会 POST browser-access 的控件、常驻一段「这版没有开关」的说明; access.state 变成 refused 时出现 trustedHosts 提示、回到 token-required 后提示自己消失。离线与走真隧道两种模式都 PASS。 (test/run-tests.sh 一次跑完三个套件。)
  • test/client-react.mjs:用真的 react + react-dom + jsdom 渲染面板(不是自制 mini-React),断言 React 没有报 hook 顺序错误、 没有 console.error、首帧在数据到达前就能渲染、三种状态(ready / refused / unknown)都渲染正确、链接进 <input value>。 依赖装在仓库外(../.scratch/uitest,pnpm add react@18.3.1 react-dom@18.3.1 jsdom);找不到依赖时套件打印 skipped(退出码 2),不阻塞前两个套件。 这个套件就是「远程协作空白」那个 bug 的复现与防回归网。三种模式都 PASS。
  • 端到端(真隧道):无 cookie 401;伪造 Host 403;GET /?token=… → 303 + Set-Cookie(HttpOnly; SameSite=Strict,30 天); 带 cookie GET / → 200、35000 字节、<title>DeepSeek Harness</title>;/remote-access/status → 200;跨站 Origin → 403;未知路由 → 404。
  • 生命周期:stop → cloudflared 退出、旧域名 530、围栏清空、state: idle;start → 新域名 + 新链接可用。
  • 装进真实 profile(~/.dsh/profiles/desktop):安装脚本成功(备份 package.json.bak-20261004-165242、cloudflared 落在 ~/.dsh/remote-access/bin/), 随后运行中的 Desktop 直接热加载了插件(约 2 秒后日志出现 state dir ~/.dsh/remote-access + tunnel URL: https://…), ./bin/dsh-remote-access status --home ~/.dsh 报 state: ready、target: http://127.0.0.1:52075、 access: token-link / token-required / gate absent。此时无令牌请求是 401、带 ?token=… 的链接直接 200: 0.2.1-rc.3 里只剩 trustedHosts + 令牌两层,403 Browser access is disabled 那一层已经不存在了。
  • 复现:
# 用插件自己的 Host 跑一个不影响桌面的实例
DSH_HOME=<临时目录> ELECTRON_RUN_AS_NODE=1 "/Applications/DeepSeek Harness.app/Contents/MacOS/DeepSeek Harness" \
  --expose-internals "/Applications/DeepSeek Harness.app/Contents/Resources/app.asar/dsh/node_modules/@deepseek-ai/dsh/lib/bin.js" \
  --profile web --no-open --port 18790
./test/run-tests.sh                                        # 全部离线测试
./test/client-smoke.mjs --live https://<隧道域名> --cookie "dsh-auth-…=…"

9. 已知限制

  • 目标只能是本机回环上的 DSH Host(不做「转发到另一台机器」)。
  • cloudflare-quick 已实测;ssh / command 通道代码路径在,但还没有在真机上验证。
  • 快速隧道域名每次重启都变(Cloudflare 免费行为的限制);固定域名请用 cloudflare-named。
  • 单实例:面板与 CLI 操作的都是同一个隧道(同一个 Host 进程)。
  • 访问模型跟着 Host 走:0.2.1-rc.3 没有 Desktop 侧开关可翻,跨机访问完全依赖 trustedHosts + 链接里的令牌; 插件不提供(也不再假装提供)第三层开关。
  • 客户端面板用的是自带的朴素 React 组件(不依赖 Harness 内部包),样式跟随 --dsw-alias-* 主题变量, 深色/浅色都能用,但视觉细节不会跟 Desktop 自带设置页 100% 一致。
  • 「重新连接中」只能被降低概率,不能被消灭:公网隧道本身会抖,插件做的是放宽心跳 + 抬高 origin keep-alive, 让一次迟到不再等于断线(见 §5.1)。

English summary

dsh-remote-access is a DSH bundle + web client plugin that publishes this Desktop's Harness Web GUI (same sessions) to the internet through a tunnel (Cloudflare quick tunnel by default) and hands you a tokenised link to open from another machine's browser — or, if the two machines can reach each other, over plain ssh -N -L 8080:127.0.0.1:<port> <you>@<this-mac> with the panel's loopback link and no tunnel at all. There is no Desktop-side gate to open any more: DSH Desktop 0.2.1-rc.3 removed the "allow opening in a browser" switch and webServer.setBrowserAccess(), so an ordinary browser gets in through exactly two things — the tunnel hostname published into connection.trustedHosts while the tunnel is up, and the launch token carried by the link (GET /?token=… → 30-day cookie). Use Settings → Remote access, or ./bin/dsh-remote-access start|link|stop --home ~/.dsh. The link is full control of this machine — treat it as a secret.

Stability: the browser talks to the Host over one WebSocket that is pinged every 2s and killed after two unanswered pings, so a lossy WAN path shows up as Reconnecting. The installer therefore writes a managed typert-gateway override (websocketHeartbeatIntervalMs: 15000) into the profile patch (--no-heartbeat to opt out), the plugin raises the origin keepAliveTimeout (60s+ to stop cloudflared's origin EOF errors), and every tunnel line is appended to <DSH_HOME>/remote-access/tunnel.log with rotation. The first two need one DSH Desktop restart.

—/ 5

No ratings yet

Verified DSH bundle

Commit 2b164f50683c

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout