Skip to content

About

Drive Termux on any Android device over plain adb: ax/atx run-as channel, Android↔Android USB OTG switching, and a probe that verifies equivalence with a real Termux app session

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

adb-termux-kit

Remote-drive Termux on any Android device over plain adb — no root, no extra app, no SSH. A few tiny pieces:

piece where what
ax device Termux $PREFIX/bin/ax environment normalizer executed via run-as
atx host $PREFIX/bin (or anywhere) thin wrapper that re-quotes arguments for the device shell
usb-host host make the host the USB OTG controller and attach the peer (Android-to-Android adb)
usb-device host revert the host to gadget mode so a PC can debug it
./install.sh                # push ax to the device + install atx locally
usb-host                    # Android host: take the OTG host role, list the peer
atx                         # interactive login bash on the device
atx pkg update              # single command
atx bash -c 'apt list --upgradable | wc -l'
ATX_PACKAGE=com.termux.debug atx ...   # different package
ANDROID_SERIAL=xxx atx ...             # multi-device

Android-to-Android setup (USB OTG)

When the host is itself an Android device (Termux) wired to the target through a USB-C cable, run usb-host once after plugging in: it flips the host's USB controller to the host role and connects over adb. usb-device reverts to gadget mode so a PC can debug the host again.

Both are vendored as-is from a daily-driver setup: they write the MTK usb-role sysfs node (/sys/devices/platform/soc/11201000.usb0/...) and the Type-C preferred_role, and need Termux sudo (tsu). Adjust RS/TC if your host exposes different paths. Note: run usb-host when the host is in its default device mode (e.g. after usb-device or a reboot) — re-running it while already in host mode resets the controller and may drop the peer's USB function set.

How it works

host shell ──> adb shell ──> run-as com.termux files/usr/bin/ax CMD
                                          │
              ax: cd $HOME, umask 077, PATH=$PREFIX/bin,
                  env -i {HOME,PREFIX,PATH,TMPDIR,LANG,LD_PRELOAD}, exec "$@"

run-as works because official Termux builds are marked debuggable; it runs your command as the Termux app uid (same data dir, same SELinux MCS categories), which is why apt/dpkg state, files and credentials behave exactly like a local session.

Equivalence verification (2026-09-25, an Android 13 tablet, Termux 0.118.0)

The same probe (probe/axprobe.sh) was executed

  1. through atx (SELinux runas_app), and
  2. inside the real Termux app (untrusted_app_27) via Termux's RUN_COMMAND intent (needs allow-external-apps=true in ~/.termux/termux.properties and a root-flavoured am startservice to satisfy the permission check).

Raw outputs are kept in probe/runas-side.out and probe/app-side.out.

Verified identical

  • uid/gid, app-data isolation (same MCS categories)
  • bash / apt / dpkg / pkg toolchain resolution and dpkg state
  • file rwx + script execution under $HOME and $PREFIX
  • DNS and outbound HTTPS
  • binder calls that an unprivileged app may make (pm path, settings get, /system/bin/am ...)
  • signals, fd limits, getprop

Differences fixed in ax v2 (found by the probe)

symptom fix
starting cwd was the package dir, not $HOME cd "$HOME"
/system/bin leaked into PATH (toybox wget shadowed) PATH=$PREFIX/bin only
umask 0000 → world-readable files umask 077
adb-injected env (ANDROID_*, HOSTNAME, ANDROID_SOCKET_adbd, …) env -i rebuild

Inherent, unfixable differences (documented, not bugs)

  1. SELinux domain runas_app vs untrusted_app_27; supplementary groups differ (the run-as context carries shell-ish groups such as readproc, i.e. it is a small superset of the real app).
  2. Seccomp off in the run-as context (the app is filtered); capability bounding set differs.
  3. No tty: no job control, isatty() false, interactive TUIs unusable.
  4. No app session: TERMUX_APP__* / TERMUX_VERSION / TERM unset; $PREFIX/bin/am (Termux's am-socket wrapper) and termux-* app-integrated commands need a live Termux session. Workaround: use /system/bin/am (or su -c am for privileged operations) — both verified to behave identically from either context.
  5. Scoped storage: /sdcard writes fail in both contexts unless the Termux app itself has been granted storage permission (then the real app can write, the run-as context still cannot).

Bottom line: for CLI work — package management, builds, scripting, networking, file operations — atx is a faithful drop-in for typing in the Termux app.

Repo layout

ax                  device-side helper (installed as $PREFIX/bin/ax)
atx                 host-side wrapper
usb-host            host-side: switch to USB host role (Android↔Android adb)
usb-device          host-side: revert to USB device role
install.sh          installer (device + host)
probe/axprobe.sh    environment equivalence probe
probe/*.out         reference outputs from the verification run
LICENSE             MIT

License

MIT — see LICENSE.

About

Drive Termux on any Android device over plain adb: ax/atx run-as channel, Android↔Android USB OTG switching, and a probe that verifies equivalence with a real Termux app session

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages