Phone access to DSH over a self-hosted relay (WSS via your own TLS-terminating proxy): bundle plugin with bridge supervisor and QR login, a native Android app, and server-side device revocation.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:zdx8637-gitdog/dshmobile#path:/plugins
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
Zero-friction remote bridge for your phone: install once, no networking configuration, no local patches — after restarting dsh, a persistent QR panel appears in the left sidebar (cross-platform, immune to DSH upgrades).
- Persistent QR (arrow popup at the bottom of the web sidebar): always scannable, independent of login state — · PC logged in → the phone (even logged out) scans to log into the same account; · PC logged out → the phone (logged in) scans to grant access and the PC logs in automatically;
- Bridge daemon: username/password mode or phone-granted token mode (passwordless, 401 auto-refresh);
- One QR, three uses: WeChat scan = download the App, camera scan = open the App for pairing, in-App scan = direct login / grant.
Install
Pick your path first: DSH desktop app 0.2.0 or newer → §A (GUI, recommended);
legacy dsh web (0.1.7) → §B (CLI). Both install the same package,
@zdx8637/dshmobile-bridge (current version 1.0.7).
A. DSH 0.2.0 desktop app — install from the GUI (recommended)
Open the DSH desktop app → plugin manager → click 「添加插件」 (Add plugin);
Paste the package name with an exact version into the input box (its placeholder reads 「输入插件的包名、GitHub 仓库地址或本地目录路径。」 — a GitHub repository URL or a local directory path is accepted there too):
@zdx8637/dshmobile-bridge@1.0.7On the right pick 「安装源」 —
npm 官方源(official npm registry) or中国大陆镜像源(Mainland-China mirror) — whichever your network reaches;Click install;
Restart DSH — the host has to reload the plugin before it takes effect;
Open the panel: a ▶ arrow appears at the bottom of the web sidebar — click to open it.
⚠️ Always pin an exact version (e.g.
@zdx8637/dshmobile-bridge@1.0.7). The profile directory contains apnpm-lock.yaml; when you reinstall by bare package name the lockfile can pin the version back to the old one (measured: npm already served 1.0.2, yet a reinstall still left 1.0.0 installed).
⚠️ Plugins do not auto-update. The dialog says so outright — 「插件安装后,暂不支持自动更新。若需升级,请先卸载再安装新版」. So to upgrade: uninstall in the plugin manager first, then repeat the steps above with the new version number.
B. DSH 0.1.7 (legacy: dsh web + CLI) — install from the CLI
npx -y @deepseek-ai/dsh plugin --profile web add @zdx8637/dshmobile-bridge@latest
# after restarting dsh, a ▶ arrow appears at the bottom of the web sidebar — click to open the panel
Prerequisite: pnpm (the dsh plugin subcommand depends on it; corepack enable or
npm i -g pnpm).
Legacy only: npm
latestfor@deepseek-ai/dshpoints at the 0.1.7 CLI, so this command pulls the 0.1.7dsh plugin. On 0.2.0 or newer use §A (the GUI) instead — the CLI is not the 0.2.0 install path.
Phone App: scan the panel QR → download the APK from the landing page (or from the releases page).
Patch-free: official RPC channel first, local HTTP as fallback
DSH 0.1.0-rc.6 does not expose third-party settings namespaces to the browser (upstream marks
this as deferred work). This plugin does not depend on that channel: the panel prefers the
official connection service RPC channel (ctx.connection.rpc, channel /dshmobile, a
same-origin relative path with no origin dependency) and automatically falls back to local HTTP at
127.0.0.1:17653 (status polling + action dispatch, CORS echoes the caller origin) when that
service is unavailable. Both channels share the same payloads and actions, therefore
- install-and-go, no local patches;
- Windows/macOS/Linux;
- works in the desktop app (window origin
dsh-app://app) and indsh web; - DSH upgrades cannot break it (historical versions ≤ 0.1.0-beta.3 needed the deprecated
scripts/expose-settings-namespace.ps1patch).
DSH v0.1.5+ adaptation (legacy DSH support removed)
Since v0.1.5 DSH added browser-session auth to the local web service (the URL printed by
dsh web carries a process-level launch token → the browser exchanges it for a session Cookie,
and every /api request is validated), and upgraded the RPC protocol to Typert endpoints
(session/list, {args} payloads, /api/remote.mux stream multiplexing, $events
approval/question waterfalls). The plugin adapts automatically since 0.1.0-beta.17:
- the host half obtains the launch token via
ctx.connection.authenticatedUrl()and hands it to the bridge child process; - the bridge exchanges the token for a Cookie once (HMAC-signed, valid 30 days), caches it in the
state directory, re-mints on 401, and attaches it to every
/apirequest and WS upgrade; - session/workspace/command endpoints are mapped to the new protocol; events flow through
/api/remote.mux(session/follow+workspace/follow+session/control); approvals and questions flow through$events+$events/result.
⚠️ Legacy DSH support (≤ v0.1.0-rc.6) was removed in 0.1.0-beta.23: the former dual-protocol auto-detection (dot endpoints, raw payloads,
events.mux/events.host,/api/respond, no auth) is gone — one protocol path removed: adapter −283 lines / dsh −59 / main −21 / host −8, plus the whole "simulated legacy DSH" smoke script. DSH ≥ v0.1.5 is now required. If the bridge cannot reach DSH it logs a clear message inbridge.log: "v2 协议握手失败:请确认 DSH 正在运行(dsh web);本插件版本已不再支持旧版 DSH(≤0.1.5-rc.6)".
Self-check scripts: node scripts/smoke-dsh-v2.mjs (full pipeline against a simulated new DSH),
node scripts/probe-real-dsh.mjs (read-only verification against a running real DSH; requires
having logged into the web panel once in this browser to generate the signing secret),
node scripts/archive-session.mjs --list | --newest-idle (safely clean idle sessions; refuses to
archive live ones by default), node scripts/unarchive-session.mjs <id> and
node scripts/probe-session-archive.mjs <id> (DSH has no unarchive API: the archive set lives
in the host's memory, so editing the state file only takes effect after a DSH restart — see
docs/dsh-session-archive.md).
Single-instance protection (against two bridges kicking each other)
If two bridges ever run on the same machine (a second DSH instance, an orphaned bridge left behind when
DSH was killed, or a mix of old/new plugin versions) they share the same state directory
~/.dsh-mobile ⇒ the same relay device identity ⇒ they kick each other off the relay, and the phone
shows "cannot refresh conversations after login". Since 0.1.0-beta.23 there are four layers of defence:
- Bridge-side singleton lock: a loopback port derived from the state directory acts as the lock (released automatically when the process dies); a new instance asks the holder to yield, and exits with code 42 if the holder refuses — the two never coexist;
- Host takeover: before starting the bridge the host terminates any other bridge process on the machine (so updating/restarting DSH also cleans up old orphans, and the newest code is the one running);
- Parent watchdog: the bridge exits as soon as its host disappears, so orphans are no longer created;
- Bridge-side self-healing: if the relay keeps closing this bridge with
4000 duplicate connection(meaning an older bridge is still around), it cleans up the other bridge processes.
The panel entry dot then shows "另一个桥实例在运行" (another bridge instance is running); saving once in the
panel (or restarting DSH) takes control back. Diagnostics: ~/.dsh-mobile/bridge.lock.json and
bridge.log (UTF-8). For a temporary second bridge (UI verification) use a separate state directory
plus --state-dir=<that dir>, or set DSHMOBILE_BRIDGE_SINGLETON=0. Details:
docs/bridge-singleton.md.
relay
The plugin connects to https://www.deepseek-claudex.cn by default (author-operated relay:
account registration, device management, message routing). You can also self-host: see the
relay/ directory and dsh-remote/docs/04-operations.md in the main repo, then point the panel
at your own relay URL.
Development
npm install
node scripts/build.mjs # produces lib/index.js + lib/client.js
node scripts/smoke-host.mjs <u> <p> # username/password smoke test
node scripts/smoke-grant.mjs <u> <p> # phone-grant smoke test
The complete three-part stack (phone App / relay / protocol) lives in the main repo zdx8637-gitdog/dshmobile.
License
MIT
Links
More in this category
zhu1090093659/dsh-web#packages/dsh-remote-web-ui★ 8707
Remote control of a dsh web workspace from phone or PC: QR-code pairing through a token-gated channel, SSE real-time sync, and separate mobile and full desktop GUI modes.
zhu1090093659/dsh-web#packages/dsh-ssh★ 8707
SSH ops panel for DSH: web terminal, SFTP transfer with progress, local port forwarding, and one-command cluster execution across hosts; agents share the same host config.
saya-ch/dsh-mobile★ 449
Access DeepSeek Harness from the Android app or a mobile browser with secure LAN and remote connections, persistent device pairing, and a customizable mobile interface.
liguobao/ds-harness-remote★ 327
Multi-device remote access for DeepSeek Harness: continue an active session from your phone, tablet, browser, or another computer over an end-to-end encrypted channel (Noise IK + adaptive relay/WebRTC transport), with device authorization, ApiProxy-only remote capabilities, and read-only file preview via dsh-file-viewer — no shell, remote desktop, or write access.
ZSeven-W/dsh-ios★ 322
A live iOS Simulator or USB-connected iPhone inside the conversation: 22 agent tools for booting, building, driving the UI by accessibility identity or OCR text, list-row actions and SwiftUI preview hot reload, plus a streaming sidebar panel you can tap and drag on.
wenbin-wb/dsh-bridge★ 195
Remote and mobile access for DeepSeek Harness: provides LAN QR code connection, Cloudflare/custom tunnels, WeChat, QQ, Feishu, Telegram bot integration, and security authentication.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.