Development & Runtime

dsh-mobile

saya-ch/dsh-mobile · ★ 860

saya-chCurated

DeepSeek Harness 移动端适配与安全局域网访问插件,支持 Android App 和手机浏览器。

An English summary is not available; the Chinese summary is shown.

License
Apache-2.0
Added
2026-08-17
Maintenance
active
Install kind
github
npm
dsh-mobile
Manifest details
Manifest status
Declared
Manifest path
package.json#dsh
Manifest checked
2026-08-19
Lifecycle scripts
None found

Static manifest checks report declarations only; they are not compatibility or security review.

安装

dsh plugin --profile web add github:saya-ch/dsh-mobile

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. What it does
  2. Quick start
  3. Official DSH Desktop
  4. DSH Web
  5. Install the Android app
  6. iPhone and iPad: Home Screen web app (PWA)
  7. Connection guide
  8. Local network
  9. Remote access
  10. Experimental iroh connection
  11. Extend and customize
  12. Device management
  13. Third-party plugin compatibility
  14. WebSocket approval
  15. Optional modules and advanced configuration
  16. App or mobile browser
  17. How it works
  18. Security

DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.

Using an iPhone or iPad? Use Safari or add DSH Mobile to your Home Screen as a web app (PWA)—no native iOS download needed.

Current stable release: 0.8.0. Add iPhone / iPad Home Screen setup and Web Push notifications, with six categories for questions, plans, approvals, responses, goals and failures. Also improve sidebar position retention, attachment actions and slow-link transfers. Plugin release notes and downloads · Full changelog.

Version policy: since plugin 0.6.2, the Android app and plugin use independent version numbers and releases. Their numbers do not need to match, and a plugin update does not imply an app update. Compatibility notes.

DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, cloudflared, self-hosted FRP, or own reverse-proxy remote path. The full Android App also supports experimental iroh encrypted direct connections with relay fallback. The phone reaches the computer's sessions, Workspaces, messages and tools. The computer manages LAN and remote switches and pairing authorizations separately; the Android app lists paired computers together. The plugin does not modify DeepSeek Harness source.

Mobile access uses a dedicated HTTPS origin and device pairing. The Android app pins the private LAN CA; public remote paths use platform-trusted certificates. The self-signed FRP entry additionally requires the 0.4.6 app to pin a remote CA during pairing.

It also lets you customize the phone from a DSH conversation: /mobile <what you want>.

What it does

  • Continue DSH work from a phone: the same sessions, Workspaces, messages, and tools, in real time.
  • Customize the phone UI by talking to DSH: request layout, interaction, or feature changes in a conversation; changed customization resources are usually picked up automatically.
  • A dedicated touch layout: session drawer, tool details, settings, question cards, and composer reorganized for phones. The sidebar remembers its list position within the page instead of jumping to the top after a session switch. The app follows the system locale (Chinese/English/Italian), plugin UI follows DSH's locale.
  • Several remote options: Tailscale, cpolar, cloudflared quick/named tunnels, self-hosted FRP, your own reverse proxy, and experimental iroh without a domain or public port; Windows/Linux x64 can also let the plugin manage Caddy HTTPS and certificates.
  • Pairing and multi-device: pair once via QR code, link, or key; Wi-Fi, hotspot, or IP changes normally recover automatically; the app lists LAN and remote paired computers together, checks their reachability periodically, and lets you switch, re-pair, or delete a local record.
  • One-click diagnostics and approval: check versions, gateway, network interface, firewall, and the remote path with a redacted report; approve blocked third-party plugin connections per exact path.
  • iPhone / iPad Web Push: add the page to your Home Screen and explicitly enable notifications in DSH General settings. Choose from six categories and receive alerts while the page is closed or the screen is locked, without conversation text on the lock screen. Requirements and setup.
  • Android task notifications: enable completion and pending-input alerts in DSH General settings inside the app, using its separate native notification channel with redacted lock-screen text.
  • Defense in depth: a private CA pinned for LAN, trusted HTTPS for public remote paths, and a remote CA pinned by the 0.4.6 app for the self-signed FRP entry. Credentials are Keystore-backed, device tokens go only to their exact Origin, and third-party WebSockets are blocked by default.

A paired device can operate DSH on the computer and must be treated as fully trusted. Enable LAN access only on trusted networks, and use a reliable HTTPS channel for remote access. Revoke a lost phone from the computer immediately.

