8.7 KiB
tmux Android
Android API client for tmux-ui / tmux-browser.
The server project is expected to already be running on port 3000. This app does not host or load the existing web UI. It calls the existing HTTP and WebSocket APIs directly:
- server URL management for Tailscale
100.x.y.z:3000APIs - quick server selectors for
100.89.0.2,100.89.0.4,100.89.0.9,100.89.0.11, and100.89.0.116 - one-tap probe for the preset Tailscale APIs, showing health/version and session counts
- native tmux session list
- Sessions page with current API/server and loaded session count
- native Projects page for kanban project grouping, project agents, project messages, add/remove session, create, and delete actions
- create, rename, send command, split pane, select pane, kill pane, pin, mute, and kill session through HTTP API
- open one live terminal viewer through
/ws/terminal - native
/ws/eventslistener for session invalidation and hook notifications - selectable Gitea or GitHub update source, defaulting to Gitea for mobile reachability
- native Tools page for health, server status, timeline, preferences, hook events, image file/URL upload, image preview info, and native image preview display
- mobile soft-key row for tmux-oriented input, including tmux prefix, detach, new window, previous/next window, Ctrl keys, arrows, page keys, and paste
- terminal viewport resize based on the phone's visible text area, including keyboard height changes, so tmux output wraps at the same width the user sees
- automatic update checks with Gitea first and GitHub fallback, plus manual source-specific checks
- one-download-per-version APK cache, SHA-256 verification, and installer handoff
- native Update and About pages for version/build type, protocol, permission, selected update source, and release information
Server URL
Default:
http://100.89.0.116:3000
On a physical Android device, 127.0.0.1 means the phone itself. The app
therefore defaults to Tailscale and includes quick selectors for:
http://100.89.0.2:3000
http://100.89.0.4:3000
http://100.89.0.9:3000
http://100.89.0.11:3000
http://100.89.0.116:3000
The upstream server should stay bound to localhost or a private Tailscale IP.
Do not expose terminal control on 0.0.0.0 to the public internet.
GitHub Actions Build
The workflow in .github/workflows/android.yml builds APKs online.
Required environment on Actions:
ubuntu-latest- JDK 17
- Android SDK platform 35 installed by
android-actions/setup-android - Gradle 8.10.2 installed by
gradle/actions/setup-gradle - Android Gradle Plugin 8.7.3 from Google Maven
For release builds that can update an already installed app, configure these repository secrets:
ANDROID_KEYSTORE_BASE64
ANDROID_KEYSTORE_PASSWORD
ANDROID_KEY_ALIAS
ANDROID_KEY_PASSWORD
Create the base64 value from your release keystore:
base64 -w 0 tmux-android-release.jks
Branch builds and manual workflow runs create Actions artifacts only. Use them to verify grouped changes before publishing.
Gitea is the primary build and update channel. Normal main pushes run the
Gitea Android workflow for compile checks, while GitHub no longer builds every
main push. Publish a release build by pushing a v* tag after a coherent
feature/test batch, not every small UI or text change.
Tag publishing can create GitHub Release assets with:
https://github.com/neatstudio/tmux-browser-android/releases/latest/download/tmux-android.apk
https://github.com/neatstudio/tmux-browser-android/releases/latest/download/latest.json
Gitea is also the app's default install/update channel because phones may not be
able to reach GitHub reliably. GitHub remains an optional public source. This
Gitea instance does not support the GitHub-style
/releases/latest/download/... URL, so the app uses the Gitea Release API as
the stable Gitea update entrypoint.
Release APKs on GitHub and Gitea should either be the exact same file or be
built from the same tag with the same signing keystore, versionCode, and
versionName. The Gitea workflow publishes release assets only when signing
secrets are present. Unsigned Gitea builds remain compile checks and must not be
used for automatic in-place updates.
Plain branch builds are useful for CI verification, but releases are the stable download/update channel.
Unsigned/debug workflow artifacts are useful only for smoke testing install and launch. Automatic in-place updates require release APKs signed with the same keystore every time; otherwise Android treats the APK as a different or incompatible package.
Current Terminal Scope
The terminal screen connects to /ws/terminal and sends the upstream protocol
messages unchanged: attach, input, resize, scroll, and clear-history.
The Android UI renders terminal output through a lightweight screen buffer with
cursor movement, line clearing, screen clearing, basic ANSI SGR color support,
and throttled redraws. It is enough for shell-oriented remote testing, but it is
not yet a complete xterm-compatible renderer for full-screen TUIs such as vim
or top.
The terminal input area is a native multi-line composer with a paged accessory
bar for editing keys, control keys, tmux prefix helpers, navigation keys, and
common shell symbols. The app sends the same control bytes a keyboard would
send, for example Ctrl+B, Ctrl+B d, Ctrl+B c, Ctrl+B n, and Ctrl+B p.
All app features are native Android controls. Complex server objects such as
preferences, timeline events, group messages, and image metadata currently use
native forms plus native JSON detail dialogs; kanban projects use a native
project/agent list; image preview uses a native ImageView. The app does not
load the browser UI.
Permissions
The app needs network access and package install handoff for updates. Android does not ask at runtime for normal internet access. Android 8+ requires the user to allow this app to install unknown apps before automatic update installation can continue. Android 13+ may ask for notification permission.
SMS permission is intentionally not requested because tmux-browser-android does not read or send SMS.
Auto Update
Normal Android apps cannot silently replace themselves. This app checks the release manifest automatically, downloads the newer APK, verifies its SHA-256, then opens Android's package installer. The user still has to approve the install, and Android 8+ may require allowing this app to install unknown apps.
The default update source is the Gitea Release API:
https://gitea.neatcn.com/api/v1/repos/tmux/tmux-browser-android/releases/latest
The default source resolves latest.json and tmux-android.apk from Gitea
release assets, so APK downloads do not require GitHub. The optional GitHub
manifest is:
https://github.com/neatstudio/tmux-browser-android/releases/latest/download/latest.json
The app has four update checks on the Update page:
Auto checktries Gitea first, then tries GitHub only if Gitea cannot be reached.Giteachecks only the public Gitea release API.GitHubchecks only the public GitHub manifest.Selectedchecks the source chosen withSource, including a custom manifest/API URL.
Each source retries transient network failures before that source is considered
failed. The APK and Release page buttons still resolve from the selected
source, so they can be forced to Gitea on phones that cannot reliably reach
GitHub.
Gitea tag-specific assets are also public, for example:
https://gitea.neatcn.com/tmux/tmux-browser-android/releases/download/v0.1.7/latest.json
https://gitea.neatcn.com/tmux/tmux-browser-android/releases/download/v0.1.7/tmux-android.apk
In the app:
- Open the
Updatepage and tapAuto checkto checklatest.json, download the APK, verify SHA-256, and open Android's installer. UseGitea,GitHub, orSelectedto force a single update source. - If the same version APK was already downloaded and its SHA-256 still matches, the app reuses that file instead of downloading it again.
- If Android sends you to the unknown-app install permission screen, return to the app after allowing it; the app continues installing the already downloaded APK without another update check or download.
- Open the
Updatepage and tapAPKto resolve the APK from the selected update source and open it in a browser. - Open the
Updatepage and tapDetailsto see the installed version, selected update source, APK/Release resolver behavior, install permission state, and aCheck updatebutton. - Open the
Updatepage and tapApp settingsfor Android's full per-app permission/settings screen. - Open the
Aboutpage to see the app version/build type, package name, API/protocol summary, selected update source, and update policy.