Tech Guides

TERMUX

Linux Forged in Android Steel

5000+ Packages
ARM64 Native
0 Root Required
01

Quick Reference

Essential Termux commands at a glance. Pin this panel to your workbench.

Package Management

Install Package
pkg install <name>
Install a package and its dependencies
Update All
pkg upgrade
Update package index and upgrade all installed packages
Search
pkg search <query>
Search available packages by name or description
List Installed
pkg list-installed
Show all currently installed packages
APT Update
apt update && apt upgrade
Direct apt usage (pkg wraps apt)
Remove Package
pkg uninstall <name>
Uninstall a package and clean up

Filesystem & Storage

Home Directory
echo $HOME
/data/data/com.termux/files/home
Prefix Path
echo $PREFIX
/data/data/com.termux/files/usr
Temp Directory
echo $TMPDIR
/data/data/com.termux/files/usr/tmp
Enable Storage
termux-setup-storage
Grant storage permission, create ~/storage symlinks

Services & Power

Start SSH
sshd
Start SSH daemon (port 8022 by default)
Wake Lock
termux-wake-lock
Prevent device from sleeping (acquire wakelock)
Wake Unlock
termux-wake-unlock
Release wakelock, allow device to sleep

System Info

Termux Info
termux-info
Dump system info (Android version, ABI, paths)
Android Version
getprop ro.build.version.release
Query Android system properties
CPU Architecture
uname -m
Show machine hardware (aarch64, armv7l, etc.)

Termux:API Highlights

Battery Status
termux-battery-status
JSON output: percentage, status, temperature
Clipboard Get
termux-clipboard-get
Read current system clipboard contents
Clipboard Set
echo "text" | termux-clipboard-set
Write to system clipboard from stdin
Notification
termux-notification -t "Title" -c "Body"
Post an Android notification from the terminal
02

What Is Termux

Termux is an Android terminal emulator coupled with a real Linux environment. It is not a virtual machine, not a container, and not an emulation layer. It runs native Linux binaries directly on Android's Linux kernel.

Architecture

Android itself runs on the Linux kernel. Termux exploits this by providing a user-space Linux environment that talks directly to the same kernel powering your phone. When you run python3 or gcc in Termux, those are real ARM64 ELF binaries executing natively — no translation, no overhead.

Key Insight: Termux is closer to a custom Linux distribution than to any kind of virtualization. It ships its own package manager, its own filesystem hierarchy, and its own set of compiled packages — all running as a regular Android app.
Aspect Termux VM / Container
Kernel Android's Linux kernel (shared) Separate kernel or isolated namespace
Binary Execution Native ARM64 ELF May involve translation layer
Root Required No Often yes
Performance Native speed Near-native to slower
Filesystem App sandbox ($PREFIX) Full FHS or overlay

Bionic vs. glibc

Android does not use the standard GNU C Library (glibc) that desktop Linux uses. Instead, it uses Bionic, Google's custom C library. This means:

  • You cannot just copy a binary from an Ubuntu server and run it in Termux
  • Every package in Termux's repository has been cross-compiled specifically to link against Bionic
  • Some glibc-specific APIs are missing or behave differently
  • Packages are patched at build time to handle these differences
Common Pitfall: Downloading a prebuilt Linux binary (e.g., from GitHub Releases) and expecting it to run in Termux. It will fail with CANNOT LINK EXECUTABLE because it was linked against glibc, not Bionic. Always use pkg install or compile from source within Termux.

The $PREFIX Convention

Standard Linux follows the Filesystem Hierarchy Standard (FHS) with paths like /usr/bin, /etc, /var. Termux cannot use these paths because it runs as an unprivileged Android app with no access to the root filesystem. Instead, everything lives under $PREFIX:

Standard FHS Termux Equivalent
/usr $PREFIX (/data/data/com.termux/files/usr)
/usr/bin $PREFIX/bin
/etc $PREFIX/etc
/var $PREFIX/var
/tmp $PREFIX/tmp (also $TMPDIR)
/home /data/data/com.termux/files/home

All Termux packages are patched at build time to replace hardcoded paths like /usr/bin/python3 with $PREFIX/bin/python3. This is done automatically by the Termux build infrastructure — the termux-packages repository handles this patching for every package.

User-Space Only

Termux operates entirely in user space. There is no sudo, no su, and no ability to modify system files — unless your device is rooted. This means:

  • No binding to ports below 1024 (use 8080 instead of 80, 8022 instead of 22)
  • No systemd or init — use termux-services (sv/runit) instead
  • No /proc write access or kernel module loading
  • No creating users or groups — everything runs as the Termux app UID
  • No chroot without root (but proot works as a userspace alternative)
The Upside: Because Termux needs no root and runs as a regular app, it's safe, simple to install, and does not void warranties or require unlocking the bootloader. You get a genuine Linux development environment with zero risk to your device.
03

Installation & Setup

Getting Termux installed correctly is the most important step. The wrong source will leave you with a broken, outdated installation.

Where to Install From

Do Not Use Google Play: The Play Store version of Termux has been deprecated since November 2020. It is stuck on an old version, cannot update packages, and will not receive fixes. Google Play's target API requirements made it impossible to maintain Termux there.

There are two recommended sources:

F-Droid Recommended
The primary distribution channel. F-Droid builds Termux from source and signs it with its own key. Install the F-Droid app first, then search for Termux.
GitHub Releases
Download APKs directly from github.com/termux/termux-app/releases. Signed with the Termux developer key. Useful if you don't want the F-Droid client.
Cannot Upgrade In-Place: You cannot upgrade from the Play Store version to the F-Droid version without uninstalling first. They use different signing keys, and Android prevents installing over a differently-signed APK. Back up your $HOME before uninstalling.

First Boot Steps

After installing and opening Termux for the first time:

# 1. Update the package index and upgrade base packages
pkg update && pkg upgrade

# 2. Grant storage access (creates ~/storage symlinks)
termux-setup-storage

# 3. Install essential tools
pkg install git curl wget openssh nano

# 4. Optional: install a better shell
pkg install zsh
chsh -s zsh

The pkg update command will prompt you to choose a repository mirror. Pick one geographically close to you for best speeds. You can change mirrors later by editing $PREFIX/etc/apt/sources.list or running termux-change-repo.

Storage Access

Running termux-setup-storage does two things:

  1. Triggers Android's storage permission dialog
  2. Creates symlinks in ~/storage/ pointing to shared storage locations
