dsh-plugin-mobile-link
v0.3.1
Published
Put your PC's DeepSeek Harness in your pocket: dials a relay over WSS so the native iOS client reaches this machine even without a public IP.
Maintainers
Readme
dsh-plugin-mobile-link
面向:使用者与实现者 · 状态:stable · 最近核对:2026-09-20
The computer half of DSH Mobile: it dials a relay over WSS, so the native iOS client reaches this DSH instance even though the computer has no public IP.
iPhone App ──WSS──▶ Relay(公网,只鉴权与转发)──WSS──▶ this plugin ──HTTP+WS──▶ 127.0.0.1:<port>The connector always talks to the local DSH as 127.0.0.1:<port>, so the host's
authority and its trust fence are unaffected: no --trusted-host, no rewritten
Host, no new listening port on this machine.
plugins/mobile-link/
├── package.json # type: module, dsh.bundle.patch, bin: dsh-mobile-link
├── cordis.patch.yml # bundle patch: the loader row + config reference
├── lib/
│ ├── index.js # cordis plugin: starts the agent, registers 3 routes
│ ├── link.js # the DLP agent transport: identity, socket, heartbeat, reconnect
│ ├── router.js # frames ⇄ local DSH mux streams, per-device `$events`
│ ├── dlp.js # DLP v1 frame codec (shared with the relay)
│ ├── files.js # phone → computer file transfers (`_link/file*` methods)
│ ├── enroll.js # invite-code redemption, writes ~/.dsh/mobile-link/agent.json
│ ├── routes.js # GET /mobile-link/status, POST /pair-code, GET /qr
│ ├── qr.js # dependency-free QR SVG
│ └── cli.js # dsh-mobile-link: enroll / mint-pair-code
└── test/ # node --test, 100+ tests (no DSH, no network)Install
dsh plugin --profile web add dsh-plugin-mobile-linkThen restart DSH (or reload the profile). From a checkout the same command takes
a path — the leading ./ matters, because DSH anchors a relative spec against
your current directory instead of resolving it inside the profile:
dsh plugin --profile web add ./plugins/mobile-linkUse
Register this computer with a relay (once). Either redeem an invite code:
dsh-mobile-link enroll --invite <邀请码> --relay wss://<你的站点>/dsh-link…or register it on the relay host with
relay/admin.py agent-register --write-config ~/.dsh/mobile-link/agent.json.Mint a pairing code, and show it as a QR the phone camera can read:
dsh-mobile-link --mint-pair-code # prints JSON: code + relay + agentIdOr open
/mobile-link/qron the local DSH (behind DSH's own authentication).Scan it in the iOS app. After that the phone reconnects on its own — nothing else has to be run by hand.
GET /mobile-link/status reports whether the link is up, which devices are
attached, and whether this computer is registered yet.
Configuration
All optional; the defaults are what a stock deployment needs. Set them in the
plugin's config block (cordis.patch.yml), not by editing this file.
| Key | Default | Meaning |
| --- | --- | --- |
| enabled | true | false stops the outbound link without uninstalling |
| relayUrl | from agent.json | Relay base URL; a bare deployment dials <relay>/link/agent |
| agentId / agentSecret | from agent.json | Override the enrolled identity |
| stateFile | ~/.dsh/mobile-link/agent.json | Where the identity lives |
| dshUrl | discovery | Explicit local DSH base URL |
| endpointFile | $DSH_HOME/desktop-shell/endpoint.json | DSH endpoint handoff file |
| heartbeatMs | 20000 | DLP ping interval |
Address resolution order: this config block, then DSH_RELAY_URL (or
DSH_MOBILE_LINK_RELAY), then the enrolled identity file, then the repository
placeholder wss://relay.example.com/dsh-link — the placeholder being the
"nothing configured yet" sentinel rather than a real address.
Design notes
- No required services.
injectis empty and the routes are attached throughctx.inject([...]), so a future DSH that renames or dropswebServer/connectioncannot make the tunnel fatal on boot. - Protocol-transparent. Nothing outside
lib/is imported and no DSH business API is touched: the connector forwards frames, it does not interpret sessions. The relay has the same property. - Disable by removing the row from the profile's
cordis.patch.yml, or by settingenabled: false.
Test
cd plugins/mobile-link && npm test # zero dependenciesThe wire protocol is specified in
docs/RELAY-PROTOCOL.md.
MIT.
