This guide documents the internal architecture, build system, configuration surface, security model, and operational concerns of the Termux Android application — the terminal emulator and Linux-environment app published at termux/termux-app. It is written for administrators, ROM/device integrators, plugin developers, contributors, and anyone forking or auditing the codebase.
Important
This repository is the app (UI + terminal emulation + bootstrap installer). The thousands of installable command-line programs are a separate project, termux-packages, which builds the bootstrap archives this app downloads at build time and unpacks at runtime. The two are versioned and maintained independently.
1. Executive Summary
Termux is a native Android application (Java, Android SDK) that provides a full terminal emulator and a self-contained Linux userland under the app's private data directory — no root, no special device configuration. It is organized as a four-module Gradle project:
| Module | Type | Responsibility |
|---|---|---|
terminal-emulator |
Android library | Headless VT100/xterm terminal engine + JNI process/PTY creation. Pure logic, no Android UI. |
terminal-view |
Android library | An Android View that renders a terminal session and handles touch, gestures, and text selection. Depends on terminal-emulator. |
termux-shared |
Android library | Shared constants, file/permission utilities, settings, shell-command runners, and the local am socket server. Imported by the app and by every plugin. |
app |
Android application | The user-facing app: activities, the foreground service, session management, the bootstrap installer, and intent receivers. |
The terminal engine and view are deliberately decoupled from Termux specifics so they can be reused (they are published to JitPack as com.termux:terminal-emulator and com.termux:terminal-view). All Termux-specific behavior — paths, package names, intent contracts, properties — is centralized in termux-shared's TermuxConstants, which is the single source of truth for the whole ecosystem.
Key facts at a glance:
| Property | Value |
|---|---|
| Package name | com.termux |
| Version | versionCode 118, versionName 0.118.0 (latest release 0.118.3) |
minSdkVersion |
21 (Android 5.0) |
targetSdkVersion |
28 (Android 9) |
compileSdkVersion |
36 |
ndkVersion |
29.0.14206865 |
| Android Gradle Plugin | 8.13.2 |
| Java level | Source/target 1.8 (with core library desugaring) |
| Bootstrap variant | apt-android-7 (default) or apt-android-5 |
| Shared user ID | com.termux (shared by app + all plugins) |
2. Architecture
2.1 Module dependency graph
┌──────────────────────────┐
│ app │ (com.android.application)
│ Activities, Services, │
│ Installer, Receivers │
└───────────┬──────────────┘
│ implementation
┌─────────────────┼──────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────┐ ┌──────────────────┐
│ terminal-view │ │ termux-shared│ │ (AndroidX, │
│ (Android View) │ │ (constants, │ │ Material, │
└────────┬─────────┘ │ utils, IPC) │ │ Guava, Markwon)│
│ api └──────┬───────┘ └──────────────────┘
▼ │ implementation
┌──────────────────┐ │
│ terminal-emulator│◄───────┘
│ (VT engine+JNI) │
└──────────────────┘
terminal-view exposes terminal-emulator transitively via api. termux-shared also depends on terminal-view (for terminal constants) and on com.termux:termux-am-library.
2.2 The terminal engine (terminal-emulator)
A headless, reusable terminal emulator written in Java. Principal classes:
| Class | Role |
|---|---|
TerminalEmulator |
The core state machine: parses the byte stream, implements escape-sequence handling (CSI, OSC, DCS, etc.), cursor and screen state, modes, and styles. |
TerminalBuffer |
The screen + scrollback buffer of TerminalRows. |
TerminalRow |
One row of cells with text and style runs. |
TerminalSession |
Owns a child process and its PTY, pumps bytes between the process and the TerminalEmulator, and notifies a TerminalSessionClient. |
KeyHandler |
Maps Android key events to terminal byte sequences. |
TextStyle |
Packs foreground/background color and attributes into a long. |
TerminalColors / TerminalColorScheme |
256-color + theme handling. |
WcWidth |
Unicode character-width calculation (wide/CJK/combining). |
ByteQueue |
Thread-safe pipe between the reader thread and the emulator. |
JNI |
Native bridge declarations. |
The native side (src/main/jni/termux.c, built with ndk-build via Android.mk) forks the shell, allocates a pseudo-terminal, and wires file descriptors — the mechanism that lets a normal Android app host real subprocesses.
Note
The emulator has the project's strongest test coverage —
terminal-emulator/src/test/java/...contains ~19 JUnit test classes covering CSI sequences, DEC private modes, OSC/APC/DCS handling, cursor/screen behavior, resizing, scroll regions, history, and Unicode input. When modifying escape-sequence handling, extend these tests first.
2.3 The terminal view (terminal-view)
| Class | Role |
|---|---|
TerminalView |
The View subclass that draws a TerminalSession, handles input connection (IME), scrolling, autofill, and the context menu. |
TerminalRenderer |
Canvas drawing of cells, colors, and the cursor. |
GestureAndScaleRecognizer |
Pinch-to-zoom (font size) and scroll gesture handling. |
TextSelectionCursorController / TextSelectionHandleView / CursorController |
Drag-handle text selection UI. |
TerminalViewClient |
Callback interface the host (the app) implements to receive key/scroll/longpress events. |
2.4 The shared library (termux-shared)
This is the largest surface and the integration point for plugins. Notable areas:
| Package | Contents |
|---|---|
termux |
TermuxConstants (all paths, package names, intent contracts), TermuxBootstrap, TermuxUtils. |
termux.settings.properties |
TermuxPropertyConstants (every termux.properties key), TermuxSharedProperties, TermuxAppSharedProperties. |
termux.settings.preferences |
Per-app SharedPreferences wrappers (TermuxAppSharedPreferences, TermuxAPIAppSharedPreferences, …) and TermuxPreferenceConstants. |
termux.extrakeys |
The extra-keys model: ExtraKeysConstants, ExtraKeysInfo, ExtraKeysView, ExtraKeyButton. |
shell.command |
ExecutionCommand (the universal command descriptor), result config/data, and the runner abstraction. |
shell.command.runner.app |
AppShell — runs a background process and captures stdout/stderr/exit code. |
shell.command.environment |
Builds the shell environment ($PREFIX, $HOME, $PATH, $TMPDIR, etc.). |
shell.am |
AmSocketServer — a local socket server that lets in-Termux processes invoke Android's am via the termux-am client (backed by native local-socket.cpp). |
file / file.filesystem |
FileUtils and a partial NIO-style filesystem layer (permissions, attributes, types). |
android |
PermissionUtils, PackageUtils, FeatureFlagUtils, PhantomProcessUtils, ProcessUtils, SELinuxUtils — Android-system integration, including reflection that bypasses hidden-API restrictions. |
errors |
Error, Errno, FunctionErrno — a structured error type used across the codebase instead of bare exceptions. |
crash / notification / markdown / logger |
Crash reporting, notifications, Markwon-based Markdown rendering, and the leveled logger. |
2.5 The application (app)
TermuxApplication.onCreate()
├─ install crash handler
├─ configure logger (log level from prefs)
├─ set bootstrap package variant (from BuildConfig.TERMUX_PACKAGE_VARIANT)
├─ init TermuxAppSharedProperties (loads termux.properties)
├─ init TermuxShellManager
├─ set app night mode
├─ verify files dir accessible → setup termux-am socket server
└─ init + write TermuxShellEnvironment to file
TermuxActivity (launcher, singleTask)
├─ load properties + theme, inflate terminal layout
├─ create TermuxTerminalViewClient + TermuxTerminalSessionActivityClient
├─ wire extra-keys toolbar (ViewPager: extra keys ⇄ text input)
├─ startService(TermuxService) + bindService(...)
└─ onServiceConnected:
if no sessions → TermuxInstaller.setupBootstrapIfNeeded(...) → addNewSession()
else → restore current/last session
TermuxService (started + bound foreground service)
├─ holds the list of TerminalSessions (foreground)
├─ holds background AppShell tasks
├─ ACTION_SERVICE_EXECUTE → create session or run background command
├─ persistent notification (keeps process alive)
└─ survives TermuxActivity destruction (work keeps running)
RunCommandService (exported, permission-protected)
└─ ACTION_RUN_COMMAND → validate → forward as ACTION_SERVICE_EXECUTE to TermuxService
Lifecycle highlights:
TermuxActivityis a thin UI shell. TheTermuxServiceis the durable owner of sessions and background tasks, so closing the activity does not kill running commands (the notification keeps the process alive).- The activity and service communicate through a local
ServiceConnection(LocalBinder), not IPC. - A
BroadcastReceiverinside the activity listens forACTION_RELOAD_STYLE(re-read properties / restyle),ACTION_NOTIFY_APP_CRASH, andACTION_REQUEST_PERMISSIONS.
2.6 Bootstrap installation flow (TermuxInstaller)
On first launch (when $PREFIX is missing or empty), the app installs the base system:
- Verify the app runs as the primary user and that the files directory is accessible (fail with a clear dialog otherwise).
- Show an "Installing…" progress dialog.
- Load the bootstrap zip from an embedded native library —
System.loadLibrary("termux-bootstrap")thengetZip()(JNI). The zip is compiled into the APK at build time (see §4.3). - Extract entries into a staging directory
…/files/usr-staging:SYMLINKS.txtentries (formattarget←linkpath) are collected and recreated as symlinks.- Files under
bin/,libexec/, and apt helper/method paths get mode0700.
- Atomically
rename()staging →$PREFIX(so a crash mid-extract never leaves a half-written prefix). - Write the shell environment file.
On error, a dialog offers Abort or Try again (which wipes $PREFIX and retries). setupStorageSymlinks() (invoked by termux-setup-storage) builds the ~/storage/* symlink tree into Android shared storage.
3. Filesystem & Runtime Layout
All paths derive from TERMUX_PACKAGE_NAME (com.termux) in TermuxConstants. The binaries in the bootstrap have $PREFIX hard-coded at compile time, which is why forking requires rebuilding the bootstrap.
| Logical name | Path | Purpose |
|---|---|---|
| App data dir | /data/data/com.termux |
Android private app data |
| Files dir | /data/data/com.termux/files |
Root of the Termux userland |
$PREFIX |
/data/data/com.termux/files/usr |
Installed packages root |
$PREFIX/bin |
…/usr/bin |
Executables |
$PREFIX/etc |
…/usr/etc |
Package configuration |
$PREFIX/lib |
…/usr/lib |
Libraries |
$PREFIX/libexec |
…/usr/libexec |
Helper executables |
$PREFIX/share |
…/usr/share |
Arch-independent data |
$PREFIX/var |
…/usr/var |
Variable state (apt, dpkg) |
$TMPDIR |
…/usr/tmp |
Temp files (auto-cleaned on exit per property) |
$HOME |
/data/data/com.termux/files/home |
User home directory |
| Staging prefix | …/files/usr-staging |
Bootstrap extraction staging |
| Config (primary) | ~/.termux/ |
termux.properties, colors.properties, font.ttf, boot/ |
| Config (secondary) | ~/.config/termux/ |
Alternate termux.properties location |
| Storage symlinks | ~/storage/ |
Symlinks into Android shared storage |
Note
termux.propertiesis read from the first of~/.termux/termux.propertiesthen~/.config/termux/termux.properties. The float plugin usestermux.float.propertiesin the same two locations.
4. Build System
4.1 Project configuration
Top-level build.gradle pins AGP 8.13.2 and uses mavenCentral(), google(), and jitpack.io repositories. gradle.properties defines the SDK/NDK versions and markwonVersion=4.6.2. The app module applies com.android.application; the three libraries apply com.android.library + maven-publish.
4.2 Package variant
packageVariant = System.getenv("TERMUX_PACKAGE_VARIANT") ?: "apt-android-7"
The variant (apt-android-7 or apt-android-5) selects which bootstrap is bundled and is written into BuildConfig.TERMUX_PACKAGE_VARIANT. TermuxApplication reads it via TermuxBootstrap.setTermuxPackageManagerAndVariant(...). The variant baked into the APK must match the device's Android version — mixing causes startup crashes, which is why the app validates it.
4.3 Bootstrap archives
The downloadBootstraps Gradle task downloads the per-architecture bootstrap zips from termux-packages releases and verifies each against a hard-coded SHA-256:
| Variant | Source |
|---|---|
apt-android-7 |
bootstrap-2026.02.12-r1+apt.android-7 release (aarch64, arm, i686, x86_64) |
apt-android-5 |
bootstrap-2022.04.28-r6+apt-android-5 release |
The download runs as a dependency of javaCompile. The zips are embedded into the APK as a native shared library (app/src/main/cpp/termux-bootstrap.c + termux-bootstrap-zip.S, built with ndk-build) and later read by TermuxInstaller.getZip().
4.4 APK splits, signing, build types
- ABI splits for
x86,x86_64,armeabi-v7a,arm64-v8aplus a universal APK, controlled byTERMUX_SPLIT_APKS_FOR_*env vars. F-Droid ships universal only (it does not support split APKs). - Debug builds are signed with the in-repo
app/testkey_untrusted.jks(see §6.4). - Release builds enable
minifyEnabled(ProGuard) withshrinkResources falsefor reproducible builds. - Output APKs are named
termux-app_<tag-or-variant>-<buildtype>_<abi>.apk.
4.5 Dependencies
| Dependency | Version | Used for |
|---|---|---|
androidx.core:core |
1.13.1 | Core compat |
androidx.appcompat:appcompat |
1.6.1 | Themed activities (in termux-shared) |
androidx.annotation:annotation |
1.9.0 | Nullability annotations |
androidx.drawerlayout:drawerlayout |
1.2.0 | Session navigation drawer |
androidx.preference:preference |
1.2.1 | Settings screens |
androidx.viewpager:viewpager |
1.0.0 | Extra-keys ⇄ text-input toolbar |
androidx.window:window |
1.1.0 | Window metrics |
com.google.android.material:material |
1.12.0 | Material UI components |
com.google.guava:guava |
24.1-jre | Collections (ImmutableBiMap), Joiner |
io.noties.markwon:* |
4.6.2 | Markdown rendering (help, reports) |
commons-io:commons-io |
2.5 | File IO (pinned ≤2.5 to keep java.nio.file.Path-free for Android < 8) |
org.lsposed.hiddenapibypass:hiddenapibypass |
6.1 | Bypass hidden-API restrictions via reflection |
com.termux:termux-am-library |
v2.0.0 | am command bridge |
junit:junit / org.robolectric:robolectric |
4.13.2 / 4.10 | Unit tests |
com.android.tools:desugar_jdk_libs |
1.1.5 | Core library desugaring |
Warning
commons-iois intentionally held at 2.5. Newer versions referencejava.nio.file.Path, which is missing on Android < 8 and causes runtimeNoClassDefFoundError. Do not bump it without dropping Android 5/6 support.
5. Android Components Reference
All components are declared in app/src/main/AndroidManifest.xml. The ${TERMUX_PACKAGE_NAME} placeholder resolves to com.termux.
| Component | Type | Exported | Notes |
|---|---|---|---|
.app.TermuxActivity |
Activity | ✅ | Launcher (MAIN/LAUNCHER, LEANBACK_LAUNCHER), singleTask, declares app shortcuts |
.HomeActivity (alias) |
Activity-alias | ✅ | IOT_LAUNCHER — auto-launch on boot for Android Things |
.app.activities.HelpActivity |
Activity | ❌ | In-app wiki viewer |
.app.activities.SettingsActivity |
Activity | ✅ | Settings root |
.shared.activities.ReportActivity |
Activity | ❌¹ | Markdown report/crash viewer |
.app.api.file.FileReceiverActivity |
Activity | ❌ | Internal file-receive handler (noHistory, own task affinity) |
.app.api.file.FileShareReceiverActivity (alias) |
Activity-alias | ✅ | Handles SEND for most MIME types |
.app.api.file.FileViewReceiverActivity (alias) |
Activity-alias | ✅ | Handles VIEW for most MIME types |
.filepicker.TermuxDocumentsProvider |
Provider | ✅ | com.termux.documents authority; MANAGE_DOCUMENTS-protected |
.app.TermuxOpenReceiver$ContentProvider |
Provider | ✅ | com.termux.files authority; RUN_COMMAND-permission protected |
.app.TermuxOpenReceiver |
Receiver | ❌ | Backs the termux-open utility |
.app.event.SystemEventReceiver |
Receiver | ❌ | BOOT_COMPLETED |
.shared.activities.ReportActivity$ReportActivityBroadcastReceiver |
Receiver | ❌ | Report actions |
.app.TermuxService |
Service | ❌ | Session/background-task owner; foreground service |
.app.RunCommandService |
Service | ✅ | ACTION_RUN_COMMAND; RUN_COMMAND-permission protected |
¹ ReportActivity is launched internally (documentLaunchMode=intoExisting).
6. Security Analysis
6.1 Threat model overview
Termux executes arbitrary user code by design, so its security boundary is what other apps and the system can do to Termux, and what Termux exposes to other apps. The main controls are the shared-user-ID signature requirement, the RUN_COMMAND permission, and the allow-external-apps opt-in.
6.2 Shared user ID & signature enforcement
The app and all plugins declare android:sharedUserId="com.termux". Android only co-locates apps under a shared UID if they are signed with the same key. This is what allows plugins to read Termux's files and properties — and why all APKs must come from one source. It also means a malicious APK cannot join the com.termux UID without the signing key.
6.3 The RUN_COMMAND surface
custom permission: com.termux.permission.RUN_COMMAND (protectionLevel: dangerous)
guarded service: .app.RunCommandService (exported, permission-protected)
guarded provider: .app.TermuxOpenReceiver$ContentProvider (com.termux.files)
runtime gate: allow-external-apps = true (in termux.properties; default false)
Two independent checks must both pass for an external app to run a command:
- The caller holds
com.termux.permission.RUN_COMMAND(a dangerous permission, surfaced to the user). allow-external-appsistrueintermux.properties.
RunCommandService additionally validates that the executable exists, is a regular file, and is readable/executable, canonicalizes paths, and validates working directories before forwarding to TermuxService. If allow-external-apps is violated, it force-shows a notification so the user is alerted that an app attempted to run a command — defending against a malicious or imported automation project acting without consent.
Caution
allow-external-appsis a security property.TermuxConstantsdocuments that it should only be modified from a properties file the user controls, and the path list is fixed so plugins cannot redirect it. Treat enabling it as granting code-execution to any app holding theRUN_COMMANDpermission.
6.4 The public test key
GitHub debug builds and the in-repo app/testkey_untrusted.jks use a publicly shared key (Owner CN=APK Signer, SHA-256 B6:DA:01:48:…:E5:E1). Anyone can build an "update" that installs over a GitHub build. The known release signing-certificate digests are encoded in TermuxConstants:
| Channel | SHA-256 digest (cert) |
|---|---|
| F-Droid | 228FB2CFE90831C1499EC3CCAF61E96E8E1CE70766B9474672CE427334D41C42 |
| GitHub | B6DA01480EEFD5FBF2CD3771B8D1021EC791304BDD6C4BF41D3FAABAD48EE5E1 |
| Google Play Store | 738F0A30A04D3C8A1BE304AF18D0779BCF3EA88FB60808F657A3521861C2EBF9 |
| Termux Devs | F7A038EB551F1BE8FDF388686B784ABAB4552A5D82DF423E3D8F1B5CBE1C69AE |
Caution
Only trust GitHub APKs downloaded directly from the official repository. Builds distributed elsewhere may be forged with the public test key.
6.5 Requested permissions
| Permission | Why Termux requests it |
|---|---|
INTERNET, ACCESS_NETWORK_STATE |
Networking for installed programs |
READ/WRITE_EXTERNAL_STORAGE, MANAGE_EXTERNAL_STORAGE |
termux-setup-storage; broad storage access on modern Android |
FOREGROUND_SERVICE |
Keep sessions alive via the persistent-notification service |
WAKE_LOCK |
termux-wake-lock for long-running tasks |
VIBRATE |
Terminal bell (vibrate mode) |
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS |
Prompt the user to whitelist Termux from battery optimization |
SYSTEM_ALERT_WINDOW |
Display-over-other-apps (used by Termux:Float) |
RECEIVE_BOOT_COMPLETED |
Boot scripts (Termux:Boot) |
REQUEST_INSTALL_PACKAGES |
Install APKs from the terminal |
READ_LOGS, DUMP, WRITE_SECURE_SETTINGS, PACKAGE_USAGE_STATS |
Diagnostics and mitigating phantom-process killing on Android 12+ (several are only grantable via ADB) |
SET_ALARM |
Scheduling helpers |
com.termux.permission.RUN_COMMAND (custom) |
Gate external command execution |
6.6 Hidden-API usage
termux-shared uses hiddenapibypass and reflection (ReflectionUtils, FeatureFlagUtils, PhantomProcessUtils) to read framework internals such as Android feature flags — needed to detect and help mitigate phantom-process killing. This is fragile across Android versions and OEM builds; treat reflection-backed paths as best-effort with graceful fallback (the code already returns UNKNOWN/null on failure).
6.7 Historical vulnerability
Versions before 0.118.0 had a world-readable vulnerability (disclosure). Users should run 0.118.0 or later. This is fixed in the documented codebase; it is noted here for audit history.
7. Configuration Mastery: Full termux.properties Reference
Loaded from ~/.termux/termux.properties (or ~/.config/termux/termux.properties). Defined in TermuxPropertyConstants. Reload at runtime via the ACTION_RELOAD_STYLE broadcast (triggered by the Style menu action).
7.1 Boolean properties
| Key | Default | Effect |
|---|---|---|
allow-external-apps |
false |
Permit external apps to run commands via RUN_COMMAND |
disable-file-share-receiver |
false |
Remove Termux from the Android Share menu |
disable-file-view-receiver |
false |
Remove Termux from the Open with menu |
disable-hardware-keyboard-shortcuts |
false |
Disable all hardware-keyboard session shortcuts |
disable-terminal-session-change-toast |
false |
Suppress the session-switch toast |
enforce-char-based-input |
false |
Char-based IME workaround (Samsung et al.) |
extra-keys-text-all-caps |
true |
Uppercase extra-key labels |
hide-soft-keyboard-on-startup |
false |
Start with keyboard hidden |
run-termux-am-socket-server |
true |
Run the local am socket server at startup |
terminal-onclick-url-open |
false |
Open URLs on single tap |
ctrl-space-workaround |
false |
Fix Ctrl+Space on some ROMs |
fullscreen |
false |
Fullscreen terminal |
use-fullscreen-workaround |
false |
Fullscreen layout workaround |
use-black-ui |
(deprecated) | Legacy black UI toggle |
7.2 Integer / float properties (with valid ranges)
| Key | Range | Default | Effect |
|---|---|---|---|
bell-character |
vibrate / beep / ignore |
vibrate |
Bell behavior |
terminal-cursor-blink-rate |
0 or engine min–max |
0 |
Blink interval (ms); 0 = no blink |
terminal-cursor-style |
block / underline / bar |
block |
Cursor shape |
terminal-margin-horizontal |
0–100 |
3 |
Left/right margin (dp) |
terminal-margin-vertical |
0–100 |
0 |
Top/bottom margin (dp) |
terminal-transcript-rows |
engine min–max | engine default | Scrollback rows |
terminal-toolbar-height |
0.4–3 |
1 |
Extra-keys toolbar height scale |
delete-tmpdir-files-older-than-x-days-on-exit |
-1–100000 |
3 |
Clean $TMPDIR on exit (-1 none, 0 all) |
7.3 String / behavior properties
| Key | Values | Default | Effect |
|---|---|---|---|
back-key |
back / escape |
back |
Back button behavior |
volume-keys |
virtual / volume |
virtual |
Volume-Down as modifier vs. normal volume |
soft-keyboard-toggle-behaviour |
show/hide / enable/disable |
show/hide |
Keyboard-toggle action |
night-mode |
true / false / system |
system |
Theme |
default-working-directory |
absolute path | $HOME |
New-session CWD |
extra-keys |
matrix (see UG) | two-row default | Extra-keys layout |
extra-keys-style |
default, arrows-only, … |
default |
Key glyph style |
7.4 Session shortcut properties
| Key | Action |
|---|---|
shortcut.create-session |
New session |
shortcut.next-session |
Next session |
shortcut.previous-session |
Previous session |
shortcut.rename-session |
Rename session |
8. Intent API Reference
8.1 RUN_COMMAND (public, plugin-facing)
Target: service com.termux/.app.RunCommandService, action com.termux.RUN_COMMAND. Requires the RUN_COMMAND permission and allow-external-apps = true.
| Extra | Type | Meaning |
|---|---|---|
com.termux.RUN_COMMAND_PATH |
String | Absolute executable path (required) |
com.termux.RUN_COMMAND_ARGUMENTS |
String[] | Arguments |
com.termux.RUN_COMMAND_STDIN |
String | Standard input |
com.termux.RUN_COMMAND_WORKDIR |
String | Working directory |
com.termux.RUN_COMMAND_BACKGROUND |
boolean | Background (app-shell) vs. foreground (terminal-session) |
com.termux.RUN_COMMAND_RUNNER |
String | Explicit runner (terminal-session / app-shell); overrides BACKGROUND |
com.termux.RUN_COMMAND_SESSION_ACTION |
String | Session/activity action for foreground commands |
com.termux.RUN_COMMAND_COMMAND_LABEL / _DESCRIPTION / _HELP |
String | Metadata for notifications/reports |
com.termux.RUN_COMMAND_BACKGROUND_CUSTOM_LOG_LEVEL |
String | Per-command log level for background runs |
…RUN_COMMAND_REPLACE_COMMA_ALTERNATIVE_CHARS_IN_ARGUMENTS / …_COMMA_ALTERNATIVE_CHARS_IN_ARGUMENTS |
boolean / String | Comma-escaping for am-delivered arguments |
…RUN_COMMAND_PENDING_INTENT |
Parcelable | Pending intent to receive results |
…RUN_COMMAND_RESULT_DIRECTORY (+ _SINGLE_FILE, _FILE_BASENAME, _FILE_OUTPUT_FORMAT, _FILE_ERROR_FORMAT, _FILES_SUFFIX) |
String/boolean | Write results to files |
Reference: RUN_COMMAND Intent wiki.
8.2 TERMUX_SERVICE (internal execution contract)
RunCommandService forwards validated commands to TermuxService as action com.termux.service_execute with a com.termux.file-scheme URI and com.termux.execute.* extras (arguments, workdir, background, runner, session_action, result extras). The session_action integer selects whether to open/switch the session and whether to bring the activity forward.
8.3 TERMUX_ACTIVITY broadcasts
| Action | Effect |
|---|---|
com.termux.app.reload_style |
Re-read termux.properties and restyle (optionally recreate the activity) |
| (crash-notify action) | Show a crash notification from the crash-log file |
| (request-permissions action) | Trigger the storage-permission request flow |
9. Operations
Termux has no server-side deployment — it is a client app installed on devices. "Operations" here means device-side lifecycle and fleet/integration management.
9.1 Install / update / rollback
# Install or update (single source!)
adb install -r termux-app_apt-android-7-release_universal.apk
Performing Streamed Install
Success
- Updates are normal APK updates from the chosen source. F-Droid lags GitHub by days.
- Rollback requires uninstalling (data is not downgrade-compatible across major changes); back up first.
9.2 Keeping Termux alive (Android 12+)
The single biggest operational issue is the OS killing background processes. Mitigations, in order of effectiveness:
- [ ] Disable battery optimization for Termux (Android Settings → Apps → Termux → Battery).
- [ ] Acquire a wake-lock for long jobs (
termux-wake-lockor context-menu Keep screen on). - [ ] Disable phantom-process and excessive-CPU killing (ADB / Developer Options; see issue #2366).
- [ ] Keep critical work in the foreground session.
9.3 Logging & diagnostics
- Set log level: Settings → Termux → Debugging → Log Level (
Off/Normal/Debug/Verbose). - Capture logs from the device:
logcat -d > logcat.txt, or over ADB from a PC. - Generate a full report: context menu → More → Report Issue.
Warning
Verbose logging may write private data to
logcatand slows execution. Revert toNormalafter debugging. Set log level for both the plugin and the main app when diagnosing plugin issues.
9.4 Backups
Back up ~/ (home) and $PREFIX before uninstalling or switching sources. See Backing up Termux.
10. Forking & Repackaging
TermuxConstants is the canonical place to change identity. To fork under a new package name you must change, at minimum:
TERMUX_PACKAGE_NAMEinTermuxConstants.applicationIdand themanifestPlaceholders(TERMUX_PACKAGE_NAME,*_APP_NAME) inapp/build.gradle.- The
ENTITYvalues instrings.xmloftermux-appandtermux-shared. shortcut.xmland*_preferences.xml(dynamic variables are not supported there).- Rebuild the bootstrap archives for the new
$PREFIX(binaries hard-code the prefix path) — see Building packages.
Important
Not all plugins use
TermuxConstants; some still hard-codecom.termuxand must be patched manually when forking. Contributions must reference shared constants fromtermux-sharedrather than hard-coding paths — PRs with hard-coded values are rejected.
11. Code Quality & Conventions
- Centralized constants — every path, package name, intent action, and extra lives in
TermuxConstants/TermuxPropertyConstantswith a versioned changelog header. This eliminates hard-coded strings across the app and plugins. - Structured errors — the
Error/Errnotypes carry a code, type, message, and throwable list, and render to log/Markdown form, instead of throwing bare exceptions. - Bidirectional value maps — properties with enumerated values use Guava
ImmutableBiMapto map user-facing strings to internal int/string values (and back). - Reusable engine/view —
terminal-emulatorandterminal-vieware kept free of Termux specifics and published independently to JitPack. - Conventional Commits — commit messages must follow Conventional Commits with capitalized types (
Added,Changed,Deprecated,Removed,Fixed,Security) so changelogs are generated automatically.versionNamemust be valid SemVer 2.0.0 (validated inbuild.gradle).
Testing strategy
terminal-emulatorhas thorough JUnit coverage of the emulator (CSI/OSC/DCS, modes, cursor, resize, history, Unicode).- The app uses Robolectric for unit tests (
TermuxActivityTest,FileReceiverActivityTest). termux-sharedincludes instrumented tests (ExampleInstrumentedTest) and aFileUtilsTestsharness.
Note
Test density is highest in the engine and thinnest in the app/UI layer — appropriate, since the engine encodes the most complex, regression-prone logic. New escape-sequence or buffer behavior should always land with tests.
12. Potential Improvements
Observations from the source, for maintainers and contributors:
- Android 12+ phantom-process killing remains the dominant stability complaint (issues #5032, #5086, #3059). The app already detects feature flags via reflection; a guided in-app mitigation wizard (where permissions allow) would cut support load.
targetSdkVersion 28is well behind the platform. Raising it unlocks modern APIs but collides with the legacy-storage and exec-from-data-dir behaviors Termux depends on; any bump needs careful validation against scoped storage and W^X exec restrictions.commons-iopinned at 2.5 for Android <8 compatibility — revisit if/when the minimum SDK rises.- Paste-of-control-characters crash (#5119) is a robustness gap in input sanitization worth hardening in
TerminalView/KeyHandler. - Hidden-API reflection is inherently brittle across OEM ROMs; continue to guard every reflective call with the existing
UNKNOWN/nullfallbacks and log clearly when the platform shape changes. - Maintainer capacity — the README explicitly calls for app maintainers; triage automation around the high-volume, low-signal issue tracker would help.
13. Quick Reference
Key paths
| Item | Path |
|---|---|
$PREFIX |
/data/data/com.termux/files/usr |
$HOME |
/data/data/com.termux/files/home |
$TMPDIR |
/data/data/com.termux/files/usr/tmp |
| Properties | ~/.termux/termux.properties |
| Storage links | ~/storage/ |
Build commands
./gradlew assembleDebug # build debug APKs (signed with the public test key)
./gradlew assembleRelease # build release APKs (minified)
./gradlew test # run unit tests
./gradlew :app:versionName # print the version name
Key constants (in termux-shared)
| Constant class | Defines |
|---|---|
TermuxConstants |
Package names, paths, intent actions & extras, signing digests, URLs |
TermuxPropertyConstants |
Every termux.properties key, default, and value map |
TermuxPreferenceConstants |
SharedPreferences keys |
ExtraKeysConstants |
Extra-key names, aliases, and display glyph maps |
Plugin packages
| Plugin | Package |
|---|---|
| Termux:API | com.termux.api |
| Termux:Boot | com.termux.boot |
| Termux:Float | com.termux.window |
| Termux:Styling | com.termux.styling |
| Termux:Tasker | com.termux.tasker |
| Termux:Widget | com.termux.widget |