Symlink Points To
~/storage/shared Internal storage root (/storage/emulated/0)
~/storage/downloads Downloads folder
~/storage/dcim Camera photos
~/storage/music Music directory
~/storage/pictures Pictures directory
~/storage/movies Movies directory
~/storage/external-1 SD card (if present)
Android 11+ Note: Scoped Storage restrictions on Android 11 and later limit what Termux can access. You may encounter Permission denied errors when trying to access files created by other apps. The termux-setup-storage command grants broad access, but some paths may still be restricted depending on your Android version and manufacturer.

termux.properties Configuration

Customize Termux behavior by editing ~/.termux/termux.properties. Create the file if it doesn't exist, then run termux-reload-settings to apply changes.

# ~/.termux/termux.properties

# Extra keys row — the toolbar above the keyboard
# This is the most important setting for usability
extra-keys = [ \
  ['ESC','/','-','HOME','UP','END','PGUP'], \
  ['TAB','CTRL','ALT','LEFT','DOWN','RIGHT','PGDN'] \
]

# Alternative: single-row with common keys
# extra-keys = [['ESC','TAB','CTRL','ALT','-','DOWN','UP']]

# Use black keyboard (matches dark theme)
use-black-ui = true

# Bell behavior: vibrate, beep, or ignore
bell-character = vibrate

# Terminal cursor style: block, underline, or bar
terminal-cursor-style = bar

# Allow external apps to run termux commands
allow-external-apps = true

# Fullscreen mode
fullscreen = false

# Volume keys as special keys
# volume-keys = volume  (default: virtual)
Extra Keys: The extra keys row is essential for productive Termux use. Without it, typing characters like Ctrl, Tab, Esc, and arrow keys requires awkward volume-button combos. Customize the layout to match your workflow.

Shell Configuration

Termux ships with bash by default. Your dotfiles go in the standard locations:

# Bash config
~/.bashrc        # Interactive shell config
~/.bash_profile  # Login shell config
~/.profile       # POSIX login profile

# If using Zsh
~/.zshrc
~/.zprofile

# Useful .bashrc additions for Termux
export EDITOR=nano
alias ll='ls -la'
alias update='pkg update && pkg upgrade'

# Fix for some programs that expect /tmp
export TMPDIR=$PREFIX/tmp

Styling the Terminal

Customize colors and font via ~/.termux/:

# Install premade themes and fonts
pkg install termux-style

# Or manually:
# Place a colors.properties file
~/.termux/colors.properties

# Place a font file (TTF or OTF)
~/.termux/font.ttf

# Apply changes
termux-reload-settings
04

Package Management

Termux ships its own package manager built on top of apt. The pkg command is a convenience wrapper that automatically runs apt update before installing, so you always get the latest package index.

Core Commands

Install
pkg install <name>
Install a package. Automatically runs apt update first.
Upgrade All
pkg upgrade
Update the package index and upgrade every installed package to the latest version.
Search
pkg search <query>
Search available packages by name or description.
List Installed
pkg list-installed
Show all currently installed packages and their versions.
Uninstall
pkg uninstall <name>
Remove a package and clean up its dependencies.
Show Info
pkg show <name>
Display detailed info about a package (version, size, dependencies).
List All Available
pkg list-all
List every package available in the configured repositories.
Reinstall
pkg reinstall <name>
Reinstall a package (useful for fixing corrupted installs).
pkg vs. apt: You can use apt directly if you prefer — pkg is just a shell wrapper. The only difference is that pkg install calls apt update automatically before installing, while raw apt install does not.

Why Not Ubuntu Repos?

You cannot add Ubuntu, Debian, or any standard Linux repository to Termux. Termux packages are cross-compiled specifically for the Android/Bionic environment. Standard Linux packages are linked against glibc and assume FHS paths like /usr/bin — both of which are incompatible with Termux.

The Termux package repository currently contains 1000+ packages, all patched and compiled to work within the Termux environment. If a package you need isn't available, you can try compiling it from source within Termux, or use proot-distro to run a full glibc-based distro.

Additional Repositories

Beyond the main repository, Termux offers several additional repos for specialized packages:

Repository Install Command Contents
x11-repo pkg install x11-repo GUI applications via X11 (XFCE, VLC, Firefox, etc.)
root-repo pkg install root-repo Tools that require root access (aircrack-ng, tcpdump, etc.)
tur-repo pkg install tur-repo Termux User Repository — community-maintained extras (code-server, etc.)
Deprecated Repos: The old unstable-repo, game-packages, and science-packages repositories have been merged into the main Termux repository. If you see references to them in older guides, ignore them — their packages are now available via the standard pkg install.

Mirror Selection

If package downloads are slow or failing, switch to a different mirror:

# Interactive mirror selector (recommended)
termux-change-repo

# Or manually edit the sources list
nano $PREFIX/etc/apt/sources.list

The termux-change-repo command provides a dialog-based interface to select mirrors for each repository. Pick the mirror geographically closest to you for best performance.

Commonly Needed Packages

Package Install Command Notes
Build Essentials pkg install build-essential Clang, make, pkg-config, and headers for compiling from source
Python pkg install python Python 3 with pip. Pure-Python packages work; C extensions may need build-essential
Node.js pkg install nodejs Node + npm. Most npm packages work out of the box
Rust pkg install rust Rustc + Cargo, compiles natively for aarch64-linux-android
Git pkg install git Full Git with SSH and HTTPS support
OpenSSH pkg install openssh SSH client and server (sshd on port 8022)
tmux pkg install tmux Terminal multiplexer — essential for long-running tasks
Neovim pkg install neovim Modern Vim. Classic vim also available
wget / curl pkg install wget curl HTTP clients for downloading files
jq pkg install jq Command-line JSON processor
ripgrep pkg install ripgrep Fast recursive search (rg). Better than grep for codebases
fd pkg install fd Fast, user-friendly find alternative
05

Filesystem & Storage

Termux cannot use standard Linux paths. Everything lives inside the app's private data directory, with its own parallel filesystem hierarchy. Understanding these paths is critical — getting them wrong breaks tools, scripts, and builds.

Key Environment Variables

Variable Value Purpose
$HOME /data/data/com.termux/files/home User home directory. Your dotfiles, projects, and personal files live here.
$PREFIX /data/data/com.termux/files/usr Equivalent to /usr. All installed packages, binaries, and libraries.
$TMPDIR $PREFIX/tmp Temporary files. This is not /tmp.
$TMPDIR Is Critical: Many tools (including Claude Code, pip, and various build systems) use $TMPDIR or default to /tmp for scratch files. In Termux, /tmp does not exist or is not writable. Tools that hardcode /tmp will fail. Always ensure $TMPDIR is set and that scripts use it instead of /tmp.