Quick start

Install the plugin on the computer, then pair the Android app or a mobile browser. Choose the installation path for your DSH host.

Official DSH Desktop

Install and enable dsh-mobile from the app's Plugins page, then open Mobile Access to configure LAN or a remote channel. The app manages its Desktop profile; the --profile web commands below do not apply to it.

After installing or updating, quit Desktop from the application menu and reopen it without clearing sessions or pairing data. If it still reports dsh-mobile-question-fixes: failed to import, check the installation log; a component-resolution failure may not be fixed by restarting alone.

DSH Web

With an installed dsh command, run:

dsh plugin --profile web add dsh-mobile@latest
dsh plugin --profile web exec dsh-mobile setup
dsh --profile web

From the DeepSeek Harness source directory, run:

pnpm install
pnpm dsh plugin --profile web add dsh-mobile@latest
pnpm dsh plugin --profile web exec dsh-mobile setup
pnpm dsh --profile web

Or via the plugin market (optional):

dsh plugin --profile web add dshmarket

Restart DSH, then search for dsh-mobile under Settings → Plugin Market and install it. On first opening Mobile access, the Local network page lists this computer's current networks; confirm one to create private certificates and LAN configuration, then restart DSH once as prompted. No terminal setup command is required for this path.

setup automatically selects and remembers the current LAN; Wi-Fi, hotspot, and IP changes normally recover without re-pairing. Use --address 192.168.x.x only when automatic selection fails. Settings, certificates, devices, and customization files live under $DSH_HOME/mobile-access/.

Install the Android app

Download the official Android APK using the link above. Then choose LAN or remote access in the connection guide; the phone needs no separate tunnel client. For browser access, including iOS, follow the steps below.

Registry-installed plugins check for updates when the desktop UI loads and show “Update plugin” beside the access-panel title when a newer release is available. Restart DSH after installation. The app download entry shows the latest version; local development packages are not overwritten, and Android does not check for or push app-version updates.

iPhone and iPad: Home Screen web app (PWA)

The plugin runs on the computer; Safari loads its mobile interface. There is no native iOS app to install.

  1. Install and enable the plugin on the computer as above. In Mobile Access, configure your connection; prefer a stable, trusted HTTPS address for a lasting Home Screen installation.
  2. Stay in that connection's panel: use Copy pairing link for LAN, or Generate remote pairing QR code then Copy remote pairing link for Remote. Open the resulting browser link in Safari and complete pairing. Use the dedicated Mobile Access link, not the computer's ordinary DSH page; Android dsh1./dsh2. keys are not browser pairing codes.
  3. From the paired page, open Safari's Share menu → Add to Home Screen. Turn on Open as Web App if offered, then tap Add. Menu layout varies; see Apple's iPhone instructions.
  4. Launch the new Home Screen icon to continue the same DSH sessions and Workspaces. If it shows a Pairing code form, follow the fresh-code recovery steps; Safari's first code is single-use. A normal reconnect page uses saved pairing instead. Keep existing installations and pairing/site data when troubleshooting.

You can also keep using Safari without installing an icon. The computer, DSH and Mobile Gateway must stay running and reachable; adding the web app does not provide offline DSH. A changing tunnel hostname does not automatically transfer pairing or push consent.

Enable Web Push: launch the Home Screen icon, open DSH Settings → General → Web push notifications, select Enable, allow notifications and choose your categories. This targets capable iOS/iPadOS 18.4+ Home Screen apps on trusted HTTPS; ordinary Safari tabs and the Android app do not show this entry. Notifications are optional and are not required for ordinary access. Full guide and troubleshooting.

Connection guide

LAN and remote access are independent connections. Prefer LAN while the phone is near the computer for the lowest latency, and enable remote access only when leaving that network. The computer manages their switches and pairing authorizations separately; the Android app shows all paired computers together in its device list.

Local network

Use this when the phone and computer share Wi-Fi, Ethernet, or a phone hotspot. It is the default and simplest path.

  1. Connect the phone and computer to the same local network, then open Mobile Access → Local network in the lower-left corner of DeepSeek Harness.
  2. If needed, select Enable local access, then select Generate pairing QR code. The panel displays a pairing QR code.
  3. In the Android app, open Local network, scan for computers, select the device, then scan the QR code or paste the pairing key.
  4. Pairing creates persistent device trust. Later app launches discover and connect automatically; Wi-Fi, hotspot, and DHCP address changes normally do not require pairing again.

LAN and HTTPS remote pairing codes show their expiry time. Generate a new code after expiry; doing so invalidates the previous code. Copy pairing link reuses the current valid code instead of invalidating the displayed QR. The computer-side Device entry lists and revokes LAN and remote authorizations in separate tabs; it does not manage the saved computer list in the App.

When other plugin entries share the sidebar footer, Mobile access becomes a phone-icon button. Hover to read its name; clicking opens the same panel. Its text label returns when the entry is alone.

Port note: dsh web --port changes the DSH Web upstream port (3080 by default), which the plugin follows automatically. dsh-mobile setup --port changes the Mobile HTTPS listener (3443 by default), and the pairing QR code includes the selected port. When DSH Desktop starts with --port 0, the gateway follows the actual port in use; upstreamOrigin in mobile-access/setup.json is only the snapshot from the first setup, and the plugin refreshes it at startup — do not read it as the upstream the gateway uses.

Headless Linux hosts, and browsers that open DSH Web through a LAN IP or reverse proxy, can use the same Mobile access control in the lower-left corner. The admin API still requires a loopback TCP peer (for example a local socat or reverse proxy to 127.0.0.1) so the plugin itself is not LAN-exposed. The browser Host may be localhost, RFC1918, or an IPv4 link-local address; public IPs and arbitrary DNS names still return 403. The reverse proxy must be limited to trusted local or LAN callers and must not publicly forward /api/mobile-access. The dedicated Mobile HTTPS listener (3443 by default) remains the phone surface and does not become the desktop admin panel.

For a routed network such as WireGuard, 0.6.0 offers additional trusted networks. It adds explicit source CIDRs only, without creating a VPN or routes or changing Windows firewall rules.

The app is optional: select Copy pairing link and open it in a mobile browser. LAN uses a private certificate, which the browser may warn about on first visit; continue only after confirming that this is your DSH gateway. A public-certificate remote origin should not show a certificate warning. If it does, check the channel and certificate instead of bypassing the warning.

Browser pairing and reauthentication pages support Simplified Chinese, English and Italian. Since plugin 0.6.16, they prefer the DSH display language remembered for that gateway hostname, falling back to the browser's Accept-Language when no usable preference exists; clearing site data or changing hostname can reset it. Native Android screens follow the system language, while the DSH plugin control panel follows DSH's current language.

For manual browser pairing, enter the 43-character pairing code shown on the computer. Keys starting with dsh1. or dsh2. belong in the Android app, not the browser field. Prefer the pairing link copied from the computer, which fills the code automatically; generate a new link when it expires.

Remote access

Use this after the phone leaves the computer's network. Remote access is disabled by default, and the phone needs no separate Tailscale, cpolar, cloudflared, or FRP app.

Without a domain or public inbound access, you can also try iroh (experimental). Install the pinned computer component and the full Android App 0.7.0 to connect through encrypted direct links with relay fallback. Computer support is currently Windows/Linux x64; the compatibility APK and mobile browsers cannot use iroh. This is not a guaranteed connectivity or acceleration service: VPNs, proxies and both networks can affect it. See iroh setup and troubleshooting.

Remote providers may impose bandwidth and connection limits: the cpolar Free plan currently lists 1 Mbps, while Tailscale Funnel has non-configurable bandwidth limits, and a cloudflared quick tunnel is a free Cloudflare address with randomized hostnames and rate limiting. DSH Mobile uses gzip for static assets, persistent WebSockets, and load-on-scroll history to improve loading; DSH controls the Session history window and page sizes, and the plugin cannot raise provider quotas.

If the page opens but stays on “Reconnecting,” distinguish WebSocket upgrade failures, slow synchronization, and heartbeat deadlines using the slow-link and reconnection guide. Version 0.5.4 also offers opt-in WebSocket compression per exact path, disabled by default; for long Sessions or metered links, follow the guide and compare actual transfer volume.

The usage notes below reflect the maintainer's long-term experience on a personal mainland-China network, not a universal comparison. Performance depends on the carrier, network and plan; verify the route on your own phone's network.

