dsh-mobile-apk
Identified★ 940dsh Android Shell APK — WebView UI + Embedded Termux Runtime Snapshot (Unpack & Run). A high-performance solution designed for local execution of dsh.
dsh-mobile-apk — DeepSeek Harness Android Shell APK
dsh-mobile ecosystem · dsh-shell-termux (shell) · dsh-client-ui-responsive (mobile UI) · dsh-host-web-compat (browser compatibility) · dsh-mobile (coordination repo, private)
0.13.0 stable release: The full ADB real-channel pipeline (pairing / port discovery / shell execution / authorization gate / audit) is implemented and verified on real devices.
- Plugin marketplace adaptation note: the built-in marketplace involves many third-party plugins, most of which are not necessarily usable on mobile; the focus during this phase is on usability verification and feedback.
- Plugin marketplace adaptation warning: the built-in marketplace involves many third-party plugins, and the majority are not guaranteed to work on mobile and are very likely to have bugs (mobile and desktop differ greatly in WebView kernel / file system / permission model / runtime environment); mobile adaptation is a long-term engineering effort. During the beta phase the focus is on "usability verification and feedback" — do not treat it as a production dependency for now. Report plugin errors in issues (include device model / version / reproduction steps).
An Android shell for DeepSeek Harness: WebView UI overlay on top of
an embedded Termux runtime snapshot (unzip-and-run, no Termux app required), SAF directory bridge, keep-alive foreground service, engine watchdog,
and online runtime updates. One APK, install-and-use: a complete dsh web agent that can genuinely execute bash. App name DeepCode
(icon text DeepSearch), package name com.dsharnessmobile.shell, version 0.13.0-fx-1 (versionCode 26).
Features
- Embedded runtime: xz snapshot (arm64 151.6MB / x86_64 158.9MB) bundles node + git + bash + coreutils +
dsh + plugins + pnpm + python/perl/ruby; first-launch extraction takes 2–4 minutes (
refreshSnapshot), the engine listens on127.0.0.1:3080; fully offline; - File-direct session (F5): "Open with another app / Share" → auto-jumps to this app → forces a new temporary workspace session to process the file; temporary workspaces have a 7-day TTL with automatic cleanup and are visible in the workspace panel (issue #60);
- Search (grep/glob): mobile ripgrep platform package (android-arm64, pcre2/NEON full feature set);
- Notifications: automatic notifications on task completion (engine event bridge + watchdog consumption); system notification chain for authorization requests;
- Mobile UI: responsive plugins (drawer/sheet on phones); adjustable font size, immersive status bar, dark theme;
- Built-in console: standalone interactive bash terminal (
assets/console.html+ embedded Termux), usable for troubleshooting even when the engine is not running; - Keep-alive: foreground service + 5-second watchdog (auto-restarts a hung engine) + 3-second UI polling + automatic crash-fallback gate (UndoGate);
- Online runtime updates: manifest-driven snapshot replacement (download → sha256 → atomic switch → automatic restart), the runtime can self-update without updating the APK;
- APK self-update (0.13.8): the "Check for updates" button on the launch page is a manual trigger (no automatic checks) — queries the GitHub latest release, matches assets by device ABI, and falls back through the mirror chain level by level for downloads; when a new version is found, the same button changes to "Download and install vX.Y.Z" for a second confirmation; after confirmation, download → the system "Install unknown apps" authorization page is automatically raised on first use → system installer (signature mismatches are rejected by the system; the app does not silently install anything);
- SAF bridge:
pickDirectorymaps the selected directory to a real path (/storage/emulated/0/…); - Device access: all-file access; Shizuke liveness probe example;
- ADB real channel (0.13.0): real
adb pairSPAKE2 handshake + NSD/mDNS port discovery, executing system commands via adbd (shell uid=2000) (dangerous-command blacklist); three-gate authorization (full-access tier / in-app switch / pairing code) + real-time session tier gating + native audit (files/audit/audit.ndjson); connection port rotation self-healing (5555 fallback).
Download / Install
Release v0.13.0-fx-1 provides dual-ABI packages (also including the snapshot archive, plugin package, MANIFEST verification checklist, and release notes):
| APK | Suitable for |
|---|---|
dsh-mobile-apk-v0.13.0-fx-1-arm64.apk | arm64 devices (real hardware) |
dsh-mobile-apk-v0.13.0-fx-1-x86_64.apk | x86_64 emulators / devices |
adb install -r -t <apk> # 同签名覆盖安装
The ABI must match the device. An ABI mismatch crashes the engine at startup — node ELF EM_X86_64 vs EM_AARCH64.
Use the arm64 package on real devices and the x86_64 package on emulators.
Build
Snapshot building and packaging happen in the coordination repository (dsh-mobile); this repository is the shell repo. Requirements: JDK 17+, Android SDK (compileSdk 36); Gradle 8.11.1 is provided by the wrapper.
# 快照构建(Termux 源 + 依赖闭包 + pnpm + cordis 权威覆盖 + 瘦身):
node scripts\build-snapshot-013.mjs <arm64|x86_64>
# 一键打包(快照 → 注入 → 门禁 → gradle):
pwsh scripts\build-apk-013.ps1 -Suffix "-preview"
# 产物: out\v0.13.0\dsh-mobile-apk-v<ver>-<abi>.apk
Gates (inside build-apk-013.ps1): third-party compliance (check-third-party.mjs, GPL obligations) / 🔒 secrets /
ELF / cordis mount set ⊇ injection set / LICENSES self-check (Python streaming) — if any fails, packaging is rejected.
Bridge Protocol v1 (window.androidBridge)
App name DeepCode (icon text DeepSearch), package name com.dsharnessmobile.shell.
androidBridge.version returns the app version number (currently 0.13.0-fx-1, versionCode 26),
which the page uses for feature detection. The ADB methods below are a preview of the authorization surface — the real channel was completed in the 0.13.0 stable release.
Synchronous returns
| Method | Signature | Description |
|---|---|---|
version | () → string | App version number (0.13.0-fx-1), used for feature detection |
getSystemDark | () → boolean | System dark mode (bypasses some OEM WebViews' broken matchMedia; used for the first-frame theme) |
checkEngine | () → string | Probes 127.0.0.1:3080; JSON {running, latencyMs, error?} |
hasAllFilesAccess | () → boolean | Whether "all file access" permission has been granted (required for external workspaces) |
getPickToken | () → string | One-shot session token for the directory-picking bridge (validated on the engine-side pick endpoint) |
copyText | (text) → boolean | Writes to the system clipboard (fallback when WebView clipboard.writeText is rejected) |
getDevLogEnabled | () → boolean | dev log switch state of fact = preference && collector running (ST-11: reject optimistic setting) |
getImmersiveMode | () → boolean | Shell-side authoritative value of the immersive status bar switch (ST-10: the page treats this as the sole initial value; same source as setImmersiveMode) |
getAdbState | () → string | ADB authorization state view (three-gate state machine): JSON {fullAccess, allowSwitch, paired, wirelessDebugOn, message} (preview) |
discoverAdbPorts | () → string | Automatic wireless-debugging port scan (native TCP blind scan): JSONArray of candidate pairing ports; returns [] when wireless debugging is off (preview) |
setAdbPair | (code, pairPort, connectPort) → boolean | Gate 3 pairing: actually performs the adb pair handshake; the code value goes only into argv, not into the audit (preview) |
adbShell | (cmd) → string | ADB shell execution primitive: JSON {ok, stdout?, stderr?, guidance?}; unauthorized is fail-closed (preview) |
Commands
| Method | Signature | Description |
|---|---|---|
keepScreenOn | (enable) | Keep screen on toggle |
showNotification | (title, text) | Notification test channel (POST_NOTIFICATIONS) |
pickDirectory | (callbackId) | SAF directory selection; the result is returned asynchronously via window.__dshBridge.onDirectoryPicked(callbackId, path) |
pickImage | (callbackId) | SAF image selection; the result is returned asynchronously the same way |
setTextZoom | (percent) | WebView font scaling (50–200, settings-page slider) |
setImmersiveMode | (enable) | Immersive status bar toggle (true = status bar always hidden) |
downloadDebugLogs | () | Export engine logs + environment info (zip archive, via system share/download) |
requestAllFilesAccess | () | Opens the system "All files access" authorization page (special permission) |
restartEngine | () | Restarts the engine process (raised by the EngineService watchdog) |
shutdownToGuide | () | Stops the engine and falls back to the test screen (no auto-restart) |
reloadWebUI | () | Reloads the Web UI |
openConsole | () | Opens the built-in console |
setDevLogEnabled | (enabled) | Sets the dev log switch (when enabled, logs are written to dshdata/log/) |
setAdbAllow | (enable) | Gate 2 "allow access" switch (off by default; turning it off fails the channel closed) (preview) |
revokeAdbPair | () | Revokes pairing (disconnect + delete adbkey + clear state; with corresponding audit) (preview) |
The bridge protocol decouples the APK from dsh versions: pages do feature detection against androidBridge.version.
Online Update Protocol
- The app fetches
manifest.json:{url, sha256, size}(defaults tohttp://10.0.2.2:8899/manifest.jsonfor emulator testing; in production it points at the release server); - Download the snapshot → verify SHA-256 → extract to staging (without touching the live directory) → atomically switch
usr→ kill the old engine → the watchdog restarts with the new runtime.
Test trigger: adb shell am start -n com.dsharnessmobile.shell/.MainActivity -a com.dsharnessmobile.shell.action.UPDATE;
status is written to files/update-status.txt. Test server: run a local HTTP service serving manifest.json and the snapshot files
(by default it points to http://10.0.2.2:8899/manifest.json, which maps the host machine in the emulator).
APK Self-Update Protocol (0.13.8)
Completely separate from the runtime snapshot update above (UpdateChecker vs UpdateManager); it only manages the APK itself:
- Manual only: triggered by the "Check for Updates" button on the start page, no automatic checking (the 169MB asset performs no background/automatic behavior whatsoever);
- Metadata: fetched directly from
api.github.com/repos/kelai141/dsh-mobile-apk/releases/latest(10/15s timeout); failures report the actual reason (HTTP code/exception) and do not block the existing engine snapshot update check (the same button continues on to the snapshot check); - Asset matching:
dsh-mobile-apk-v<版本>-<abi>.apk, ABI taken fromSUPPORTED_ABIS[0](the device's native ABI— on x86 devices with ARM translation the abilist looks likex86_64,arm64-v8a,x86, so "contains arm64 means arm64" would pick the wrong package); - Version comparison: tag compared against
BuildConfig.VERSION_NAME(stripping the-SN-*snapshot suffix) by numeric component groups— covering both semantic versioning and0.13.7fx-Nrevision naming; - Mirror-chain download:
github.comdirect →gh-proxy.com→ghfast.top, falling back step by step, saved toDocuments/dshdata/updates/(within the existing FileProvider mapping),.tmp→ rename for atomicity; if a.sha256asset is present it is verified—on verification failure the file is deleted and an error is reported; a package already downloaded and verified is not re-downloaded (can be directly resumed after an authorization interruption); - Installation: if "Install unknown apps" permission is not granted → first open the system authorization page (auto-resume on
onResumeafter returning) → FileProvider URI +ACTION_VIEWto invoke the system installer; signature mismatch is rejected by the system. The app does not silently install.
This is the only external HTTP egress on the shell side (all other shell-side HTTP is consolidated onto the local engine's same-origin 127.0.0.1:3080),
and is only issued when the user taps the button.
Permissions
| Permission | Purpose |
|---|---|
INTERNET | WebView + engine probing + APK self-update (manual trigger only) |
POST_NOTIFICATIONS | Notification channel (requested at runtime on API 33+) |
FOREGROUND_SERVICE + FOREGROUND_SERVICE_DATA_SYNC | Keep-alive foreground service |
MANAGE_EXTERNAL_STORAGE | "All files access" (required for external workspaces; special permission, granted manually by the user) |
REQUEST_INSTALL_PACKAGES | Launches the system installer to install a downloaded update package (0.13.8; the user must explicitly authorize on the system page, "Install unknown apps") |
SAF directory/image picker needs no permission.
ABI and Page Size
Both arm64 and x86_64 have been verified end-to-end; the APK is distributed by ABI (the snapshot embeds architecture-specific content). 16KB-page builds must be produced on a 16KB-page device (see docs/design.md §ABI).
License
MIT. Third-party components follow their own licenses (see the dependency declarations). GPL compliance: the full copyleft text is present in all three forms — the snapshot
usr/share/LICENSES/, the repo LICENSES/, and the APK assets/licenses/. Design doc: docs/design.md.
Acknowledgments
Thanks to all community members for your feedback and contributions! Special thanks: cdwlll (environment issue feedback), haitunlang (MIUI12 compatibility), TACONailoong (legacy WebView compatibility solution), X-SCI-TECH (PR contribution), Yangerwei (file race feedback), gr12-cmd (armv7l requirement), cmyfqwq (overlay-install compatibility feedback).
We warmly invite developers to join: issues, PRs, and suggestions for improvement are welcome. What we especially need: Android compatibility testing
(Huawei/Honor/Xiaomi and other custom WebViews), support for more device types such as armv7l, ADB channel improvements, and plugin ecosystem expansion.
Development and maintenance conventions are in each repo's AGENTS.md (the development map).
Comments
Loading…
Similar plugins
by Hotsteel2901
Your DeepSeek Harness web UI, rebuilt for the phone in your hand. Built for developers who code in Termux on Android: single-column layout, sidebar drawer, one-line composer, fullscreen scrollable set
★ 12
MIT
JavaScript
Oct 18, 2026
dsh plugin --profile web add dsh-client-ui-mobile-adaptby kelai141
dsh Web UI 的移动响应式 AppFrame——派生自 dsh-client-ui-layout,新增 <640px 抽屉侧栏、底部 sheet 与安全区。
★ 4
MIT
TypeScript
Oct 18, 2026
dsh plugin --profile web add @dsh-android/dsh-client-ui-responsiveby saya-ch
DeepSeek Harness 的 Android App 与安全远程访问插件,支持局域网/远程连接和高度自定义的移动界面与扩展能力。
★ 664
↓ 4.2k/wk
Apache-2.0
TypeScript
Oct 28, 2026
dsh plugin --profile web add dsh-mobileby crwsr124
Mobile experience suite for the DeepSeek Harness web UI — responsive reading layout, composable glass skinning, download affordances for the built-in 0.1.5 files sidebar, and session-state healing. Zero package dependencies.
★ 0
MIT
JavaScript
Sep 22, 2026
dsh plugin --profile web add dsh-mobile-layoutby yunliya-cuter
DSH Web GUI 暖色主题 + 液态玻璃材质 + 输入栏工具行整形(客户端插件包)
★ 0
MIT
JavaScript
Sep 30, 2026
dsh plugin --profile web add dsh-warm-uiby ImHaoYuan
DSH 插件:搭建远程控制局域网服务器,手机浏览器直连,也可下载App
★ 0
MIT
JavaScript
Oct 10, 2026
dsh plugin --profile web add dsh-mobile-mirror