FHS Path Mapping

A complete reference of how standard Linux paths map into Termux:

Standard Linux Termux Notes
/usr/bin $PREFIX/bin Where all installed binaries live
/usr/lib $PREFIX/lib Shared libraries (.so files)
/usr/include $PREFIX/include C/C++ header files
/usr/share $PREFIX/share Man pages, docs, data files
/etc $PREFIX/etc Configuration files (sshd_config, profile, etc.)
/var $PREFIX/var Variable data (logs, databases, caches)
/tmp $PREFIX/tmp Temporary files — use $TMPDIR in scripts
/bin /system/bin Android system binaries — NOT Termux tools
/home/user $HOME Single user, no /home hierarchy
Beware /bin: In Termux, /bin points to /system/bin, which contains Android's minimal system tools (toybox, sh, linker). These are not Termux binaries. If a script references /bin/sh, it will use Android's stripped-down shell, not Termux's bash or zsh.

Shebangs

Because binaries do not live at standard paths, hardcoded shebangs will break:

# WRONG — this path does not exist in Termux
#!/usr/bin/python3

# WRONG — /bin is Android's system bin, not Termux
#!/bin/bash

# CORRECT — env finds the right binary via $PATH
#!/usr/bin/env python3

# CORRECT — env finds bash in $PREFIX/bin
#!/usr/bin/env bash
Why env works: The /usr/bin/env path is actually a special symlink that Termux creates pointing to $PREFIX/bin/env. This is one of the few standard paths that Termux patches to work, specifically to support shebangs.

Shared Storage

After running termux-setup-storage, the ~/storage/ directory contains symlinks to Android's shared storage areas:

Symlink Android Location
~/storage/shared Internal storage root (/sdcard)
~/storage/downloads Downloads folder
~/storage/dcim Camera photos and videos
~/storage/music Music files
~/storage/pictures Pictures folder
~/storage/movies Movies folder
~/storage/external-1 SD card (if present)
Shared Storage Limitations: Android's shared storage uses FAT-like semantics. You cannot create symlinks, hardlinks, change file permissions with chmod, or use Unix-specific file operations on shared storage. This makes it unsuitable for development work — keep all code, git repos, and project files in $HOME, not in ~/storage/.

Where Things Live

# Your config files
$PREFIX/etc/              # System configs (sshd_config, profile.d/, etc.)
$HOME/.bashrc             # Bash user config
$HOME/.termux/            # Termux-specific config (colors, font, keys)

# Installed binaries
$PREFIX/bin/              # All executables (python, node, git, etc.)
which python3             # Shows $PREFIX/bin/python3

# Libraries
$PREFIX/lib/              # Shared objects (.so)
$PREFIX/lib/python3.*/    # Python standard library

# Package databases
$PREFIX/var/lib/dpkg/     # dpkg/apt package database
$PREFIX/var/cache/apt/    # Downloaded .deb files
06

Development Environments

Termux supports a surprisingly complete set of programming languages and development tools. Here is what works, what needs workarounds, and what flatly refuses to cooperate.

Node.js

# Install Node.js and npm
pkg install nodejs

# Verify installation
node --version
npm --version

# Initialize a project
mkdir my-project && cd my-project
npm init -y

# Install packages (most work fine)
npm install express
npm install typescript -g

Node.js works well on Termux. The npm ecosystem is largely compatible — pure-JavaScript packages install without issues. However, native modules that use node-gyp can fail because node-gyp expects standard Linux paths and GCC, while Termux uses Clang and non-standard paths.

node-pty Is Broken: The node-pty package (used by many terminal-related tools) does not compile on Termux due to PTY handling differences in the Android kernel. This has cascading effects on tools that depend on it. The full story is in Section 07: The PTY Story.

Python

# Install Python 3 with pip
pkg install python

# Verify
python3 --version
pip --version

# Create a virtual environment
python3 -m venv myenv
source myenv/bin/activate

# Pure-Python packages — no issues
pip install flask requests beautifulsoup4 click

# Scientific packages — install via pkg, not pip
pkg install python-numpy
pkg install python-scipy
pkg install python-pillow

Python works well for most use cases. Pure-Python packages install normally via pip. Packages with C extensions (NumPy, SciPy, Pillow) should be installed via pkg when available, as the Termux-packaged versions are pre-compiled for Bionic. Building C extensions from source with pip may fail due to missing headers or Bionic incompatibilities.

Rust

# Install Rust toolchain
pkg install rust

# Verify
rustc --version
cargo --version

# Create and build a project
cargo new hello-termux
cd hello-termux
cargo build
cargo run

# The target triple in Termux
rustc --print target-list | grep android
# aarch64-linux-android

Rust compiles natively for aarch64-linux-android. Cargo works, crate downloads work, and most crates build without issues. Rust is particularly important in the Termux ecosystem because it's the language used to build native PTY handling solutions — a critical topic covered in Section 07.

Go

# Install Go
pkg install golang

# Verify
go version

# Create a module
mkdir my-go-app && cd my-go-app
go mod init my-go-app

# Build and run
go build -o app main.go
./app

# Cross-compilation still works
GOOS=linux GOARCH=amd64 go build -o app-x86 main.go

Go works well on Termux. Modules, vendoring, and the standard library all function as expected. Cross-compilation to other targets is fully supported.

C / C++

# Install the compiler toolchain
pkg install clang make cmake

# Compile a simple program
echo '#include <stdio.h>
int main() { printf("Hello from Termux\\n"); return 0; }' > hello.c
clang hello.c -o hello
./hello

# Use cmake for larger projects
mkdir build && cd build
cmake ..
make

# Additional build tools
pkg install ninja autoconf automake libtool

Clang is the compiler in Termux, not GCC. GCC is not available. Most C/C++ projects that support Clang will compile fine. Build systems like CMake, Ninja, and Autotools are all available.

Ruby & PHP

# Ruby
pkg install ruby
ruby --version
gem install bundler

# PHP
pkg install php
php --version

# PHP with common extensions
pkg install php-fpm php-pgsql

Both Ruby and PHP are available and functional. gem install works for most gems. PHP includes common extensions with additional ones available via pkg.

What Does NOT Work

