# Termux Admin & Architecture Guide

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](https://github.com/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](https://github.com/termux/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

```text
                    ┌──────────────────────────┐
                    │          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 `TerminalRow`s. |
| `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`)

```text
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:**

- `TermuxActivity` is a thin UI shell. The **`TermuxService` is 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 `BroadcastReceiver` inside the activity listens for `ACTION_RELOAD_STYLE` (re-read properties / restyle), `ACTION_NOTIFY_APP_CRASH`, and `ACTION_REQUEST_PERMISSIONS`.

### 2.6 Bootstrap installation flow (`TermuxInstaller`)

On first launch (when `$PREFIX` is missing or empty), the app installs the base system:

1. Verify the app runs as the **primary user** and that the files directory is accessible (fail with a clear dialog otherwise).
2. Show an "Installing…" progress dialog.
3. Load the bootstrap zip **from an embedded native library** — `System.loadLibrary("termux-bootstrap")` then `getZip()` (JNI). The zip is compiled into the APK at build time (see [§4.3](#43-bootstrap-archives)).
4. Extract entries into a **staging** directory `…/files/usr-staging`:
   - `SYMLINKS.txt` entries (format `target←linkpath`) are collected and recreated as symlinks.
   - Files under `bin/`, `libexec/`, and apt helper/method paths get mode `0700`.
5. Atomically `rename()` staging → `$PREFIX` (so a crash mid-extract never leaves a half-written prefix).
6. 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.properties` is read from the **first** of `~/.termux/termux.properties` then `~/.config/termux/termux.properties`. The float plugin uses `termux.float.properties` in 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

```groovy
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-v8a` plus a universal APK, controlled by `TERMUX_SPLIT_APKS_FOR_*` env vars. F-Droid ships universal only (it [does not support](https://github.com/termux/termux-app/pull/1904) split APKs).
- **Debug** builds are signed with the in-repo `app/testkey_untrusted.jks` (see [§6.4](#64-the-public-test-key)).
- **Release** builds enable `minifyEnabled` (ProGuard) with `shrinkResources false` for 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-io` is intentionally held at **2.5**. Newer versions reference `java.nio.file.Path`, which is missing on Android < 8 and causes runtime `NoClassDefFoundError`. 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

```text
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:

1. The caller holds `com.termux.permission.RUN_COMMAND` (a *dangerous* permission, surfaced to the user).
2. `allow-external-apps` is `true` in `termux.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-apps` is a **security property**. `TermuxConstants` documents 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 the `RUN_COMMAND` permission.

### 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](https://termux.github.io/general/2022/02/15/termux-apps-vulnerability-disclosures.html)). 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](https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent).

### 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

```bash
# Install or update (single source!)
adb install -r termux-app_apt-android-7-release_universal.apk
```

```text
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-lock` or context-menu **Keep screen on**).
- [ ] Disable phantom-process and excessive-CPU killing (ADB / Developer Options; see [issue #2366](https://github.com/termux/termux-app/issues/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 `logcat` and slows execution. Revert to `Normal` after 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](https://wiki.termux.com/wiki/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_NAME` in `TermuxConstants`.
- `applicationId` and the `manifestPlaceholders` (`TERMUX_PACKAGE_NAME`, `*_APP_NAME`) in `app/build.gradle`.
- The `ENTITY` values in `strings.xml` of `termux-app` and `termux-shared`.
- `shortcut.xml` and `*_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](https://github.com/termux/termux-packages/wiki/Building-packages).

> [!IMPORTANT]
> Not all plugins use `TermuxConstants`; some still hard-code `com.termux` and must be patched manually when forking. Contributions must reference shared constants from `termux-shared` rather 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`/`TermuxPropertyConstants` with a versioned changelog header. This eliminates hard-coded strings across the app and plugins.
- **Structured errors** — the `Error`/`Errno` types 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 `ImmutableBiMap` to map user-facing strings to internal int/string values (and back).
- **Reusable engine/view** — `terminal-emulator` and `terminal-view` are kept free of Termux specifics and published independently to JitPack.
- **Conventional Commits** — commit messages must follow [Conventional Commits](https://www.conventionalcommits.org) with capitalized types (`Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, `Security`) so changelogs are generated automatically. `versionName` must be valid SemVer 2.0.0 (validated in `build.gradle`).

### Testing strategy

- `terminal-emulator` has thorough JUnit coverage of the emulator (CSI/OSC/DCS, modes, cursor, resize, history, Unicode).
- The app uses Robolectric for unit tests (`TermuxActivityTest`, `FileReceiverActivityTest`).
- `termux-shared` includes instrumented tests (`ExampleInstrumentedTest`) and a `FileUtilsTests` harness.

> [!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](https://github.com/termux/termux-app/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 28`** is 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-io` pinned at 2.5** for Android <8 compatibility — revisit if/when the minimum SDK rises.
- **Paste-of-control-characters crash** ([#5119](https://github.com/termux/termux-app/issues/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`/`null` fallbacks 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

```bash
./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` |

### Useful links

- App repo: <https://github.com/termux/termux-app>
- Packages: <https://github.com/termux/termux-packages>
- Wiki: <https://wiki.termux.com/wiki/>
- RUN_COMMAND: <https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent>
- Issues: <https://github.com/termux/termux-app/issues>

---

_Generated June 2026 from termux/termux-app at 30ebb2d. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