Channel Prerequisites Address and limitation Maintainer's usage notes
iroh (experimental) Windows/Linux x64 computer component and full Android App 0.7.0 No domain, port forwarding or tunnel account; encrypted direct links with relay fallback; setup and VPN troubleshooting An option without public ingress, not a stability ranking; verify on both actual networks. Mobile browsers are unsupported
cpolar Account and Authtoken Free temporary URLs may change The free plan's bandwidth limit noticeably slows everyday loading and synchronization
cloudflared quick tunnel No account or domain Random temporary URL; no SSE, with notification limits; officially intended only for development and testing Frequent disconnections in long-term use, with the cause still unconfirmed; a temporary or testing choice
cloudflared named tunnel Cloudflare account and domain Fixed hostname; setup guide The most stable of the channels used long-term; worth trying first if you have an account and domain
Tailscale Funnel Sign-in and Funnel authorization Availability depends on the network This personal network often needs proxy assistance and may still fail to connect; not every user needs a proxy
Self-hosted FRP VPS and domain or real public IPv4 Server maintenance required; deploy or attach to existing frps More control over deployment and resources; long-term stability depends on the VPS route, configuration and maintenance
Own reverse proxy Existing public HTTPS proxy The plugin provides only its private authenticated backend; guide Reuses your proxy infrastructure; stability depends on the proxy, network route and maintenance
Managed Caddy Tencent Cloud DNSPod-managed domain and reachable public ingress Plugin-managed HTTPS and certificates on Windows/Linux x64; guide Does not traverse NAT; check inbound ports and forwarding. Existing Cloudflared users do not need to migrate

The following steps cover HTTPS remote channels. iroh uses its own “Generate iroh pairing QR code” action and the full App, as described below. Do not open its descriptor as an ordinary browser URL.

  1. Open Mobile Access in the lower-left corner of DeepSeek Harness, choose an HTTPS channel and complete its sign-in or configuration.
  2. Once ready, select Generate pairing QR code. External proxy mode's Backend listening does not establish public readiness; verify public HTTPS and WebSocket access as well.
  3. Select Remote access in the Android app and scan the current QR code. A publicly trusted certificate also permits pairing from a mobile browser.
  4. Later launches reconnect using the saved address and credential. If a temporary address changes, scan the current computer QR code to verify it. Do not clear app data; the stored device token never goes to a new Origin.

After selecting the channel in the panel:

  • iroh (experimental): select iroh, choose Install official component, then enable remote access after installation and verification. Once ready, choose Generate iroh pairing QR code and scan it through the full Android App's iroh flow, or copy the pairing link. Main actions stay hidden before installation; afterwards all three share one row, with Copy disabled until valid pairing data exists. After stopping the channel, component details let you remove the downloaded program without deleting identity or pairings. See the iroh guide for the full procedure and limits.
  • Tailscale Funnel: select Enable remote access, complete the one-time Tailscale sign-in on the official page, follow the panel prompt to allow Funnel, then return to DSH and wait until the connection is ready.
  • cpolar: select Install official component, sign in to the cpolar dashboard and obtain an Authtoken, paste it, then select Save and connect. The component is downloaded into the plugin's private directory only after confirmation; free temporary addresses may change after DSH or cpolar restarts.
  • Self-hosted FRP (advanced): if you have a VPS, select Self-hosted FRP under Mobile access and enter its frps details and a public HTTPS domain or real public IPv4 address. Apply the restricted frps + Caddy template manually, or deploy with an SSH key on Ubuntu/Debian with systemd. Password login is unsupported. Use manual deployment and merge the import as described in the guide when custom Caddy sites already exist. Verify the VPS host keys against its console before deployment or cleanup. The local frpc is downloaded and verified on demand; VPS cleanup is separate. Android app 0.3.3 or later is required. The self-hosted FRP guide covers certificates, ports, and the complete procedure.
  • Own reverse proxy: open Mobile access → Own reverse proxy, enter the public HTTPS origin (custom ports supported), private listen IP (IPv4 or IPv6 loopback/ULA), separate HTTP backend port (default 3444), and allowed direct proxy source CIDRs, then select Save and start backend. This uses your existing Lucky/Nginx/Caddy without a tunnel component and requires Android app 0.4.0 or later. See the own reverse proxy guide.
  • Managed Caddy: under Mobile access → Own reverse proxy, select Managed Caddy, choose Install managed Caddy, and confirm the download. Enter the public HTTPS origin, Tencent Cloud DNSPod credentials and local HTTPS listen port, then choose Save and start Caddy. A domain and reachable public ingress are required; this does not bypass CGNAT. See the managed Caddy guide for forwarding and complete steps.
  • cloudflared quick tunnel: select Install official component. After you confirm, the plugin downloads a pinned build from the official release page into its private directory and requests a temporary public address (a quick tunnel) with no sign-up or sign-in. Choose this when you would rather not create an account. The quick-tunnel hostname changes on every reconnect, and Cloudflare positions quick tunnels for testing: they are rate-limited and carry no uptime guarantee, so do not rely on one for production access that must stay reachable; it suits temporary or verification use.
  • cloudflared named tunnel: with a Cloudflare account and domain, switch Tunnel type to Named, then supply a connector token, a public hostname and a local forward port to get an address that survives restarts. The token is stored only in the private directory and reaches cloudflared through the environment rather than the command line; see Cloudflare named tunnel.

