Run Bun on Termux (Android) without proot.
Installation | Documentation | Known Issues | Credits
Want to use Drivebase, OpenCode, or Pi with Bun in Termux? See other projects guides.
curl -fsSL "https://raw.githubusercontent.com/Happ1ness-dev/bun-termux/main/helper_scripts/bun-termux-manager" | bash -s install# Prerequisites
pkg install git curl clang make glibc-repo python
pkg install glibc-runner
# Bun install script will skip bashrc if it doesn't exist
touch ~/.bashrc
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Make bun install visible
source ~/.bashrc
# Obtaining bun-termux source
git clone https://github.com/Happ1ness-dev/bun-termux.git
cd bun-termux
# Build and install wrapper
make && make installbun --version
# --bun/-b to force bun instead of node
bun --bun x cowsay "bun-termux works!"
# "--os=android" helps with some native modules
BUN_OPTIONS="--os=android" bun install -g cowsay
cowsay "bun-termux works!"Tip
Symlink bun as node: If you don't have Node installed, some scripts may fail.
ln -s $HOME/.bun/bin/bun $HOME/.bun/bin/nodeIf you've installed bun-termux-manager, you can easily manage Bun versions.
Run
btm helpto see all available commands
btm update [bun|wrapper|all]bun- Just update Bunwrapper- Just update wrapperall- Update everything (Default)
You can also add --check to check for updates.
btm install --bun-version VERSION # e.g. 1.0.0Bun is built for glibc, not Android's bionic libc, and needs access to paths that Android restricts. bun-termux solves this with two components:
1. Wrapper (bun)
Uses "userland exec" to launch the real Bun binary through glibc's dynamic linker. This technique means bun build --compile outputs embed the wrapper, making binaries work.
2. LD_PRELOAD Shim (bun-shim.so)
Intercepts system calls to work around Android restrictions:
- Redirects denied opens of CWD parents → fake root directory (avoids
EACCESwhen Bun walks parent dirs) - Redirects shebang paths (e.g.
/usr/bin/env) → Termux prefix - Fakes
/proc/stat→ makesos.cpus()work - Stubs hardlinking → makes
bun installwork - Redirects bun's hardcoded
/tmp/bun-node*to$TMPDIRand bun symlinks to wrapper → makes--bunarg work - Redirects some dns-related
/etcpaths to$PREFIX/etc→ makesdns.lookup()work
See docs/README.md for the full technical breakdown.
| Variable | Description |
|---|---|
BUN_INSTALL |
Installation prefix (~/.bun) |
BUN_BINARY_PATH |
Override path to original bun binary |
BUN_OPTIONS |
Used by Bun for options/args |
See docs/README.md for all variables and defaults.
- x86_64 support is experimental. Any feedback from x64 Android users is welcome.
- Binaries built with
bun build --compilehave wrapper embedded, requiringbuno,bun-shim.soand glibc to be present on the system where they run. - Bun install/add/update/remove commands might require
BUN_OPTIONS="--os=android"env var if they install native modules. - If bun somehow fails to walk the current path due to permission error, it'll fail to get the current env vars too. I'll have to investigate why.
- When using
bun install, some module install scripts might fail withoutBUN_OPTIONS="--verbose". bun createwill skip copyinggitignore->.gitignoresince it always tries to hardlink it and has no copyfile fallback when that fails (e.g. EXDEV), leaving the project without a.gitignore.
For troubleshooting, refer to troubleshooting.md
This project is based on the userland exec technique from bun-termux-loader by @kaan-escober.
While bun-termux-loader focuses on creating self-contained bundled binaries with embedded Bun runtimes, this project takes a simpler approach: a lightweight wrapper that enables the standard Bun installation to work on Termux, including bun build --compile output, without embedding the entire Bun runtime.
MIT License - see LICENSE file for details.