Tool / Technology Why It Fails Alternative
Docker Requires kernel namespaces, cgroups, and root access proot-distro for isolated Linux environments
systemd Requires PID 1, cgroups, and root termux-services (sv/runit)
glibc binaries Termux uses Bionic, not glibc Compile from source or use proot-distro
node-pty PTY implementation incompatible with Android Rust-based PTY crate (see Section 07)
Snap / Flatpak Require systemd and namespaces Use pkg or compile from source
Kernel modules No root, no /lib/modules access None — kernel-level features unavailable

proot-distro: The Escape Hatch

Need a Full Linux Distro? When Termux's Bionic-based packages aren't enough, proot-distro lets you run full glibc-based distributions (Ubuntu, Debian, Fedora, Alpine, Arch, etc.) inside Termux using proot — a user-space chroot replacement that needs no root.
# Install proot-distro
pkg install proot-distro

# List available distros
proot-distro list

# Install Ubuntu
proot-distro install ubuntu

# Launch into Ubuntu
proot-distro login ubuntu

# Now you're in a full Ubuntu environment:
apt install docker.io   # Still won't work (no kernel support)
apt install gcc         # GCC works here (glibc-based)
apt install python3     # Standard Ubuntu Python

Inside a proot-distro environment, you get a standard FHS filesystem, glibc, and the distribution's full package repository. Performance is slightly reduced due to proot's syscall translation, but for most development tasks the overhead is negligible. Note that kernel-level features (Docker, systemd, etc.) still won't work even inside proot.

07

The PTY Story

This is the story of how pseudoterminals broke on Android, how Microsoft's node-pty became a long-standing blocker, and how a Rust crate cracked the problem open — enabling real web terminals on Android for the first time.

What Is a PTY?

A pseudoterminal (PTY) is a kernel mechanism that lets a program act as a terminal. It is the fundamental abstraction behind every terminal emulator, every SSH session, every tmux pane, and every screen session on any Unix system.

A PTY is a pair of virtual file descriptors:

  • Master side — held by the controlling program (the terminal emulator, SSH daemon, or multiplexer). It reads what the child process writes and sends keystrokes to the child.
  • Slave side — presented to the child process (the shell, or whatever runs inside the terminal). From the child's perspective, the slave looks exactly like a real hardware terminal.
# The kernel PTY architecture

  Terminal Emulator (xterm, Alacritty, Termux)
         │
         │  reads/writes
         ▼
    ┌──────────┐
    │  Master   │  <── PTY pair (kernel-managed)
    │  (ptmx)   │
    └────┬─────┘
         │  kernel passes data between master ↔ slave
    ┌────┴─────┐
    │  Slave    │  <── looks like /dev/pts/N
    │  (pts/N)  │
    └──────────┘
         │
         │  stdin/stdout/stderr
         ▼
    Shell (bash, zsh, fish)

The POSIX convenience function forkpty() bundles the entire dance into one call: it allocates the PTY pair, forks a child process, connects the child's stdin/stdout/stderr to the slave side, and returns the master file descriptor to the parent. Every major terminal emulator on Linux and macOS uses forkpty() — it is the standard way to spawn a shell inside a program.

node-pty — The Standard That Breaks on Android

node-pty is Microsoft's npm package for PTY allocation in Node.js. It is the de facto standard for any Node.js application that needs to spawn a terminal session. The list of tools that depend on it is staggering:

Tool What It Does
VS Code (integrated terminal) The most popular code editor's terminal
code-server VS Code in a browser (self-hosted)
Hyper Electron-based terminal emulator
Tabby Cross-platform terminal with SSH
ttyd Share terminal over the web
Wetty Web-based SSH terminal
Gemini CLI Google's AI coding assistant
Claude Code Anthropic's AI coding CLI

node-pty has two fatal problems on Termux:

Problem 1 — Build Failure: node-pty uses node-gyp to compile a native C++ addon. Its binding.gyp file references an android_ndk_path variable that does not exist in Termux. Termux is not an Android NDK build environment — it is a native Linux environment that happens to run on Android. The build fails immediately with gyp errors.
Problem 2 — Runtime Failure: Even if you could get it to compile, node-pty calls forkpty() from glibc's <pty.h>. Android's Bionic libc historically did not implement forkpty(). The function either does not exist or behaves incorrectly on older Android versions. The process crashes or hangs trying to allocate a PTY.

This has been a long-standing, well-known blocker. Issues have been reported against node-pty since 2024. As of late 2025, there is no upstream fix. The problem is fundamental — node-pty was designed for desktop operating systems and has no Android code path.

The real-world impact: any xterm.js-based web terminal with a Node.js backend simply cannot work on Android. code-server's terminal tab? Broken. ttyd on your phone? Dead on arrival. Building a web-based terminal tool in Node.js for Termux? Impossible.

portable-pty — The Rust Solution

portable-pty is a Rust crate by Wez Furlong, the author of WezTerm terminal. It provides a trait-based, cross-platform PTY abstraction that works on Linux, macOS, Windows, and — with a patch — Android.

Claude helped patch portable-pty to add #[cfg(target_os = "android")] detection. The Android code path avoids forkpty() entirely and instead uses lower-level POSIX primitives that Bionic does support:

// The Android PTY allocation sequence
// Each step uses primitives that Bionic implements correctly

// 1. Open the PTY master device
let master = open("/dev/ptmx", O_RDWR | O_NOCTTY);

// 2. Grant and unlock the slave side
grantpt(master);    // Set ownership/permissions on slave
unlockpt(master);   // Allow the slave to be opened

// 3. Get the slave device name (e.g., "/dev/pts/3")
let slave_name = ptsname(master);

// 4. Open the slave side
let slave = open(slave_name, O_RDWR);

// 5. Fork a child process
match fork() {
    Ok(ForkResult::Child) => {
        // In the child: set up a new session
        setsid();              // Become session leader
        ioctl(slave, TIOCSCTTY); // Set controlling terminal

        // Wire stdin/stdout/stderr to the slave PTY
        dup2(slave, STDIN);
        dup2(slave, STDOUT);
        dup2(slave, STDERR);

        // Execute the shell
        exec("/data/data/com.termux/files/usr/bin/bash");
    }
    Ok(ForkResult::Parent { child }) => {
        // In the parent: use master fd to communicate
        // Read from master = see what the shell prints
        // Write to master = send keystrokes to the shell
    }
}

