$ ccx status · stable pinned · next one command ahead

Claude Code on Termux

Current Claude Code, patched to fit, pinned so it stays that way

stable / next channels · CLAUDE.md-aligned prompt patches · byte-preserving binary patcher

Claude Code ships as a bun-compiled glibc binary that hardcodes the /lib/ld-linux-aarch64.so.1 interpreter — absent on Android's bionic libc — and reads /etc/resolv.conf with a raw syscall that Termux cannot satisfy. ccx fetches each release from Anthropic's native channel, runs it through bun-on-termux's userland exec, patches the binary without moving a byte, and keeps a stable launcher that only changes when you promote.

# Two channels

next

~/.local/bin/claude-next
Runs
The newest release from Anthropic's native channel, fetched and patched by `ccx update`.
Patching
Byte-preserving: same-length edits survive bun-vfs offsets; a backup is kept.
Commands
ccx update [--channel latest|stable] [--pin X.Y.Z]

stable

~/.local/bin/claude
Runs
Whatever you last promoted. It never changes underneath you: the launcher sets DISABLE_AUTOUPDATER=1.
Patching
`ccx promote` snapshots next → stable and archives the outgoing binary for `ccx rollback`.
Commands
ccx promote · ccx rollback [--to X.Y.Z]

The same model runs Codex (cdx: isolated Bun install, DNS and ripgrep fixes, no PRoot) and Google's Antigravity CLI (agx: SHA-512 verified glibc binary launched through proot with its self-updater disabled). Every manager keeps immutable per-version releases, previews prune, and only schedules next updates when asked.

# What the patcher does

Applied by ccx update to every fetched binary. Each edit is opt-out via an env var (CCPATCH_KEEP_*); a .bak-prepatch copy is kept.

P1

DNS resolver

Rewrite the literal /etc/resolv.conf → /sdcard/dns.conf (same length).

bun's bundled c-ares reads that absolute path with a raw syscall; Termux has no /etc/resolv.conf, so OAuth login and token refresh time out. Opt out: CCPATCH_KEEP_RESOLV=1.

P2

Socket path

Launcher exports CLAUDE_CODE_TMPDIR=$PREFIX/tmp.

Termux /tmp is not writable; Claude Code's own tmpdir helper honours the variable, so no binary edit is needed.

P3

Commit directive

Blank “NEVER commit changes unless the user explicitly asks.”

Conflicts with a conventional-commit-per-round workflow. Opt out: CCPATCH_KEEP_NO_COMMIT=1.

P4

Comment directive

Blank “Default to writing no comments.”

Conflicts with a typed, explanatory-comment house style. Opt out: CCPATCH_KEEP_NO_COMMENTS=1.

# Patching a bun-compiled binary

# bun embeds the JS in a vfs blob keyed by internal byte offsets

  length-changing edit   ──▶  offsets shift  ──▶  binary corrupts
                                              (--version → bun 1.3.x)

  length-preserving edit ──▶  offsets intact ──▶  binary still runs
   (blank a string with equal-length spaces, or swap a path for one of the same length)

bun-vfs is not checksummed, so a same-length overwrite leaves every downstream offset in place: the patched binary still reports its own version and runs full inference. That's why ccx blanks the conflicting prompt lines with spaces instead of deleting them, and why the resolver redirect swaps /etc/resolv.conf for the exactly-as-long /sdcard/dns.conf.

# Quick start

install Claude Code with ccx
# Requirements: Termux + bun-on-termux (~/.bun/bin/bun-termux) + pkg install glibc-runner nodejs
npm i -g termux-tools          # ccx (Claude Code), cdx (Codex), agx (Antigravity)
export PATH="$HOME/.local/bin:$PATH"

ccx update                     # fetch + byte-patch the latest release into claude-next
claude-next --version          # try it
ccx promote                    # make it the stable `claude` (archives the previous one)
ccx status                     # channels, upstream versions, PATH check

# Something broke upstream? Go back in one command:
ccx rollback

Updates come from downloads.claude.ai/claude-code-releases, not npm. Each binary is ~250 MB; ccx prune reclaims old ones (keeps 2 by default). ccx schedule --every 24 is opt-in and only refreshes next.