Remote notifications: Android task reminders use the page/SSE path and need the app's WebView to remain alive. iPhone/iPad Web Push is explicitly enabled from a capable Safari Home Screen app and does not need an open page. Both require DSH to keep running on the computer; networks, Focus settings and platform scheduling can delay delivery, so neither is a guaranteed alarm service. Independently configured channels such as dsh-ping remain unchanged.

The Funnel runtime ties the public listener to the parent process and a bounded control channel; parent exit, channel closure, or an explicit stop ends the current generation and cleans up its resources. An unregistered domain on a mainland-China VPS may be intercepted by the cloud provider; public IPv4 mode avoids that dependency. The plugin validates pinned on-demand components; locally managed configuration and binaries live under $DSH_HOME/mobile-access/ and can be cleaned up from the panel. VPS files require separate cleanup through the self-hosted connection guide.

Managed self-hosted FRP uses an HTTP vhost to the DSH loopback gateway. Its plaintext VPS listener must be loopback-only, with Caddy providing public HTTPS. Version 0.4.6 adds existing-frps attachment without installing or changing the server: its public-CA mode still needs a restricted HTTP vhost and Caddy, while its self-signed mode forwards raw TCP to a computer-side HTTPS gateway whose CA the 0.4.6 Android app pins during pairing. The self-signed mode currently uses public IPv4 and is unavailable to older apps. Neither mode exposes arbitrary FRP configuration. Because frps proxyBindAddr governs proxy listeners globally, do not change it for the new TCP entry without checking existing plaintext vhosts. See the attachment guide.

The own-proxy HTTP backend must remain on a trusted private network: never port-forward it publicly or bypass it by proxying to DSH or the existing LAN 3443 gateway. CIDRs match the proxy's direct TCP peer, not forwarded headers. Preserve the external Host (including port), Origin, cookies and WebSocket. Clearing proxy settings keeps paired remote devices.

See Compatibility for the supported components and platforms. Locally managed programs, credentials and settings can be removed from the panel; VPS files require separate cleanup through the corresponding guide.

Experimental iroh connection

Since plugin 0.7.0, the experimental transport from dsh-mobile-iroh is integrated into this repository. Its computer component, native Android transport and full APK are maintained here. The standalone repository retains the design and prototype records; normal installation uses this project's plugin and App, without maintaining two Apps. See the iroh guide for setup, platform limits and troubleshooting.

Extend and customize

Type /mobile <what you want> in a DSH conversation to hand the request to the current agent. Changed customization resources are usually picked up within a few seconds. For example:

/mobile turn the phone UI into an old CRT terminal, with messages scrolling like terminal output

It can also drive computer capabilities the phone can use, like reading the machine's live state:

/mobile give the phone a cyberpunk-style computer monitor panel that shows live CPU, memory, and disk usage

Two kinds of changes are supported: the phone UI itself (theme, layout, buttons), and computer capabilities the phone can use (browsing computer files, running programs on the computer). /mobile hands the request to the DSH agent, which edits files under the local DSH configuration directory ($DSH_HOME/mobile-access/); paired mobile pages automatically check and apply them. UI changes live in mobile.css/mobile.js. Computer capabilities come from extensions under extensions/, whose host.mjs runs with the local user's privileges on the computer. DeepSeek Harness source is not modified.

Open customizations through the Mobile Access pairing entry. Opening an ordinary DSH page or selecting a phone-sized browser viewport is not mobile pairing, and a file's presence does not establish that the current page loaded it. If extension requests return 401, check the entry and pairing state; do not enable anonymous access or share Cookies or Tokens.

An old mobile.css patch can override a newer built-in fix. Back up that file and compare the same session, orientation and font settings with and without its styles before adding more rules. Scope CSS Modules selectors to an inspected ancestor, such as [data-dsh-mobile-header] [class*="_titleRow"], rather than matching bare class suffixes/substrings across the page. Hiding an action area with display: none removes access to its controls; it is not a collapsible presentation. Thanks for the controlled comparison in #219.

Extension manifests, scripts, styles, and assets are revisioned. When the plugin observes a /mobile or extension-file change, it notifies authenticated phones to refresh immediately; 45-second visible and 5-minute hidden checks remain only as recovery fallbacks. A failed Host staging pass keeps the current version; if the Host has changed but the new phone UI cannot activate, that extension closes and retries instead of mixing generations.

An extension action's input may use a callable Schemastery schema such as api.schema.object(...) or an adapter with parse(value); mobile api.host.invoke() sends JSON explicitly, and the input is validated and normalized before the computer-side action runs.

Prefer DSH's built-in file upload for attachments. If an extension must simulate a drop, its dataTransfer needs iterable items (file items) as well as files; a files array alone is insufficient. Some WebViews have incomplete native drag-and-drop constructors; see the plugin's file-delivery implementation for compatibility handling. An accepted dragover or successfully dispatched event does not confirm attachment delivery: check the composer's attachments and previews.

The 0.6.3 release adds optional Worker execution for trusted local JavaScript hosts. It is disabled by default, selectable by extension, and recovers explicitly without replaying interrupted actions. It is not a permission sandbox and does not require a matching App version.

You can even use an extension to connect to SillyTavern running on the same computer, give it a lightweight mobile frontend, and open it from the same app.

host.mjs has the same privileges as a local program. Create and run only computer-side extensions that you understand and trust.

The examples above, applied:

Device management

The Android app lists computers and their LAN/remote records under Paired computers. The two authorization types remain separate, so one computer can have two rows. Upgrades migrate old credentials without re-pairing; after a changed address is verified, matching identities merge and keep their names. Self-signed FRP uses a separate CA fingerprint and may create another row. Android Keystore encrypts tokens and pinned CAs. A pairing QR code contains temporary pairing information, never a long-lived device token or CA private key.

Unless an identifier is configured manually, new pairings through a public-certificate remote entry use a random identifier saved on the computer, preventing identical installation paths from overwriting another computer's row. Working connections need no re-pairing or Android App update; LAN and self-signed FRP still use their respective CAs. Quit DSH normally and restart after updating; read the state-backup precautions before downgrading.

Each row shows its custom name, transport, Origin, periodically refreshed reachability, and last connection time. A green dot means Reachable; a gray dot means Checking, Temporarily unreachable, Pairing expired, or Removed on computer. The check validates the DSH Gateway over HTTPS instead of using ICMP, so a temporary network outage is not mistaken for computer-side revocation.

  • Startup behavior → Open DSH directly (default): one device connects directly; with multiple devices, the app tries the last-used device first, then the still-valid device with the most recent connection. A bounded connection budget returns to the list instead of spinning forever.
  • Startup behavior → Show device list: choose a computer on every launch, which is useful when switching between several machines. Open the list's top-right Settings → Startup behavior; changes are saved immediately.
  • Tap a row to connect. The overflow button and long press open the same action sheet for rename, check now, pair again, or delete the local record. Deletion has a second confirmation and a short undo window; undo restores only the local row and never restores a computer-side revocation.
  • Open DSH Settings → General → Switch computer in the WebView to return to the list. An online computer-side revocation keeps the row as Removed on computer, stops reconnection and offers re-pairing or local deletion.
  • Added in 0.6.0: fixed order, new computers appended, and migration of the previously visible order. Move up / Move to top save the arrangement independently from startup selection. Inside the app, hold the top-left drawer toggle to return to the list; a normal tap still toggles the drawer. Browsers have no such native action.

With App 0.6.7 and plugin 0.6.16, open the list's Settings → Automatic same-computer connection to choose Manual (default), Detect and ask, or Automatic switch and notify. Pair the computer's LAN and remote entries separately. Automatic mode transfers only eligible plain-text drafts in the current Session, not full page state; attachments, references or pending operations require confirmation. See the App switching guide.