The key insight: forkpty() is just a convenience wrapper around these individual operations. Every one of these primitives — open, grantpt, unlockpt, ptsname, fork, setsid, ioctl(TIOCSCTTY) — works correctly on Android's Bionic. The problem was never that Android couldn't do PTYs. It was that the standard convenience function was broken, and nobody had implemented the manual path.

// Using portable-pty in a Rust application
use portable_pty::{CommandBuilder, PtySize, native_pty_system};

fn spawn_shell() -> Result<(), Box<dyn std::error::Error>> {
    let pty_system = native_pty_system();

    // Open a PTY with initial size
    let pair = pty_system.openpty(PtySize {
        rows: 24,
        cols: 80,
        pixel_width: 0,
        pixel_height: 0,
    })?;

    // Spawn bash in the PTY
    let mut cmd = CommandBuilder::new("bash");
    cmd.env("TERM", "xterm-256color");
    let child = pair.slave.spawn_command(cmd)?;

    // Read/write via the master side
    let mut reader = pair.master.try_clone_reader()?;
    let mut writer = pair.master.take_writer()?;

    // Now pipe these to a WebSocket, HTTP stream, etc.
    Ok(())
}

What This Enables

With portable-pty working on Android, the entire architecture changes:

Architecture Data Flow Status
Old (Node.js) Browser xterm.js → WebSocket → Node.js → node-pty → bash BROKEN
New (Rust) Browser xterm.js → WebSocket → Rust server → portable-pty → bash WORKS

Rust web frameworks — axum, actix-web, warp — all compile and run natively on Termux. Combined with portable-pty, you can build a complete web terminal server that:

  • Serves an xterm.js frontend over HTTP
  • Accepts WebSocket connections from browsers
  • Spawns real bash sessions via PTY
  • Runs entirely on your Android phone
# Building a Rust web terminal on Termux — it actually works
pkg install rust
cargo new termux-web-terminal
cd termux-web-terminal

# Add dependencies to Cargo.toml
# axum (web framework) + portable-pty + tokio-tungstenite (WebSockets)
cargo add axum tokio portable-pty tokio-tungstenite

# Build natively on the phone
cargo build --release

# Run it
./target/release/termux-web-terminal
# Now open http://localhost:3000 in your phone's browser

This is a fundamental capability unlock. Web-based development tools, terminal sharing, remote access servers, pair programming tools — all are now possible on Android. The bottleneck was never the hardware (modern phones have 8+ cores and 12GB+ RAM). It was a single missing function in a C library.

Claude Code TMPDIR Fix

Even after solving PTY allocation, getting real development tools running on Termux exposed another class of problem: hardcoded temp paths.

Claude Code (Anthropic's AI coding CLI) hardcoded /tmp/claude/ paths throughout its codebase for subagent communication, background task state, and the Task tool. On Android, /tmp is not writable by non-root users. Termux provides $TMPDIR pointing to $PREFIX/tmp, but Claude Code ignored it entirely.

Impact: The basic CLI launched and could hold a conversation, but critical subsystems silently failed. Subagent spawning crashed with EACCES. Background tasks could not write state files. The Task tool threw permission errors. The tool appeared to work but was running in a severely degraded mode.

Multiple GitHub issues documented the problem over months:

Issue Title / Context
#15628 Initial report — /tmp permission denied on Termux
#15637 Subagent spawn failure on Android
#15700 EACCES writing to /tmp/claude/ in Termux
#16955 Task tool broken on Termux
#17366 Background tasks fail silently
#18342 Request: respect $TMPDIR environment variable
#19387 Follow-up / confirmation of fix

The fix arrived in Claude Code v2.1.4 / v2.1.5 with a new environment variable:

# Set the Claude Code temp directory to Termux's writable tmp
export CLAUDE_CODE_TMPDIR="$TMPDIR/claude"
mkdir -p "$CLAUDE_CODE_TMPDIR"

# Add to your shell config so it persists
echo 'export CLAUDE_CODE_TMPDIR="$TMPDIR/claude"' >> ~/.bashrc
echo 'mkdir -p "$CLAUDE_CODE_TMPDIR"' >> ~/.bashrc

# Verify it's set
echo $CLAUDE_CODE_TMPDIR
# /data/data/com.termux/files/usr/tmp/claude
Broader Lesson: Well-behaved Unix programs should use os.tmpdir() (Node.js), tempfile.gettempdir() (Python), or std::env::temp_dir() (Rust) — all of which respect $TMPDIR. Hardcoding /tmp is a portability bug that breaks on Android, macOS sandboxed apps, and various embedded Linux systems. If your tool writes temp files, honor the environment variable.
08

Termux:API & Android Integration

Termux:API bridges the gap between the Linux command line and Android's hardware and system services. Camera, GPS, SMS, notifications, biometrics — all accessible from bash scripts.

Setup

Termux:API requires two installations — the companion Android app and the CLI package:

# Step 1: Install the Termux:API app from F-Droid
# (Search for "Termux:API" in F-Droid — it must be from the same source as Termux)

# Step 2: Install the CLI tools inside Termux
pkg install termux-api

# Step 3: Test it
termux-battery-status
Both Are Required: The termux-api package provides the CLI commands, but they communicate with the Termux:API Android app via IPC to access hardware. If you only install the package without the companion app, every command will hang indefinitely waiting for a response that never comes.
Same Source Rule: The Termux:API app must come from the same source (F-Droid or GitHub) as the main Termux app. Mixing sources means different signing keys, and the IPC communication will be rejected by Android's security model.

Device & Sensor Commands

Battery Status
termux-battery-status
JSON: percentage, status, temperature, plugged
GPS Location
termux-location
JSON: latitude, longitude, altitude, accuracy
WiFi Info
termux-wifi-connectioninfo
Current connection: SSID, BSSID, IP, speed
WiFi Scan
termux-wifi-scaninfo
Scan nearby networks (JSON array)
Volume Control
termux-volume
Get/set volume for all audio streams
Vibrate
termux-vibrate -d 500
Vibrate for N milliseconds
Flashlight
termux-torch on
Toggle the camera flashlight on or off
Fingerprint Auth
termux-fingerprint
Trigger biometric authentication dialog
# Battery monitoring — JSON output, perfect for jq
$ termux-battery-status
{
  "health": "GOOD",
  "percentage": 73,
  "plugged": "UNPLUGGED",
  "status": "DISCHARGING",
  "temperature": 28.5
}

# GPS location with provider selection
$ termux-location -p gps
{
  "latitude": 37.7749,
  "longitude": -122.4194,
  "altitude": 12.0,
  "accuracy": 3.5,
  "bearing": 0.0,
  "speed": 0.0
}

# Biometric auth for scripts that need security
$ termux-fingerprint
{
  "auth_result": "AUTH_RESULT_SUCCESS"
}

Camera & Media

Take Photo
termux-camera-photo out.jpg
Capture from rear camera (use -c 1 for front)
Text-to-Speech
termux-tts-speak "Hello"
Speak text aloud using Android TTS engine
Toast Message
termux-toast "Done!"
Show a brief Android toast notification
# Take a photo with the front camera
termux-camera-photo -c 1 selfie.jpg

# Speak text aloud (pipes work)
echo "Build complete" | termux-tts-speak

# Toast with positioning and color
termux-toast -g middle -b white -c black "Server started on :8080"

Clipboard & Communication

Clipboard Get
termux-clipboard-get
Read current system clipboard
Clipboard Set
termux-clipboard-set
Pipe content to system clipboard
Send SMS
termux-sms-send -n NUM "msg"
Send a text message to a phone number
List SMS
termux-sms-list
Read recent text messages as JSON
# Copy command output to clipboard
pwd | termux-clipboard-set

# Paste clipboard into a file
termux-clipboard-get > pasted.txt

# Send an SMS
termux-sms-send -n "+15551234567" "Build deployed successfully"

# Read last 5 SMS messages
termux-sms-list -l 5 | jq '.[].body'

Notifications & Dialogs

# Send a notification
termux-notification \
  --title "Build Complete" \
  --content "Project compiled successfully in 42s" \
  --id build-status

# Notification with action button
termux-notification \
  --title "Server Crashed" \
  --content "Express server exited with code 1" \
  --button1 "Restart" \
  --button1-action "termux-toast 'Restarting...'; node server.js &"

# Remove a notification by ID
termux-notification-remove build-status

# Interactive dialog — text input
termux-dialog text -t "Enter project name" -i "my-project"
# Returns: {"code": 0, "text": "user-input-here"}

# Dialog — radio buttons
termux-dialog radio -t "Choose environment" -v "dev,staging,prod"

# Dialog — date picker
termux-dialog date -t "Select deadline"

# Dialog — checkbox list
termux-dialog checkbox -t "Select features" -v "auth,api,ui,tests"

Scripting Patterns

Every Termux:API command outputs JSON, making it ideal for scripting with jq:

# Low battery warning script
#!/bin/bash
LEVEL=$(termux-battery-status | jq '.percentage')
if [ "$LEVEL" -lt 20 ]; then
    termux-notification \
        --title "Low Battery" \
        --content "Battery at ${LEVEL}%  — plug in soon"
    termux-vibrate -d 1000
    termux-tts-speak "Battery low. ${LEVEL} percent remaining."
fi

# Location-based greeting
#!/bin/bash
LAT=$(termux-location -p network | jq '.latitude')
LON=$(termux-location -p network | jq '.longitude')
termux-toast "You are at $LAT, $LON"

# Clipboard monitor — log everything copied
#!/bin/bash
LAST=""
while true; do
    CURRENT=$(termux-clipboard-get)
    if [ "$CURRENT" != "$LAST" ]; then
        echo "$(date): $CURRENT" >> ~/clipboard-log.txt
        LAST="$CURRENT"
    fi
    sleep 2
done

# Build notification helper function
notify_result() {
    if [ $? -eq 0 ]; then
        termux-notification -t "Success" -c "$1 completed"
        termux-vibrate -d 200
    else
        termux-notification -t "Failed" -c "$1 failed with exit code $?"
        termux-vibrate -d 1000
    fi
}

# Usage:
cargo build --release; notify_result "Rust build"

Companion Add-on Apps

Beyond Termux:API, the Termux ecosystem includes several other add-on apps — all available on F-Droid:

Add-on Purpose Use Case
Termux:Boot Run scripts on device boot Auto-start SSH server, web servers, or cron jobs when your phone boots
Termux:Widget Home screen shortcut widgets One-tap script execution from Android home screen (place scripts in ~/.shortcuts/)
Termux:Tasker Tasker/Automate integration Run Termux scripts from Tasker automations (location triggers, time-based, NFC, etc.)
Termux:Float Floating terminal window Terminal overlay on top of other apps — run commands without leaving your current app
Termux:Styling Color schemes & fonts Choose from preset color schemes and fonts for the Termux terminal
# Termux:Boot — auto-start script
# Place scripts in ~/.termux/boot/
mkdir -p ~/.termux/boot
cat > ~/.termux/boot/start-sshd.sh <<'EOF'
#!/data/data/com.termux/files/usr/bin/bash
termux-wake-lock
sshd
EOF
chmod +x ~/.termux/boot/start-sshd.sh

# Termux:Widget — home screen shortcuts
# Place scripts in ~/.shortcuts/
mkdir -p ~/.shortcuts
cat > ~/.shortcuts/sync-notes.sh <<'EOF'
#!/data/data/com.termux/files/usr/bin/bash
cd ~/notes && git pull && git add -A && git commit -m "sync" && git push
termux-toast "Notes synced"
EOF
chmod +x ~/.shortcuts/sync-notes.sh
09

Services & Networking

Running servers, daemons, and persistent processes on a phone requires navigating Android's aggressive process management. SSH, web servers, and background services are all possible — but you have to fight for every watt.

SSH Server

OpenSSH runs out of the box on Termux, but listens on port 8022 instead of 22. Unprivileged apps can't bind to ports below 1024, so Termux's sshd defaults to a high port. Password auth works immediately; key-based auth takes a minute to configure and is strongly recommended.

# Install OpenSSH
pkg install openssh

# Set a password (required for first login)
passwd

# Start SSH server (port 8022 by default)
sshd

# Check your phone's IP
ifconfig wlan0 | grep 'inet '

# Connect from your desktop (same Wi-Fi network)
# Username is always your Termux user — check with `whoami`
ssh -p 8022 $(whoami)@192.168.1.XXX
# Key-based authentication (recommended)
# On your desktop, copy your public key to the phone:
ssh-copy-id -p 8022 user@192.168.1.XXX

# Or manually append your key:
cat ~/.ssh/id_ed25519.pub | ssh -p 8022 user@phone "cat >> ~/.ssh/authorized_keys"

# Disable password auth after keys work
# Edit $PREFIX/etc/ssh/sshd_config:
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' $PREFIX/etc/ssh/sshd_config

# Restart sshd to apply
pkill sshd; sshd

# SCP files to/from phone
scp -P 8022 ./file.txt user@phone:~/
scp -P 8022 user@phone:~/output.log ./
Port 8022, not 22: This trips up everyone on day one. Termux runs as a regular (unprivileged) app, so it cannot bind to ports below 1024. Every Termux networking tool — sshd, nginx, Node — must use a high port. Memorize -p 8022.

Auto-Start on Boot

Termux:Boot is a companion app (install from F-Droid alongside Termux) that runs scripts from ~/.termux/boot/ whenever the device boots. Combined with a wake lock, this keeps your services alive through reboots.

# Create the boot directory
mkdir -p ~/.termux/boot

# Auto-start SSH with wake lock
cat > ~/.termux/boot/start-sshd.sh <<'EOF'
#!/data/data/com.termux/files/usr/bin/bash
termux-wake-lock
sshd
EOF
chmod +x ~/.termux/boot/start-sshd.sh

# Auto-start multiple services
cat > ~/.termux/boot/start-services.sh <<'EOF'
#!/data/data/com.termux/files/usr/bin/bash
termux-wake-lock

# Start SSH
sshd

# Start crond
crond

# Start a web server in the background
cd ~/www && python -m http.server 8080 &

# Log boot time
echo "Booted at $(date)" >> ~/boot.log
EOF
chmod +x ~/.termux/boot/start-services.sh
Termux:Boot must be launched once: After installing Termux:Boot from F-Droid, you must open the app at least once so Android registers it as a boot receiver. After that, it runs silently on every boot. Also ensure Termux:Boot is excluded from battery optimization.

termux-services (runit)

For proper service management (start, stop, restart, auto-start), termux-services provides a runit-based supervisor. Services are directories under $PREFIX/var/service/, each containing a run script.

# Install the runit service manager
pkg install termux-services

# Restart Termux after installation (required)
# runit starts on next session

# Service management commands
sv up sshd           # Start sshd service
sv down sshd         # Stop sshd service
sv status sshd       # Check service status

# Enable a service (auto-start on Termux launch)
sv-enable sshd

# Disable auto-start
sv-disable sshd

# List all available services
ls $PREFIX/var/service/
# Create a custom service
# Service directory structure:
# $PREFIX/var/service/myservice/
#   run        — executable script that stays in foreground
#   log/run    — optional logging script

mkdir -p $PREFIX/var/service/mywebserver

cat > $PREFIX/var/service/mywebserver/run <<'EOF'
#!/data/data/com.termux/files/usr/bin/bash
exec python -m http.server 8080 --directory ~/www 2>&1
EOF
chmod +x $PREFIX/var/service/mywebserver/run

# runit picks it up automatically
sv status mywebserver

Web Servers

Any web server that runs on Linux can run on Termux — just remember to bind to a port above 1024.

nginx
pkg install nginx
Full-featured web server and reverse proxy
Python
python -m http.server 8080
Zero-config static file server
Node.js
npx serve -l 3000
Static server with directory listing
# nginx — edit config to use high port
pkg install nginx
# Default config: $PREFIX/etc/nginx/nginx.conf
# Change: listen 8080; (not 80)
sed -i 's/listen       80;/listen       8080;/' $PREFIX/etc/nginx/nginx.conf
nginx                # Start
nginx -s reload      # Reload config
nginx -s stop        # Stop

# Python — instant static server
cd ~/my-site && python -m http.server 8080

# Node.js — with npx (no global install)
npx serve ~/my-site -l 3000

# Node.js — custom server
node -e "require('http').createServer((q,s)=>s.end('Hello from Termux')).listen(3000)"

Wake Locks & Battery

Android aggressively suspends background apps to save battery. A wake lock tells Android to keep the CPU running even when the screen is off. Without one, long-running processes (compiles, downloads, servers) will be killed within minutes.

# Acquire wake lock (keeps CPU alive, screen can be off)
termux-wake-lock

# Release wake lock
termux-wake-unlock

# Check wake lock status — look for Termux notification icon
# A persistent notification with a lock icon = wake lock active

# Pattern: acquire before long tasks, release after
termux-wake-lock
make -j4 && echo "Build done"
termux-wake-unlock
Battery optimization must be disabled for Termux: Even with a wake lock, Android may still kill Termux if it's "battery optimized." Go to Settings → Apps → Termux → Battery → Unrestricted (path varies by OEM). On Samsung, also check Device Care → Battery → Sleeping Apps and remove Termux. On Xiaomi, look for Settings → Battery → App Battery Saver → Termux → No Restrictions.

Phantom Process Killer (Android 12+)

The single biggest threat to Termux reliability. Starting with Android 12, Android monitors child processes spawned by apps and kills them when the system-wide count exceeds 32. This is the infamous Phantom Process Killer.

Android Version Fix
12 – 12L ADB command: adb shell device_config put activity_manager max_phantom_processes 2147483647
13 Same ADB command, or Developer Options → "Feature flags" → settings_enable_monitor_phantom_procs → disable
14+ Developer Options → "Disable child process restrictions" toggle
# Symptoms: random SIGKILL during compilation, servers dying
# You'll see this in Termux:
[Process completed (signal 9) - press Enter]

# Fix for Android 12-13 via ADB (run from desktop)
adb shell "device_config set_sync_disabled_for_tests persistent"
adb shell "device_config put activity_manager max_phantom_processes 2147483647"

# Verify the setting stuck
adb shell "device_config get activity_manager max_phantom_processes"
# Should output: 2147483647

# Fix for Android 14+
# Settings → Developer Options → "Disable child process restrictions" → ON
# No ADB required
OEM variations: Samsung's OneUI and Xiaomi's MIUI add additional process killers on top of stock Android's Phantom Process Killer. Samsung has "Sleeping Apps" and "Deep Sleeping Apps" lists that must exclude Termux. Xiaomi has "Battery Saver" per-app restrictions and "MIUI Optimization" that adds its own kills. Always check both the stock Android settings and OEM-specific battery/memory management.

Tunneling for Remote Access

Your phone sits behind NAT on a cellular or Wi-Fi network. To access Termux services from outside the local network, you need a tunnel.

# ADB port forwarding (phone connected via USB)
# Run on desktop — forwards desktop:8022 → phone:8022
adb forward tcp:8022 tcp:8022
ssh -p 8022 user@localhost    # Now connect to localhost

# cloudflared tunnel (free, no account needed for quick tunnels)
pkg install cloudflared
cloudflared tunnel --url http://localhost:8080
# Gives you a public https://xxx.trycloudflare.com URL

# ngrok (free tier, account required)
# Download arm64 binary from ngrok.com
./ngrok tcp 8022
# Gives you a public tcp://X.tcp.ngrok.io:NNNNN endpoint
# Connect: ssh -p NNNNN user@X.tcp.ngrok.io

# SSH reverse tunnel (if you have a VPS)
ssh -R 9022:localhost:8022 you@your-vps.com
# Then from anywhere: ssh -p 9022 user@your-vps.com
ADB over Wi-Fi: On Android 11+, enable wireless debugging in Developer Options. Pair your phone with adb pair HOST:PORT, then adb connect HOST:PORT. This lets you use ADB port forwarding without a USB cable.
10

Troubleshooting & Survival Guide

A catalog of every wall you'll hit and the crowbar to get past it. Termux errors are cryptic because they come from the collision of Linux expectations and Android reality.

Common Problems

Error / Symptom Cause Fix
[Process completed (signal 9)] Phantom Process Killer (Android 12+) ADB command or Developer Options toggle — see Section 09
bad system call seccomp filtering blocking syscalls Check Android version; some syscalls are blocked on newer kernels. Update Termux packages.
Permission denied on executables W^X enforcement (Android 10+) Don't run binaries from /sdcard/ or /tmp/. Use $PREFIX/bin/ or $HOME/ paths.
EACCES: permission denied, mkdir '/tmp/...' Hardcoded /tmp paths in tools Set TMPDIR=$PREFIX/tmp or tool-specific env vars (npm_config_cache, etc.)
pkg: command not found Missing termux-tools or corrupted PATH apt update && apt install termux-tools or restart Termux session
Services stop after screen off Battery optimization killing Termux termux-wake-lock + disable battery optimization for Termux
SSH connection drops randomly Android suspending Termux process Wake lock + battery exemption + Termux:Boot for auto-restart
Can't access /sdcard files Missing storage permission Run termux-setup-storage, grant permission in Android dialog
error: externally-managed-environment Python PEP 668 enforcement Use python -m venv or pip install --break-system-packages
node-gyp build failures Missing NDK path or unsupported native module Check if the native module supports Termux/Android. Try pkg install nodejs-lts instead.

Android Version Timeline

Each Android release tightened the screws on what unprivileged apps can do. Here's the history of restrictions that affect Termux:

Android API What Changed Impact on Termux
7 – 8 24–27 Minimal restrictions The golden age. Everything just works. execve from anywhere, no process killers.
10 29 W^X enforcement execve blocked on app data directory for SDK 29+ targets. Termux F-Droid build still works (targets lower SDK). Binaries from /sdcard/ won't execute.
11 30 Scoped storage mandatory MANAGE_EXTERNAL_STORAGE permission needed for broad file access. termux-setup-storage handles this.
12 31–32 Phantom Process Killer The big one. Kills child processes beyond 32 system-wide. Compilations, servers, tmux sessions — all at risk. ADB command required to disable.
13 33 Settings flag for phantom killer Can disable phantom process monitoring from Developer Options feature flags — no ADB required on some ROMs.
14 34 Developer Options toggle Clean "Disable child process restrictions" toggle in Developer Options. The easiest fix yet.
15+ 35+ Ongoing platform pressure Rising minTargetSdkVersion requirements, tightening SELinux policies. Termux adapts with each release but the trend is toward more restriction.

Quick Diagnostics

When something breaks, start here. These commands tell you exactly what Android version, API level, and configuration you're dealing with:

# Android version (e.g., "14")
getprop ro.build.version.release

# API level (e.g., "34")
getprop ro.build.version.sdk

# Full Termux diagnostic dump — paste this in bug reports
termux-info

# SELinux status (usually "Enforcing")
getenforce

# CPU architecture
uname -m       # aarch64 for most modern phones

# Available RAM
free -h

# Check if phantom process limit is set
# (run via ADB from desktop)
adb shell "device_config get activity_manager max_phantom_processes"

# List running Termux processes
ps aux

# Check Termux app version
cat $PREFIX/etc/motd 2>/dev/null || echo "Check: Settings → Apps → Termux → Version"

Useful Aliases for .bashrc

Drop these into ~/.bashrc (or ~/.zshrc) to make daily Termux life faster:

# ~/.bashrc — Termux survival aliases

# Quick IP check (Wi-Fi)
alias myip='ifconfig wlan0 2>/dev/null | grep "inet " | awk "{print \$2}"'

# Battery status
alias battery='termux-battery-status | python -c "import sys,json; b=json.load(sys.stdin); print(f\"{b[\"percentage\"]}% {b[\"status\"]}\")"'

# Clipboard shortcuts
alias clip='termux-clipboard-get'
alias setclip='termux-clipboard-set'

# Quick TTS
say() { echo "$*" | termux-tts-speak; }

# GPS location (one-liner)
alias whereami='termux-location -p network | python -c "import sys,json; l=json.load(sys.stdin); print(f\"{l[\"latitude\"]}, {l[\"longitude\"]}\")"'

# Wake lock toggle
alias wl='termux-wake-lock && echo "Wake lock ON"'
alias wul='termux-wake-unlock && echo "Wake lock OFF"'

# Package shortcuts
alias pkgi='pkg install'
alias pkgs='pkg search'
alias pkgu='pkg update && pkg upgrade -y'

# Start SSH server + wake lock
alias startssh='termux-wake-lock && sshd && echo "sshd on :8022"'

# tmux persistent session — reattach or create
alias t='tmux attach 2>/dev/null || tmux new -s main'

Key File Locations

Termux uses a non-standard filesystem layout. This table maps the paths you'll need most often:

Variable / Path Expands To Purpose
$HOME /data/data/com.termux/files/home Your home directory
$PREFIX /data/data/com.termux/files/usr The "root" filesystem (/usr equivalent)
$PREFIX/bin/ Installed binaries (python, node, git, etc.)
$PREFIX/etc/ Config files (sshd_config, nginx.conf, etc.)
$PREFIX/tmp/ Temp directory (set TMPDIR to this)
$PREFIX/var/service/ runit service directories
~/.ssh/ SSH keys and authorized_keys
~/.termux/ Termux config (termux.properties, colors, font)
~/.termux/boot/ Scripts run on device boot (Termux:Boot)
~/.shortcuts/ Home screen widget scripts (Termux:Widget)
~/storage/ Symlinks to /sdcard/ subdirectories (after termux-setup-storage)