dsh-mobile-apk: an Android shell that ships its own Termux runtime for DeepSeek Harness
dsh 安卓壳 APK——WebView UI + 内嵌 Termux 运行时快照(解压即跑),为dsh本地运行设计的高性能方案
At a glance
- What is it?
- The repository packages a WebView UI, an embedded Termux snapshot and a real ADB channel into one APK, so a phone can run the dsh web agent and execute bash without installing Termux separately. The trade-off is size, ABI matching and a plugin ecosystem the README itself warns is mostly untested on mobile.
- Who is it for?
- Adopt dsh-mobile-apk if you want a dsh web agent on a real Android device and you accept a roughly 150 MB snapshot that unpacks on first launch, plus an arm64 or x86_64 package that must match your hardware. Do not adopt it as a production dependency for third-party dsh plugins, because the README states most of the bundled market is not verified on mobile and likely to have bugs, and do not expect it to be a general Linux environment for Android.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem dsh-mobile-apk solves: running a dsh agent on a phone without a separate Termux install
DeepSeek Harness is a web agent that expects a shell. On a desktop that is a given. On Android it is not: you normally install Termux, build or fetch a Node runtime, arrange a working directory, and then find some way to reach the agent from a UI. dsh-mobile-apk collapses that into one APK. The repository description calls it a WebView UI plus an embedded Termux runtime snapshot, unpack-and-run, aimed at local dsh execution on Android. The README is explicit that no Termux app is needed, and that the result is a complete dsh web agent that can really execute bash. The audience is narrow and identifiable: people who already use dsh and want it on a phone, not people looking for a general-purpose Linux terminal on Android. The application name is DeepCode, the icon text is DeepSearch, and the package is com.dsharnessmobile.shell.
What actually runs: a snapshot, a local engine on port 3080, and a watchdog
The mechanism is a bundled filesystem image. The repository ships an xz snapshot, 151.6 MB for arm64 and 158.9 MB for x86_64, containing node, git, bash, coreutils, dsh, plugins, pnpm and python/perl/ruby. On first launch the app extracts it through a routine the README calls refreshSnapshot, which takes 2 to 4 minutes. After that the engine listens on 127.0.0.1:3080 and the whole thing works offline. The WebView UI sits on top and talks to the app through a JavaScript bridge exposed as window.androidBridge. The bridge is versioned: androidBridge.version returns the application version, currently 0.13.0-fx-1 with versionCode 26, and the README states the page uses it for feature detection. That detail matters more than it looks. It means the UI and the native shell can drift apart without breaking, because the page can ask what the shell supports instead of assuming. Around the engine sit a foreground service, a 5-second watchdog that restarts a hung engine, a 3-second UI poll, and an UndoGate that falls back on crash.
Installing the APK and getting a first session
Releases carry two packages, one per ABI, and the README is blunt that the ABI must match the device: a mismatch crashes the engine on start because the node ELF is EM_X86_64 or EM_AARCH64. Real devices take the arm64 build, emulators take x86_64. The install command given in the README is:
adb install -r -t <apk> # 同签名覆盖安装Once installed, launch the app and wait. The first run extracts the snapshot, which the README puts at 2 to 4 minutes, and the engine then comes up on 127.0.0.1:3080. The bridge exposes a synchronous probe named checkEngine that tests whether the engine is up and returns JSON containing running, latencyMs and an optional error field. For a first real task, the README describes a file-to-session path: open a file in another app and choose open-with or share, which routes to this app and forces a new temporary workspace session. Those temporary workspaces carry a 7-day TTL and are cleaned automatically, with the workspace panel showing what exists. If the engine is not running and you need to debug, the built-in console is a separate bash terminal backed by the same embedded Termux, opened through the openConsole bridge method.
The ADB channel and its three authorization gates
Version 0.13.0 added a real ADB path, and the README describes it as fully implemented and verified on a physical device. It performs a genuine adb pair SPAKE2 handshake, discovers ports through NSD/mDNS, and executes system commands through adbd under shell uid 2000. Three gates must open before anything runs: the full-access tier, the in-app switch, and the pairing code. Session tier is gated in real time, and every action lands in a native audit log at files/audit/audit.ndjson. The pairing code itself goes only into argv and is not written to the audit. Dangerous commands are blocked by a blacklist. Connection ports rotate and self-heal, with a fallback to 5555. The bridge methods behind this are marked as a preview authorization surface in the README, including setAdbPair, adbShell, discoverAdbPorts, setAdbAllow and revokeAdbPair. The design is fail-closed: adbShell returns a JSON object with ok, stdout, stderr and guidance, and an unauthorized call fails rather than degrading. If you are evaluating this for anything beyond personal use, the audit file and the revoke path are the two things to read first in the source.
Where dsh-mobile-apk breaks down
The most honest paragraph in the README is the plugin market warning. It states that the built-in market pulls in a large number of third-party plugins, that most of them are not necessarily usable on a phone and are likely to have bugs, because mobile and desktop differ substantially in WebView engine, filesystem, permission model and runtime environment. It calls mobile adaptation a long-term effort and says the beta stage is about verifying usability and collecting feedback, and it explicitly does not recommend treating plugins as a production dependency. That is a real limitation, not a disclaimer. A second one is the ABI coupling: there is no universal APK, and the wrong package fails at engine start rather than at install. A third is first-run cost. Extracting a 150 MB snapshot over 2 to 4 minutes is not a background nicety, it is a wait before anything works. And the scope is bounded: external workspaces require all-files access, so on a locked-down device or a work profile the file-to-session path may simply be unavailable. If you want a general Linux environment on Android, this is the wrong tool; it is a host for one specific agent.
Termux plus a Node runtime, and how the approach differs
The obvious alternative is the manual route: install Termux, install a Node runtime inside it, install dsh, and reach the web UI from a browser on the same device. The difference is not convenience, it is where the runtime lives. In the manual route the runtime is yours to manage, update and break, and the UI is a browser tab with no native bridge. In dsh-mobile-apk the runtime is a snapshot owned by the app, replaced wholesale through a manifest-driven update. The README describes the sequence: the app fetches manifest.json with url, sha256 and size, downloads the snapshot, verifies SHA-256, extracts to staging without touching the live directory, atomically switches usr, kills the old engine, and the watchdog restarts with the new runtime. That means the runtime can update itself without an APK update. That is the architectural bet: you give up control of the runtime in exchange for a managed one. The APK self-update path is deliberately separate, handled by UpdateChecker rather than UpdateManager, and it is manual only. The README states it never checks automatically, queries the GitHub latest release endpoint with 10 and 15 second timeouts, matches assets by SUPPORTED_ABIS[0], and falls back through a mirror chain. A failure there reports the HTTP code or exception and does not block the snapshot check.
Licence, maintenance and what an upgrade costs you
The repository is MIT licensed. That covers the shell code, but the bundled snapshot is a different question: the build pipeline runs a third-party compliance gate called check-third-party.mjs inside build-apk-013.ps1, described as enforcing GPL obligations, and the repository carries a LICENSES directory and a THIRD_PARTY_NOTICES.md. If you redistribute a built APK, the snapshot contents are the part to inspect, not the MIT header on the shell. The last push to the repository was on 2026-09-16, and the most recent release is v0.14.0-preview from 2026-09-13, following v0.13.8 and v0.13.7fx-1 earlier that month. The release cadence is fast and the versioning is honest about maturity: the preview tag is there for a reason. Upgrade cost splits in two. Runtime updates are cheap by design, since the snapshot swaps atomically and the engine restarts. APK updates cost a large download and a manual button press, and the README notes signature mismatch is rejected by the system installer, so you cannot move between differently signed builds without uninstalling.
Editorial conclusion
Adopt dsh-mobile-apk if you want a dsh web agent on a real Android device and you accept a roughly 150 MB snapshot that unpacks on first launch, plus an arm64 or x86_64 package that must match your hardware. Do not adopt it as a production dependency for third-party dsh plugins, because the README states most of the bundled market is not verified on mobile and likely to have bugs, and do not expect it to be a general Linux environment for Android. Before installing, verify three things: that your device ABI matches the APK you download, that you can grant all-files access because external workspaces require it, and that you have 2 to 4 minutes of first-launch time for the snapshot extraction.
Frequently asked questions
How do I download the dsh-mobile-apk?
Releases publish two APKs, one for arm64 devices and one for x86_64 emulators or devices, alongside the snapshot archive, plugin package and a MANIFEST checksum file. The README gives adb install -r -t as the install command, and warns that the ABI must match the device or the engine crashes on start.
Is there an Android app for running dsh locally?
dsh-mobile-apk is that app: an Android shell for DeepSeek Harness with a WebView UI over an embedded Termux runtime snapshot. The README states it needs no Termux app and runs the complete dsh web agent with real bash execution, offline, with the engine on 127.0.0.1:3080.
Does dsh-mobile-apk update itself automatically?
No. The README states the APK self-update is manual only, triggered by the check-update button on the start screen, and that it never checks automatically. Runtime snapshot updates are a separate mechanism from the APK update.
Why does the first launch of dsh-mobile-apk take minutes?
The app unpacks an embedded xz snapshot on first start, 151.6 MB for arm64 or 158.9 MB for x86_64, containing node, git, bash, coreutils, dsh, plugins, pnpm and python/perl/ruby. The README puts that extraction at 2 to 4 minutes.
Can I use third-party dsh plugins with dsh-mobile-apk?
The README warns that the built-in plugin market covers many third-party plugins, that most are not necessarily usable on mobile and are likely to have bugs, and that mobile adaptation is a long-term effort. It says the beta stage focuses on usability verification and feedback, and does not recommend treating plugins as a production dependency.
Community notes