Revoking a device permanently deletes its durable record and token digest instead of retaining a revokedAt tombstone. Startup also removes legacy revoked rows. A deleted token receives 401 authentication_failed, just like an unknown token. Existing apps checking a device that was revoked while offline may therefore show Pairing expired and require pairing again; online Sessions still receive the revocation notification and disconnect immediately.

Third-party plugin compatibility

Version 0.5.3 includes the independently switchable dsh-mobile-question-fixes component, enabled by default. Disable it in DSH's plugin component list to restore the stock card immediately. Long questions, options, and footer actions share one bounded scroll area, and collapsed titles show up to two lines. Touch Enter retains its newline in phone browsers; the Android app applies this behavior only when its software keyboard is open and no hardware keyboard is connected. DSH continues to own answer drafts, with no additional copy in browser localStorage.

DSH Mobile keeps the Workspace, task-management, terminal and file-panel entry points; DSH still loads third-party plugins. The mobile layer adapts layout and access without changing DSH source. A particular plugin's usability on a small screen still depends on its own layout and interactions.

A third-party plugin must work in DSH Web and use reachable HTTP/WebSocket interfaces. The mobile layer cannot guarantee a phone layout for every plugin or replace a desktop-native window required by that plugin.

A skin tied to stock layout containers may not mount its backgrounds or decorations in the dedicated mobile layout. Mobile page module settings can omit an optional skin on this device without uninstalling the computer plugin; see skins and mobile layout for theme behavior and diagnosis.

WebSocket approval

  • The gateway allows first-party DSH WebSocket paths by default, including /sidebar/ws/terminal. Other paths used by community sidebar plugins are blocked by default and appear in Diagnostics; the /sidebar/ws/agent-opens and /sidebar/ws/agent-terminals paths in the image are examples that must be reviewed for the actual plugin.
  • In Connection diagnostics → Third-party WebSocket paths, select Allow only for an exact path you have verified. Query strings and fuzzy prefixes are rejected; Allow all is not recommended. Approved paths can be removed at any time, and the same policy applies to LAN and remote connections.
  • Approval only lets that path pass through the authenticated, same-origin DSH Mobile gateway. It does not open arbitrary TCP/UDP ports or bypass device pairing. If a community plugin still fails, check the path recorded by Diagnostics and approve one path at a time.

If another remote-access plugin shows its own “not paired” page inside DSH Mobile, the two authorization systems are separate. Temporarily turn off the other plugin's remote access on the computer to check whether the Mobile path recovers; do not enter a DSH Mobile pairing key on that page. Excluding its client module below does not necessarily remove a request-rewriting script injected before client boot. See #111.

Allowing HTTP frames in the gateway does not make every client load them: the content is unencrypted, Android still blocks HTTP mixed content inside HTTPS pages, and browsers may block it too. Prefer HTTPS. The remote panel shows this risk when opened through an HTTPS administration entry.

Optional modules and advanced configuration

Version 0.6.0 adds mobile page module settings for computer defaults and device choices without uninstalling plugins. Changes apply on the next manual open, not an automatic conversation reload; an outdated saved selection offers an explicit recovery action.

Advanced users can reduce mobile startup traffic by adding exact package ids to excludedClientModules in the current profile's mobile-access plugin configuration, then restarting DSH. This changes only the dedicated mobile page served through the gateway; desktop and ?frontend=stock pages are unaffected. If both packages are present in the current boot graph, this example removes document preview and its dependent “Open In…” feature:

excludedClientModules:
  - '@deepseek-ai/dsh-client-ui-sidebar-documentpreview'
  - '@deepseek-ai/dsh-client-ui-open-in-app'

There is no default exclusion list. The plugin rejects unknown or boot-critical modules and modules still referenced through inject or external by retained entries. If a DSH or community-plugin update invalidates the selection, the mobile page returns 409 excluded_client_modules_invalid with the conflicting module; the computer also warns so you can adjust or remove the option. Bundle sizes and dependencies change between DSH installations and versions; another user's savings are not a prediction for yours.

Selection priority is device choice → computer defaults → plugin configuration. See the module guide for application and recovery rules.

App or mobile browser

Client Best for Notes
Android app Everyday use Separate Local and Remote entries at first pairing; LAN discovery, system trust for public remote certificates, and app-pinned CA for the self-signed FRP entry
iPhone/iPad Safari or Home Screen web app (PWA) Everyday iOS access and optional push Pair in Safari and add a Home Screen icon; no native iOS app. Capable Home Screen apps can enable Web Push
Mobile browser Everyday or cross-platform access Open the HTTPS origin shown by Mobile Access; a private LAN certificate may need confirmation, while a public remote certificate should not warn. Continuing through a certificate warning does not make the page eligible for Web Push

The Android app is a thin Kotlin WebView shell and contains no frontend copy; mobile browsers load the same page. Developers can append ?frontend=stock to an authenticated mobile URL to diagnose boot and layout behavior. This entry skips dedicated mobile boot rewriting and module selection, but installed client adaptation and authenticated customizations may still apply. It is not a plugin-free control; some API operations may be rejected, so it does not replace normal mobile access. See skins and mobile layout.

The dedicated mobile page synchronously loads the authenticated, same-origin /mobile-access/compat.js before the first DSH boot script. This bundled compatibility layer supplies missing Iterator / Iterator helpers, Promise.withResolvers and AbortSignal.any. It uses feature detection to preserve or repair native implementations, needs no CDN, and does not weaken CSP. The desktop and ?frontend=stock pages do not load this gateway script. On WebViews that support document-start injection, the Android App also supplies Promise.withResolvers early for the paired exact Origin.

Old-engine limits: API shims cannot repair JavaScript syntax an engine cannot parse. The published DSH 0.2.1-rc.2 frontend contains class static blocks, which Chromium 92 cannot parse. This syntax became enabled by default in Chrome 94, but that does not establish full DSH compatibility on 94. V8 announcement. The App's below-100 advisory is not a compatibility guarantee; choosing Continue does not make the current DSH runnable. If system WebView cannot be updated, use a phone browser already confirmed to work with the computer's mobile address, without clearing existing App pairings.

The current plugin retains the 0.6.12 compatibility layer and startup feedback, alongside 0.6.13's Gateway receive-timeout/header-size classification and packed text/image prompt-failure checks. It does not transpile or modify DSH, and it does not automatically replay messages; acceptance on the physical Huawei Chromium 92 App remains unverified. Reports should include DSH/plugin/App and WebView versions, entry mode and the first redacted console error, never tokens or complete pairing URLs.

Community client (unofficial): WeChat Mini-Program client A native WeChat Mini-Program that reuses the Mobile Access pairing and Remote stream protocol (requires dsh-mobile ≥ 0.3.8). Because WeChat release builds enforce a domain allow-list (ICP-registered HTTPS origins only), it currently works via WeChat DevTools / real-device debugging; see its README.

How it works

flowchart LR
  Phone["Android / mobile browser"] -->|"LAN HTTPS"| Lan["LAN gateway"]
  Phone -->|"remote HTTPS"| Remote["separate remote gateway"]
  Lan --> Gateway["DSH Mobile Gateway Core"]
  Remote --> Gateway
  Gateway -->|"loopback proxy"| DSH["Stock DSH Web and Host"]
  DSH -->|"same workspace, sessions and event stream"| Phone

Three layers: the Host face for discovery, pairing, HTTPS, loopback proxying, and extension registration; the Client face for the dedicated mobile layout and extension SDK; and the Android app for a narrow native bridge. The bridge uses androidx.webkit WebMessage, verifies the exact top-level origin and main frame on every bounded message, and never uses addJavascriptInterface. The plugin does not rewrite source or webpage files in the DeepSeek Harness installation. Its mobile gateway serves the startup compatibility layer and dedicated layout per request; installation and removal use the plugin mechanism. The upstream DSH Web port defaults to 3080 and is configurable through dsh web --port.

Security

  • Use the LAN listener only on a trusted home, office, or hotspot network; do not add your own port forwarding.
  • A remote origin is publicly reachable, but unpaired requests cannot enter DSH; turn the remote switch off when it is not needed.
  • cpolar downloads a pinned official build only after confirmation and verifies its size and SHA-256. It installs no system service, PATH entry, or startup task, and plugin cleanup removes its managed files.
  • cloudflared likewise downloads a pinned build from the official GitHub Release only after confirmation and verifies the exact size and SHA-256, and it launches the client with automatic updates disabled so the running binary is always the verified one. A quick tunnel needs no account, token, or DNS record; a named tunnel token is stored only in the plugin private directory and reaches cloudflared through the environment, and cleanup deletes every file it manages.
  • Managed Caddy downloads a fixed c

…