DSH 这么好玩,但是只能在电脑上玩太可惜了。于是我用 Kuikly 框架做了一个 DeepSeek Harness App——一码三端的跨端原生 App,不是把官方 Web 塞进 WebView,而是按官方 Host 协议跟电脑上的 DeepSeek Harness 说话。
-
Kuikly 框架:github.com/Tencent-TDS…
它是什么
DeepSeek Harness 跑在电脑上,界面是 Web。DSH 开源之后,手机端客户端冒出来好几个,我也用 Kuikly 跨端 UI 框架做了一个 DSH App。
DSH 自带的 Web GUI 只监听 127.0.0.1,而且不带认证。出门想用手机连,你不能把 3080 直接打公网——因为它自带 bash 工具,谁连上谁就拿到你电脑的执行权。
社区里早有「手机遥控 DSH」的玩法,大多是套一层浏览器或 WebView。我走另一条:原生界面 + 官方协议。按官方 Host 协议连接电脑上的 Harness,它不是把官方 Web 塞进 WebView,也没自己另起一套聊天后端。
Harness 的 Agent 循环、工具调用、流式事件、插件都还在电脑上跑。App 只做宿主:管连接、生命周期、聊天界面,通过 RPC 和事件流跟 Host 通信。手机上看到的会话、工具卡片、审批,对应电脑上 Harness 的同一套协议。
快速开始
打开 App,首页是「连接 DSH」,先选 扫码连接 或 SSH。两套配置互不干扰,会话缓存也不会混。DeepSeek API Key 配在电脑端 DSH,不要配在手机里。
扫码要同时开着三样:电脑上的 Relay、电脑上的 DSH、手机上的 App。建议电脑开两个终端,都不要关。
先分清两个容易混的地址,后面命令会用到:
-
relay/DSH_RELAY:插件连 Relay 用的地址,电脑本机一般是http://127.0.0.1:8787。 -
publicRelayUrl/PUBLIC_RELAY_URL:写进二维码、给手机用的地址,必须是手机能打开的电脑 IP,例如http://192.168.1.10:8787。
手机不内置公网域名,一律读二维码里的 origin。电脑 3080 始终只听回环,不用打公网。
扫码连接
手机和电脑先连到同一个 Wi-Fi(两边要能互通;有些会隔离终端)。
**1. 启动 Relay(默认 127.0.0.1:8787) **
Relay 在插件仓库的 relay/ 目录,没有单独安装包:
git clone https://github.com/yukiykchen/dsh-scan-remote.git
**cd** dsh-scan-remote/relay
cp .env.example .env
npm ci
npm run build
HOST=127.0.0.1 PORT=8787 npm start
也可以 docker compose up --build。另开窗口确认还活着:
curl http://127.0.0.1:8787/health
Relay 要一直开着。关掉后扫码和隧道都会断。
2. 给 DSH 安装插件
npx @deepseek-ai/dsh plugin --profile web add "github:yukiykchen/dsh-scan-remote#v0.0.1"
已经装过可以跳过。Settings 里没有 Remote Access,多半是插件没装到 web profile,或 Host 不是用这个 profile 启动的。
3. 写入手机能访问的电脑地址,再启动 DSH
ipconfig getifaddr en0 # macOS Wi-Fi;Linux 用 ip addr / hostname -I
把看到的局域网 IP 写进二维码 origin:
**export** PUBLIC_RELAY_URL=http://192.168.1.10:8787 # 换成上一步的电脑 LAN IP
npx @deepseek-ai/dsh web
从 DeepSeek Harness 仓库开发也可以用 pnpm dsh web。已经用过插件时,可以直接改 ~/.dsh-scan-remote/config.json 的 publicRelayUrl,再重启 DSH。改完一定要重启,否则 Settings 里仍是旧码。
浏览器打开本机 DSH:Settings > Remote Access,应看到二维码、倒计时和电脑名。确认码里的地址是当前网段,不是上一张网的 IP。
4. 手机扫码
Android 试用包在 github.com/yukiykchen/… 下载 dsh-mobile-*.apk。iOS 用 Xcode 打开 iosApp/iosApp.xcworkspace 装到真机。
-
打开 App,选 扫码连接。
-
点 扫描电脑二维码。
-
配对成功后点 连接已配对电脑。
扫完后经 Relay 建密封隧道。电脑 3080 继续只听回环;Key 留在电脑上;Relay 只转发密文,看不到对话。跨网段的话,把 Relay 部署到手机能打开的地址即可,协议是两端出站连 Relay,不依赖把 Host 端口映射出去。
SSH
已经有私钥、或不走 Relay 时用这条。只做本地端口转发,不通过 SSH 执行远程命令,同样不暴露 3080。SSH 不需要 Relay。
电脑先启动 DSH:
npx @deepseek-ai/dsh web --port 3080
推荐给手机用的 SSH 用户配 Ed25519 公钥:
ssh-keygen -t ed25519
ssh-copy-id your-user@your-computer
Windows OpenSSH 把 .pub 追加到 %USERPROFILE%\.ssh\authorized_keys。
手机和电脑不在同一局域网时,可以两边都加入 Tailscale / ZeroTier,App 里填虚拟地址,例如 100.86.12.34。
在 App 里填 SSH 主机、端口、用户名、远程 DSH 端口,导入私钥。首次连接会出示主机指纹,确认后用于后续校验;指纹变了要重新确认。
电脑侧细节以 github.com/yukiykchen/… 为准;连上之后的 RPC 和事件见 App 仓库 github.com/yukiykchen/…
原理与安全
原理一句话:手机和电脑各自出站连 Relay,用二维码里的密钥建 sealed-tunnel-v1;插件在电脑本机把隧道接到 127.0.0.1:3080。Host 零改动,bash 工具和信任围栏仍在电脑上。
App 怎么对接上远程 DSH
-
Host 生成 32 字节主密钥,HKDF 派生
claimToken(info:dsh-claim-v1)。 -
Host
POST /pair/session,Relay 只拿到SHA-256(claimToken),拿不到密钥本身。 -
二维码是
{PUBLIC_RELAY_URL}/app/#/pair?id=...&key=...。#后面的密钥不会发给 Relay。 -
App
POST /pair/claim-device,HostPOST /pair/confirm。 -
App 拿 access ticket,再
WSS /client-tunnel(ticket 只走 Authorization 头)。 -
连上之后,App 在手机本机拉一个 loopback 网关,后面的 JSON-RPC 和
events.mux与官方 Host 协议对齐,不另起聊天后端。
会话列表、发消息、模型切换、工具卡片、审批,走的是官方 Host 的 POST /api/{method} 和 WebSocket events.mux / events.host。方法名不自造。远程就绪顺序是:先开两条 WS,再 host.describe,再拉 workspace.list / session.list。mux 断线会重放漏掉的 session/event,重连后再拉一次 session.history。
细节以 github.com/yukiykchen/… 为准。扫码配对和密封隧道不属于 Host 协议,在 github.com/yukiykchen/… 里。
三点必须说在最后
-
DSH 还在 preview。 官方会有破坏性变更,协议没有版本协商。别当稳定基础设施,跟着升级是预期成本。这个 App 也是开发和验证中的实验项目,不要当生产客户端。
-
不要轻易装来历不明的 DSH 插件。 插件能起子进程、读写文件、在 GUI 里挂页面,装一个约等于给这台电脑装常驻软件。本插件 MIT,衍生自
april-jk/dsh-mobile-plugin和april-jk/dsh-relay,源码看得见更放心。 -
永远不要把 dsh 的 3080 直接暴露公网。 局域网 Relay 适合同一可互通网段;跨网段就自持一台 HTTPS Relay,不要把配对二维码发到聊天里。
觉得有用,欢迎 star / 提 issue / 提 PR。