Skip to content

Commit 4c8923b

Browse files
committed
feat: native Android (Termux) build + install.sh detection
- build btch-android-arm64 via bun-android-arm64 (bionic-linked, runs on Termux) - shim @opentui/core-android-arm64 for bundling (libopentui.so is static) - install.sh detects Termux and picks the android build, symlinks to $PREFIX/bin - bump Bun in CI to 1.3.14 (Android compile target)
1 parent bf67dc0 commit 4c8923b

5 files changed

Lines changed: 84 additions & 32 deletions

File tree

‎.github/workflows/release.yml‎

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ jobs:
4444
build_output: btch-arm64
4545
asset_name: btch-linux-arm64
4646
compile_target: bun-linux-arm64
47+
# Native Android (Termux) — Bun 1.3.14+ compiles a bionic-linked
48+
# binary (interpreter /system/bin/linker64) that actually runs on
49+
# Termux, unlike the glibc linux-arm64 build. libopentui.so is
50+
# statically linked so the TUI works too.
51+
- runner: ubuntu-latest
52+
build_output: btch-android
53+
asset_name: btch-android-arm64
54+
compile_target: bun-android-arm64
4755
- runner: windows-latest
4856
build_output: btch.exe
4957
asset_name: btch-windows-x64.exe
@@ -74,20 +82,29 @@ jobs:
7482
- name: Setup Bun
7583
uses: oven-sh/setup-bun@v2
7684
with:
77-
bun-version: 1.3.11
85+
bun-version: 1.3.14
7886

7987
- name: Install dependencies
8088
run: bun install --frozen-lockfile
8189

8290
# bun install only installs the OpenTUI platform package matching the
83-
# *build host* (x64), so cross-compiling the arm64 binary needs the
84-
# linux-arm64 native package present too (Bun bundles it at build time).
91+
# *build host* (x64), so cross-compiling the arm64/android binaries needs
92+
# the arm64 native package present too (Bun bundles it at build time).
8593
# The shared script downloads the tarball directly, bypassing npm's
8694
# os/cpu check without touching package.json/lockfiles.
8795
- name: Install ARM64 OpenTUI native package (cross-compile)
88-
if: matrix.asset_name == 'btch-linux-arm64'
96+
if: contains(matrix.asset_name, 'arm64')
8997
run: node scripts/install-opentui-platform.mjs @opentui/core-linux-arm64
9098

99+
# OpenTUI has no android package; for the android target Bun resolves
100+
# @opentui/core-android-arm64 at build time. libopentui.so is statically
101+
# linked, so the linux-arm64 package works verbatim as the android shim.
102+
- name: Shim Android OpenTUI package
103+
if: matrix.asset_name == 'btch-android-arm64'
104+
run: |
105+
mkdir -p node_modules/@opentui/core-android-arm64
106+
cp -r node_modules/@opentui/core-linux-arm64/. node_modules/@opentui/core-android-arm64/
107+
91108
- name: Compile standalone binary
92109
run: bun build --compile --target="${{ matrix.compile_target }}" --outfile "release/${{ matrix.build_output }}" ./src/index.ts
93110

@@ -161,6 +178,7 @@ jobs:
161178
release-assets/**/btch-linux-x64
162179
release-assets/**/btch-linux-x64-baseline
163180
release-assets/**/btch-linux-arm64
181+
release-assets/**/btch-android-arm64
164182
release-assets/**/btch-darwin-arm64
165183
release-assets/**/btch-windows-x64.exe
166184
release-assets/checksums.txt
@@ -194,7 +212,7 @@ jobs:
194212
- name: Setup Bun
195213
uses: oven-sh/setup-bun@v2
196214
with:
197-
bun-version: 1.3.11
215+
bun-version: 1.3.14
198216

199217
- name: Install dependencies
200218
run: bun install --frozen-lockfile

‎CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [3.0.5] - 2026-08-17
9+
10+
### Added
11+
- **Native Android (Termux) build**: release now ships `btch-android-arm64` (bionic-linked, Bun 1.3.14+ `bun-android-arm64` target) that runs directly on Termux with the full interactive TUI
12+
- `install.sh` detects Termux automatically and downloads the Android build (plus symlinks to `$PREFIX/bin`)
13+
14+
### Fixed
15+
- `install.sh` on Termux previously downloaded the glibc `linux-arm64` binary, which cannot execute on Termux (bionic libc) — `cannot execute: required file not found`
16+
817
## [3.0.4] - 2026-08-17
918

1019
### Added

‎README.md‎

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,17 @@ yarn global add btch-cli
5858
5959
**Android / Termux:**
6060

61-
- **npm route** (recommended) — `npm install -g btch-cli` works on Termux.
62-
The installer auto-detects Termux and installs OpenTUI's native ARM64
63-
component, which npm normally skips on Android. Requires Bun for Android
64-
(Bun ≥ 1.3.14 supports Android natively; install it with
65-
`curl -fsSL https://bun.sh/install | bash` or via Termux packages).
66-
- **Headless mode** — `btch --prompt "..."` does not need the interactive UI
67-
and is the most reliable way to run the agent inside Termux.
68-
- The standalone `install.sh` binary also ships an ARM64 build
69-
(`btch-linux-arm64`, cross-compiled), so Raspberry Pi / ARM Linux works too.
61+
- **One-liner works** — `curl -fsSL https://raw.githubusercontent.com/hostinger-bot/btch-cli/main/install.sh | bash`
62+
detects Termux and downloads the **native Android build** (`btch-android-arm64`,
63+
bionic-linked), which runs directly on Termux with the full interactive TUI.
64+
- **npm route** — `npm install -g btch-cli` also works on Termux (requires Bun
65+
for Android; Bun ≥ 1.3.14 supports Android natively). The postinstall hook
66+
auto-installs OpenTUI's native ARM64 component, which npm normally skips on
67+
Android.
68+
- **Headless mode** — `btch --prompt "..."` runs without the interactive UI
69+
and is the most lightweight way to use the agent inside Termux.
70+
- The release also ships `btch-linux-arm64` (glibc) for Raspberry Pi / ARM
71+
Linux servers — that one does **not** run on Termux (Termux uses bionic libc).
7072

7173
**Prerequisites:** an **API key** for your OpenAI-compatible endpoint and a modern terminal emulator for the interactive OpenTUI experience. Headless `--prompt` mode does not depend on terminal UI support. If you want host desktop automation via the built-in computer sub-agent, also enable **Accessibility** permission for your terminal app on macOS.
7274

‎install.sh‎

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,32 @@ done
6868
mkdir -p "$INSTALL_DIR"
6969
chmod 700 "$USER_DIR" "$INSTALL_DIR"
7070

71+
is_termux() {
72+
# Android/Termux uses the bionic libc, so the glibc linux-arm64 binary
73+
# cannot run there ("cannot execute: required file not found"). Detect it
74+
# and pick the dedicated android-arm64 build instead.
75+
[[ -n "${TERMUX_VERSION:-}" ]] && return 0
76+
[[ -d /data/data/com.termux ]] && return 0
77+
[[ "$(uname -o 2>/dev/null)" == "Android" ]] && return 0
78+
return 1
79+
}
80+
7181
resolve_target() {
7282
local raw_os arch
7383
raw_os=$(uname -s)
74-
case "$raw_os" in
75-
Darwin*) OS="darwin" ;;
76-
Linux*) OS="linux" ;;
77-
MINGW*|MSYS*|CYGWIN*) OS="windows" ;;
78-
*)
79-
echo "Unsupported OS: ${raw_os}" >&2
80-
exit 1
81-
;;
82-
esac
84+
if is_termux; then
85+
OS="android"
86+
else
87+
case "$raw_os" in
88+
Darwin*) OS="darwin" ;;
89+
Linux*) OS="linux" ;;
90+
MINGW*|MSYS*|CYGWIN*) OS="windows" ;;
91+
*)
92+
echo "Unsupported OS: ${raw_os}" >&2
93+
exit 1
94+
;;
95+
esac
96+
fi
8397

8498
arch=$(uname -m)
8599
case "$arch" in
@@ -92,7 +106,7 @@ resolve_target() {
92106
esac
93107

94108
case "${OS}-${ARCH}" in
95-
darwin-arm64|linux-x64|linux-arm64|windows-x64) ;;
109+
darwin-arm64|linux-x64|linux-arm64|android-arm64|windows-x64) ;;
96110
*)
97111
echo "Unsupported platform: ${OS}-${ARCH}" >&2
98112
exit 1
@@ -165,18 +179,27 @@ METAEOF
165179

166180
setup_global_symlink() {
167181
# Create a symlink in a system bin dir that is already on PATH (e.g.
168-
# /usr/local/bin) so `btch` works immediately in the current session
169-
# without needing to source shell config. Only done when possible; the
170-
# script falls back to the PATH hint otherwise.
182+
# /usr/local/bin, or $PREFIX/bin on Termux) so `btch` works immediately in
183+
# the current session without needing to source shell config. Only done
184+
# when possible; the script falls back to the PATH hint otherwise.
171185
GLOBAL_BIN_PATH=""
172186
[[ "$TARGET" == windows-* ]] && return 0
173-
[[ -w /usr/local/bin ]] || return 0
174-
if [[ -e "/usr/local/bin/${BINARY_NAME}" ]] && [[ ! -L "/usr/local/bin/${BINARY_NAME}" ]]; then
187+
188+
local bin_dir=""
189+
if is_termux && [[ -n "${PREFIX:-}" ]] && [[ -w "${PREFIX}/bin" ]]; then
190+
# Termux keeps $PREFIX/bin (e.g. /data/data/com.termux/files/usr/bin) on PATH.
191+
bin_dir="${PREFIX}/bin"
192+
elif [[ -w /usr/local/bin ]]; then
193+
bin_dir="/usr/local/bin"
194+
fi
195+
[[ -n "$bin_dir" ]] || return 0
196+
197+
if [[ -e "${bin_dir}/${BINARY_NAME}" ]] && [[ ! -L "${bin_dir}/${BINARY_NAME}" ]]; then
175198
# A real file (not our symlink) already exists; don't clobber it.
176199
return 0
177200
fi
178-
if ln -sf "${INSTALL_DIR}/${BINARY_NAME}" "/usr/local/bin/${BINARY_NAME}" 2>/dev/null; then
179-
GLOBAL_BIN_PATH="/usr/local/bin/${BINARY_NAME}"
201+
if ln -sf "${INSTALL_DIR}/${BINARY_NAME}" "${bin_dir}/${BINARY_NAME}" 2>/dev/null; then
202+
GLOBAL_BIN_PATH="${bin_dir}/${BINARY_NAME}"
180203
fi
181204
}
182205

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "btch-cli",
3-
"version": "3.0.4",
3+
"version": "3.0.5",
44
"description": "An open-source AI coding agent, built with Bun and OpenTUI.",
55
"type": "module",
66
"main": "dist/index.js",

0 commit comments

Comments
 (0)