close
Skip to content

Instantly share code, notes, and snippets.

@Brajesh2022
Last active June 26, 2026 01:54
Show Gist options
  • Select an option

  • Save Brajesh2022/e42160d29b55417db6c18c52dd1d6d37 to your computer and use it in GitHub Desktop.

Select an option

Save Brajesh2022/e42160d29b55417db6c18c52dd1d6d37 to your computer and use it in GitHub Desktop.
Antigravity CLI on Termux: Auto-Installer and Manual Patching Guide

🚀 Recommended Installation (Auto-Installer)

Antigravity CLI Demo The easiest and community-recommended way to install Antigravity CLI on Termux is using the standalone auto-installer.

curl -fsSL https://raw.githubusercontent.com/wallentx/antigravity-cli-termux/dev/install.sh | bash

How it works: This script instantly installs the latest release directly from the wallentx/antigravity-cli-termux repository. A huge thanks to the original repository owner, @wallentx, for packaging these releases! The repository automatically runs a GitHub Action every six hours that fetches the official binary and patches it using the exact methods outlined in this guide below.

If this script does not work for your specific device, or if some nerds want to patch it manually from scratch, use the manual method detailed below.


This document describes the manual working setup for running the native Antigravity CLI (agy) on Android Termux.

The main goal is to run the official Linux ARM64 Antigravity binary directly from Termux without Cloud Shell, without a full VM, and without replacing Android. The setup uses a small binary patch plus a wrapper that adapts the Linux/glibc binary to Termux's Android environment.

The method is designed to be repeatable for future Antigravity releases. The patch script scans instruction patterns instead of relying on fixed offsets. If Antigravity changes its allocator code generation in the future, the script will print warning counts instead of silently claiming success.

Shoutout

A huge shoutout to hojatha for providing the original patching analysis and strategy that makes this setup possible.

What This Fixes

Antigravity's Linux ARM64 binary can fail on Termux for multiple independent reasons.

The working setup fixes these problems:

  1. TCMalloc assumes a 48-bit ARM64 userspace virtual address space.
  2. Many Android/Termux devices expose only a 39-bit userspace virtual address layout.
  3. Android seccomp can block Go's faccessat2 syscall and kill the process with SIGSYS.
  4. Termux's LD_PRELOAD can inject a Bionic preload library into the glibc binary.
  5. The glibc environment may try to load libc.so, but Termux glibc's libc.so is a linker script, not an ELF shared object.
  6. Go's DNS resolver inside the glibc-loaded binary may not find the correct Android/Termux resolver config.
  7. TLS verification can fail unless the Termux CA bundle is exposed through SSL_CERT_FILE.
  8. Shell command hashing can keep pointing at an old agy, so the shortcut clears the shell hash before launching.

Expected Final Layout

After setup, the important files are:

~/.local/bin/agy              # original official Antigravity binary, left unchanged
~/.local/bin/agy.va39         # patched binary generated by the script
~/.local/bin/agy-va39         # wrapper used to launch the patched binary
~/.local/lib/agy-glibc/libc.so
~/.local/lib/agy-glibc/libc.so.6
~/patch_agy_va39.py           # reusable patch script

The user-facing commands are:

agy
a
agy-va39

agy and a should both run the agy-va39 wrapper.

Requirements

Install or verify these tools in Termux:

pkg update
pkg install python proot curl ca-certificates

You also need a Termux-compatible glibc installation that provides these files:

/data/data/com.termux/files/usr/glibc/lib/ld-linux-aarch64.so.1
/data/data/com.termux/files/usr/glibc/lib/libc.so.6

Verify them:

test -x /data/data/com.termux/files/usr/glibc/lib/ld-linux-aarch64.so.1
test -f /data/data/com.termux/files/usr/glibc/lib/libc.so.6

You also need the official Linux ARM64 agy binary installed at:

~/.local/bin/agy

Verify the binary exists:

test -x ~/.local/bin/agy
file ~/.local/bin/agy

The file output should identify it as an ARM64 Linux ELF binary.

Step 0: Install the Official Antigravity CLI Binary

Skip this step if ~/.local/bin/agy already exists.

Run the official install script:

curl -fsSL https://antigravity.google/cli/install.sh | bash

## Step 1: Create the Generalized VA39 Patch Script

Create `~/patch_agy_va39.py`:

```python
#!/usr/bin/env python3
"""
Generalized VA39 patch for the agy linux_arm64 binary.

Based on hjotha's analysis in:
https://github.com/google-antigravity/antigravity-cli/issues/64

This scans instruction patterns instead of using fixed offsets, so it can work
across builds where the relevant TCMalloc code moved.
"""

import hashlib
import shutil
import struct
import sys
from pathlib import Path


src = Path(sys.argv[1] if len(sys.argv) > 1 else str(Path.home() / ".local/bin/agy"))
dst = Path(str(src) + ".va39")

if not src.exists():
    raise SystemExit(f"Input binary does not exist: {src}")

print(f"Input binary : {src}")
print(f"SHA256 in    : {hashlib.sha256(src.read_bytes()).hexdigest()}")
print()

shutil.copyfile(src, dst)
data = bytearray(dst.read_bytes())


def get(off):
    return struct.unpack_from("<I", data, off)[0]


def put(off, word):
    struct.pack_into("<I", data, off, word)


# 1. Find google_malloc section via ELF header parsing.
lo, hi = 0, len(data)


def find_section(name_target):
    if data[:4] != b"\x7fELF":
        return None, None

    e_shoff = struct.unpack_from("<Q", data, 40)[0]
    e_shentsize = struct.unpack_from("<H", data, 58)[0]
    e_shnum = struct.unpack_from("<H", data, 60)[0]
    e_shstrndx = struct.unpack_from("<H", data, 62)[0]

    shstr_base = e_shoff + e_shstrndx * e_shentsize
    shstr_off = struct.unpack_from("<Q", data, shstr_base + 24)[0]

    for i in range(e_shnum):
        base = e_shoff + i * e_shentsize
        sh_name = struct.unpack_from("<I", data, base)[0]
        sh_offset = struct.unpack_from("<Q", data, base + 24)[0]
        sh_size = struct.unpack_from("<Q", data, base + 32)[0]

        nend = data.index(b"\x00", shstr_off + sh_name)
        section = data[shstr_off + sh_name : nend].decode("utf-8", errors="replace")
        if section == name_target:
            return sh_offset, sh_offset + sh_size

    return None, None


sec_lo, sec_hi = find_section("google_malloc")
if sec_lo is not None:
    lo, hi = sec_lo, sec_hi
    print(f"Found google_malloc section: file 0x{lo:x} - 0x{hi:x} ({(hi - lo) // 1024} KB)")
else:
    print("google_malloc section not found - scanning entire binary.")
    print("This is slower but may still work.")
print()

# 2. ubfx #42,#3 -> #35,#3 and lsl #42 -> #35.
# These move TCMalloc's tag extraction/insertion from bit 42 to bit 35.
ubfx_count = 0
lsl_count = 0
for off in range(lo, hi, 4):
    w = get(off)
    if (w & 0x7F800000) == 0x53000000:  # bitfield-move family
        immr = (w >> 16) & 0x3F
        imms = (w >> 10) & 0x3F
        if immr == 42 and imms == 44:  # ubfx Xn, Xm, #42, #3
            put(off, (w & ~((0x3F << 16) | (0x3F << 10))) | (35 << 16) | (37 << 10))
            ubfx_count += 1
        elif immr == 22 and imms == 21:  # lsl Xn, Xm, #42 encoded as lsr
            put(off, (w & ~((0x3F << 16) | (0x3F << 10))) | (29 << 16) | (28 << 10))
            lsl_count += 1

print(f"[1] ubfx patches : {ubfx_count}  (expect ~15)")
print(f"    lsl  patches : {lsl_count}   (expect ~2)")

# 3. Random address mask pairs.
# mov x10, #-0x6c00000001; movk x10, #0, lsl #48
# -> mov x10, #-1; lsr x10, x10, #29
# Gives x10 = 0x7ffffffff, a 39-bit address mask.
mask_count = 0
for off in range(lo, hi - 4, 4):
    if get(off) == 0x92D3800A and get(off + 4) == 0xF2E0000A:
        put(off, 0x9280000A)
        put(off + 4, 0xD35DFD4A)
        mask_count += 1

print(f"[2] Random mask  : {mask_count}  (expect ~3)")

# 4. MmapAlignedLocked upper bound: 1 << 48 -> 1 << 39.
mmap_count = 0
for off in range(lo, hi, 4):
    if get(off) == 0xF2E00029:
        put(off, 0xD3596129)
        mmap_count += 1

print(f"[3] MmapAligned  : {mmap_count}  (expect ~1)")

# 5. Inlined tag constants and fast-path deallocation masks.
# Move tag placement from bit 42 to bit 35.
word_rewrites = {
    0xD2C20009: 0xD2C00409,  # normal P0 tag x9: 4 << 42 -> 4 << 35
    0xD2C2000A: 0xD2C0040A,  # normal P0 tag x10
    0xF2C20008: 0xF2DFF408,  # normal dealloc mask x8
    0xF2C20009: 0xF2DFF409,  # normal dealloc mask x9
    0xD2C10009: 0xD2C00209,  # cold tag x9: 2 << 42 -> 2 << 35
    0xD2C1000A: 0xD2C0020A,  # cold tag x10
    0xF2C38008: 0xF2DFF708,  # cold/tagged dealloc mask x8
    0xF2C38009: 0xF2DFF709,  # cold/tagged dealloc mask x9
    0x92560A6C: 0x925D0A6C,  # tag mask 0x1c0000000000 -> 0x3800000000 x12
    0x92560A6A: 0x925D0A6A,  # tag mask x10
    0xD2C3000D: 0xD2C0060D,  # normal P1 tag x13: 6 << 42 -> 6 << 35
    0xD2C3000C: 0xD2C0060C,  # normal P1 tag x12
    0xD2C08008: 0xD2C00108,  # kTagFree: 1 << 42 -> 1 << 35
}
counts = {old: 0 for old in word_rewrites}
for off in range(lo, hi, 4):
    w = get(off)
    if w in word_rewrites:
        put(off, word_rewrites[w])
        counts[w] += 1

print(f"[4] Tag constants: {sum(counts.values())} words rewritten")

# 6. Android/Termux syscall compatibility.
# Go's faccessat2 syscall can be killed by Android seccomp with SIGSYS. The
# old faccessat syscall is enough for os/exec.LookPath checks on Termux.
faccessat2_count = 0
for off in range(0, len(data) - 12, 4):
    if (
        get(off) == 0xAA1F03E5
        and get(off + 4) == 0xAA1F03E6
        and get(off + 8) == 0xD28036E0
        and (get(off + 12) & 0xFC000000) == 0x94000000
    ):
        put(off + 8, 0xD2800600)  # mov x0, #48; syscall.SYS_FACCESSAT
        faccessat2_count += 1

print(f"[5] faccessat2   : {faccessat2_count} syscall wrapper rewritten")

dst.write_bytes(data)
dst.chmod(0o755)

out_sha = hashlib.sha256(dst.read_bytes()).hexdigest()
print()
print(f"SHA256 out   : {out_sha}")
print(f"Output       : {dst}")
print()

total = ubfx_count + lsl_count + mask_count + mmap_count + sum(counts.values()) + faccessat2_count
if total == 0:
    print("WARNING: No patches applied - binary structure may have changed.")
    print("Do NOT use the output binary.")
elif ubfx_count == 0 or mask_count == 0:
    print("WARNING: Some expected patches were not found.")
    print("The patch may be incomplete - test carefully.")
else:
    print("Patch looks complete. Now test with:")
    print()
    print("  GLIBC=/data/data/com.termux/files/usr/glibc/lib")
    print("  $GLIBC/ld-linux-aarch64.so.1 --library-path $GLIBC \\")
    print(f"    {dst} --version")

Make it executable:

chmod +x ~/patch_agy_va39.py

Step 2: Patch the Official Binary

Run the script against the original official binary:

python3 ~/patch_agy_va39.py ~/.local/bin/agy

The script creates:

~/.local/bin/agy.va39

The original binary remains unchanged:

~/.local/bin/agy

Healthy output should show nonzero patch counts. On the tested build, the counts were:

[1] ubfx patches : 15
    lsl  patches : 2
[2] Random mask  : 3
[3] MmapAligned  : 1
[4] Tag constants: 108 words rewritten
[5] faccessat2   : 1 syscall wrapper rewritten

Future builds may have different tag constant counts, but these are important signs:

ubfx patches should not be 0
Random mask should not be 0
MmapAligned should usually be nonzero
faccessat2 may be 0 if Go or the binary changed

If the script says no patches were applied, do not use the generated output.

Step 3: Create the glibc libc.so Shim

Some parts of the program or its dependencies may try to load libc.so dynamically. In the Termux glibc layout, libc.so can be an ASCII linker script instead of an ELF shared object. glibc's dynamic loader rejects that with invalid ELF header.

Create a tiny shim directory where both libc.so and libc.so.6 point to the real ELF library:

mkdir -p ~/.local/lib/agy-glibc
ln -sfn /data/data/com.termux/files/usr/glibc/lib/libc.so.6 ~/.local/lib/agy-glibc/libc.so
ln -sfn /data/data/com.termux/files/usr/glibc/lib/libc.so.6 ~/.local/lib/agy-glibc/libc.so.6

Verify:

file ~/.local/lib/agy-glibc/libc.so
file /data/data/com.termux/files/usr/glibc/lib/libc.so.6

libc.so in the shim should be a symlink to the real libc.so.6.

Step 4: Create the Termux Wrapper

Create ~/.local/bin/agy-va39:

#!/data/data/com.termux/files/usr/bin/sh
G=/data/data/com.termux/files/usr/glibc/lib
S=/data/data/com.termux/files/home/.local/lib/agy-glibc
unset LD_PRELOAD
unset LD_LIBRARY_PATH
export GODEBUG=netdns=go
export SSL_CERT_FILE=/data/data/com.termux/files/usr/etc/tls/cert.pem
exec /data/data/com.termux/files/usr/bin/proot \
  -b /data/data/com.termux/files/usr/etc/resolv.conf:/etc/resolv.conf \
  $G/ld-linux-aarch64.so.1 --library-path $S:$G \
  /data/data/com.termux/files/home/.local/bin/agy.va39 "$@"

Make it executable:

chmod +x ~/.local/bin/agy-va39

Why each line matters:

G points to the Termux glibc loader and libraries.
S points to the shim directory where libc.so resolves to libc.so.6.
unset LD_PRELOAD prevents Termux's Bionic preload from entering a glibc process.
unset LD_LIBRARY_PATH prevents host Termux library paths from polluting glibc resolution.
GODEBUG=netdns=go forces Go's pure DNS resolver.
SSL_CERT_FILE points TLS verification at Termux's CA bundle.
proot binds Termux's resolver config into /etc/resolv.conf for the glibc program.
--library-path $S:$G makes glibc search the shim first, then the real glibc libs.

Step 5: Add Shell Shortcuts

Make sure ~/.local/bin is in PATH. Add this near the top of ~/.bashrc if it is not already present:

export PATH="$HOME/.local/bin:$HOME/bin:$PATH"

Add these functions to ~/.bashrc:

agy() {
  hash -r
  agy-va39 "$@"
}

a() {
  hash -r
  agy-va39 "$@"
}

Reload the shell config:

source ~/.bashrc

The hash -r line clears Bash's command lookup cache. This matters when agy previously pointed at a different binary, alias, or wrapper.

Step 6: Verify the Setup

Check the wrapper directly:

agy-va39 --version

Check the shortcuts:

agy --version
a --version

Then start the interactive CLI:

agy

If agy starts but complains about login or authentication, the native binary is running. At that point the remaining issue is account/auth flow, not the Termux compatibility layer.

Updating Antigravity Later

When a new Antigravity release is installed, the official binary at ~/.local/bin/agy may be replaced. Repeat only the patch step:

python3 ~/patch_agy_va39.py ~/.local/bin/agy

Then test:

agy-va39 --version
agy --version

The wrapper usually does not need to change after an Antigravity update.

If future Antigravity releases include an official VA39-compatible Linux ARM64 build, the TCMalloc patch may no longer be needed. The Termux wrapper may still be useful for glibc, DNS, certificates, and preload cleanup.

Problems Encountered and the Working Fixes

1. TCMalloc failed before startup

Observed error:

MmapAligned() failed - unable to allocate with tag
TCMalloc assumes a 48-bit virtual address space size
FATAL ERROR: Out of memory trying to allocate internal tcmalloc data

Cause:

The binary was built with TCMalloc constants for a 48-bit ARM64 userspace VA.
Many Android/Termux devices use a 39-bit userspace VA layout.
TCMalloc generated mmap hints above the address range accepted by the kernel.

Working fix:

Patch TCMalloc's inlined address/tag constants from bit 42 to bit 35.
Patch the random mmap address mask to 39 bits.
Patch the MmapAligned upper bound from 1 << 48 to 1 << 39.
Patch tag/deallocation masks, not only RandomMmapHint.

2. SIGSYS: bad system call from faccessat2

Observed error:

SIGSYS: bad system call
syscall.faccessat2
os/exec.findExecutable

Cause:

Go used the newer faccessat2 syscall. Android seccomp blocked it.
The kernel killed the process with SIGSYS before the CLI could continue.

Working fix:

Patch the Go syscall wrapper from faccessat2 syscall 439 to older faccessat syscall 48.

This is included in patch_agy_va39.py.

3. invalid ELF header for glibc libc.so

Observed error:

error while loading shared libraries: /data/data/com.termux/files/usr/glibc/lib/libc.so: invalid ELF header

Cause:

The file named libc.so in the Termux glibc directory can be a linker script, not an ELF shared object.
The runtime loader or a dlopen path needed an actual shared object.

Working fix:

Create ~/.local/lib/agy-glibc/libc.so as a symlink to glibc's real libc.so.6.
Put that shim directory before the glibc lib directory in --library-path.

4. LIBC not found from libtermux-exec-ld-preload.so

Observed error:

version `LIBC' not found (required by /data/data/com.termux/files/usr/lib/libtermux-exec-ld-preload.so)

Cause:

Termux can set LD_PRELOAD to inject libtermux-exec-ld-preload.so.
That library is built for Android's Bionic libc, not glibc.
Preloading it into a glibc process breaks symbol/version resolution.

Working fix:

unset LD_PRELOAD
unset LD_LIBRARY_PATH

These lines are in the wrapper before invoking the glibc loader.

5. DNS looked up oauth2.googleapis.com through [::1]:53

Observed behavior:

lookup oauth2.googleapis.com on [::1]:53

Cause:

The glibc-loaded binary did not see Termux's resolver config at /etc/resolv.conf.
On this setup, /etc/resolv.conf did not exist, while Termux's resolver file existed at:
/data/data/com.termux/files/usr/etc/resolv.conf

Working fix:

Use proot to bind Termux's resolver file into /etc/resolv.conf for the launched process.
Force Go's pure resolver with GODEBUG=netdns=go.

Wrapper lines:

export GODEBUG=netdns=go
exec /data/data/com.termux/files/usr/bin/proot \
  -b /data/data/com.termux/files/usr/etc/resolv.conf:/etc/resolv.conf \
  ...

6. TLS verification failed after DNS worked

Cause:

The glibc process did not automatically know where Termux's CA certificate bundle lives.

Working fix:

export SSL_CERT_FILE=/data/data/com.termux/files/usr/etc/tls/cert.pem

Verify the file exists:

test -f /data/data/com.termux/files/usr/etc/tls/cert.pem

7. agy command still pointed at the wrong thing

Cause:

Bash caches command paths. Existing aliases or old command lookups can persist in a running shell.

Working fix:

agy() {
  hash -r
  agy-va39 "$@"
}

a() {
  hash -r
  agy-va39 "$@"
}

Quick Health Checks

Use these commands when debugging:

type agy
type a
type agy-va39
agy-va39 --version
agy --version
a --version
file ~/.local/bin/agy
file ~/.local/bin/agy.va39
file /data/data/com.termux/files/usr/glibc/lib/libc.so
file /data/data/com.termux/files/usr/glibc/lib/libc.so.6
test -f /data/data/com.termux/files/usr/etc/resolv.conf
test -f /data/data/com.termux/files/usr/etc/tls/cert.pem
curl -I https://oauth2.googleapis.com

If curl works but agy has DNS or TLS errors, check the wrapper's GODEBUG, proot bind, and SSL_CERT_FILE lines.

Known Caveats

This is still a binary patch. It is practical, but it is not as robust as an official VA39-compatible build.

The correct upstream fix would be one of these:

Build the Linux ARM64 binary with TCMALLOC_ADDRESS_BITS=39.
Provide a runtime VA-aware TCMalloc configuration.
Provide a non-TCMalloc Linux ARM64 binary.
Provide an official Android/Termux-compatible build.

The patch script is intentionally conservative. If expected instruction patterns disappear, do not assume the output is safe. Re-check the binary, update the pattern scanner, or wait for an official build.

Minimal Repeat Workflow

For future Antigravity updates, the short version is:

python3 ~/patch_agy_va39.py ~/.local/bin/agy
chmod +x ~/.local/bin/agy.va39
agy-va39 --version
agy --version

Updating Antigravity Later

When a new Antigravity release is installed, repeat only Steps 0 and 2:

curl -fsSL https://antigravity.google/cli/install.sh | bash
python3 ~/patch_agy_va39.py ~/.local/bin/agy
agy-va39 --version
agy --version

If `agy-va39` already exists and the wrapper has not been changed, you usually do not need to recreate the wrapper or shell functions.

## Updating Antigravity Later

When a new Antigravity release is installed, repeat only Steps 0 and 2:

```bash
curl -fsSL https://antigravity.google/cli/install.sh | bash
python3 ~/patch_agy_va39.py ~/.local/bin/agy
agy-va39 --version
agy --version

## Final Working Wrapper

Keep this as the known-good wrapper:

```sh
#!/data/data/com.termux/files/usr/bin/sh
G=/data/data/com.termux/files/usr/glibc/lib
S=/data/data/com.termux/files/home/.local/lib/agy-glibc
unset LD_PRELOAD
unset LD_LIBRARY_PATH
export GODEBUG=netdns=go
export SSL_CERT_FILE=/data/data/com.termux/files/usr/etc/tls/cert.pem
exec /data/data/com.termux/files/usr/bin/proot \
  -b /data/data/com.termux/files/usr/etc/resolv.conf:/etc/resolv.conf \
  $G/ld-linux-aarch64.so.1 --library-path $S:$G \
  /data/data/com.termux/files/home/.local/bin/agy.va39 "$@"
@sapereaude2014

Copy link
Copy Markdown

It's freaking awesome!

@Brajesh2022

Copy link
Copy Markdown
Author

It's freaking awesome!

❤️

@wallentx

wallentx commented May 24, 2026

Copy link
Copy Markdown

As someone maintaining termux compatible releases of codex , I salute your work

@marshallrichards

Copy link
Copy Markdown

Just tested, works great!

@wallentx

wallentx commented May 25, 2026

Copy link
Copy Markdown

I built on top of this work to set up: https://github.com/wallentx/antigravity-cli-termux/releases/tag/v1.0.2
It has atomatic releases on update detection. No wrappers, no proot, no /etc/resolve.conf requirement, and custom agy update behavior. I'm not certain on the fragility of this for future releases, but this is working fine for all I've tested.

Credits in the Readme.

Every 6 hours, a GitHub Actions workflow performs the following workflow to produce the release archive:

graph TD
    A[Upstream Release Detected] --> B[Download Linux arm64 Binary]
    B --> C[Apply VA39 Structural Memory Allocation Patches]
    C --> D[Cross-Compile Native Bionic C Bootstrapper]
    D --> E[Package Relocatable Standalone Tarball]
    E --> F[Cryptographically Sign Build via Sigstore OIDC]
Loading

1. VA39 Memory Layout Patching (TCMalloc)

Upstream utilizes Google's TCMalloc, which assumes a standard 48-bit Virtual Address (VA) space. On Android devices with custom kernels or older configurations, the user space utilizes a 39-bit VA space. Running the unmodified binary results in segmentation faults or fatal allocation failures.
We run a dedicated Python patching process that:

  • Rewrites specific bitmask and ubfx (unsigned bitfield extract) instructions.
  • Adjusts page-alignment logic and mmap parameters.
  • Rewrites low-level library wrappers (faccessat2) to guarantee absolute compatibility with 39-bit systems.

2. Relocatable Bionic C Bootstrapper

Standard Termux runs under the Android Bionic libc environment, injecting specific preloads (LD_PRELOAD=/data/.../libtermux-exec.so) to intercept calls. However, because our patched binary is built under glibc, loading it directly causes immediate crashes (invalid ELF header) when the glibc dynamic linker processes Bionic preloads.
To circumvent this, we compile a native Bionic C bootstrapper (bin/agy):

  • Dynamic Resolution: Resolves its own folder at runtime using /proc/self/exe via readlink, enabling the package to be extracted and executed in any directory without wrappers.
  • Environment Cleansing: Unsets conflicting environment variables (LD_PRELOAD, LD_LIBRARY_PATH) before executing the loader.
  • Redirection: Configures the native Termux CA bundle (SSL_CERT_FILE) and DNS routing (GODEBUG=netdns=cgo), then passes execution cleanly to the glibc loader.

3. In-Place Self-Updating

The C bootstrapper intercepts the update subcommand and queries this fork's GitHub Releases API, providing a seamless in-place update mechanism that updates both the patched engine and itself without needing complex wrappers or manually executing curl commands.

@Brajesh2022

Brajesh2022 commented May 25, 2026

Copy link
Copy Markdown
Author

UPDATE: Incredible work by @wallentx! He took this guide and built a dedicated standalone releases repository for Termux users to automate the binary assets.

When I saw his repo, it had separate build releases and their respective commands. I thought, why not just make one single installer that can pull the latest release automatically? So, I built exactly that to completely close the loop.

I’ve submitted the fully automated, standalone installer script as a Pull Request to his repository! While we wait for the PR to be merged into his main repo, the installer is fully live and safe to test right now using my repository branch.

Skip the manual patching entirely and run it with this single command:

curl -fsSL https://raw.githubusercontent.com/Brajesh2022/antigravity-cli-termux/dev/install.sh | bash

What this installer handles for you automatically:

  • Detects your Termux environment and aarch64 architecture.
  • Cleans up any broken or previous installations automatically.
  • Downloads the latest release payload
  • Auto-Failover: If the standard binary throws a Bus Error, the script automatically catches it, logs a warning, swaps in the va39 patch binary seamlessly, and verifies the engine.

Massive shoutout to @wallentx for setting up the automated release pipeline. Give the command a run and let me know how it works for you! 🚀

@Manamama

Copy link
Copy Markdown

FYI:

python is already the newest version (3.13.13-1).
proot is already the newest version (5.1.107.72).
curl is already the newest version (8.20.0).
ca-certificates is already the newest version (1:2026.03.19).
0 upgraded, 0 newly installed, 0 to remove and 7 not upgraded.
~/Downloads $ test -x /data/data/com.termux/files/usr/glibc/lib/ld-linux-aarch64.so.1
test -f /data/data/com.termux/files/usr/glibc/lib/libc.so.6
~/Downloads $ 
~/Downloads $ 
~/Downloads $ ll /data/data/com.termux/files/usr/glibc/lib/libc.so.6
.rwx------. u0_a278 u0_a278 2296648  Mon Feb  9 01:55:40 2026  /data/data/com.termux/files/usr/glibc/lib/libc.so.6*
~/Downloads $ test -x ~/.local/bin/agy
file ~/.local/bin/agy
/data/data/com.termux/files/home/.local/bin/agy: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[md5/uuid]=8b410546736cc4377246c571c97eff24, stripped
~/Downloads $ 

but:

~/Downloads $ wget  https://raw.githubusercontent.com/wallentx/antigravity-cli-termux/dev/install.sh
--2026-05-26 10:42:52--  https://raw.githubusercontent.com/wallentx/antigravity-cli-termux/dev/install.sh
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.110.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13543 (13K) [text/plain]
Saving to: ‘install.sh.2’

install.sh.2                                    100%[=====================================================================================================>]  13.23K  --.-KB/s    in 0.001s  

2026-05-26 10:42:52 (18.3 MB/s) - ‘install.sh.2’ saved [13543/13543]

~/Downloads $ bash install.sh.2

                        
                        
         ▄▄▄▄▄▄             Antigravity Termux
        ▄▄▄▄▄▄▄▄            Standalone Installer
       ▄▄▄▄▄▄▄▄▄            ────────────────────
       ▄▄▄▄▄▄▄▄▄▄           Target:  Termux
      ▄▄▄▄▄▄▄▄▄▄▄▄          Arch:    aarch64
      ▄▄▄      ▄▄▄          Status:  Online
     ▄▄▄        ▄▄▄     
   ▄▄▄            ▄▄▄   
                        
                        


────────────────────────────────────────
 [OK] Environment: Termux aarch64
 [..] [█████████████████████████████████████████████████████░░░░░░░]  88%  41.3M / 46.7M
 [OK] [████████████████████████████████████████████████████████████] 100%  46.7M / 46.7M
 [OK] Extracting binaries...
 [OK] Binary found

 [ERR] Binaries failed to execute locally. Check dependencies.
For manual patching and installation:
https://gist.github.com/Brajesh2022/e42160d29b55417db6c18c52dd1d6d37

ref:

u0_a278@localhost
-----------------
OS: Android REL 11 aarch64
Host: realme 8 (RMX3085)
Kernel: Linux 4.14.186+
Uptime: 3 days, 18 hours, 34 mins
Packages: 921 (dpkg), 142 (pacman)
Shell: bash 5.3.9
DE: RMX3085_11_A.26

@Brajesh2022

Brajesh2022 commented May 26, 2026

Copy link
Copy Markdown
Author

@Manamama
Your kernel (4.14) is too old for the pre-patched binary. The automated installer can't fix kernel-level syscall limitations.
Try the manual setup guide instead:

https://gist.github.com/Brajesh2022/e42160d29b55417db6c18c52dd1d6d37/raw

Paste it into any AI agent (Gemini CLI, Claude etc) and it will handle the setup for your specific device.

@Botspot

Botspot commented May 28, 2026

Copy link
Copy Markdown

Interesting. How future-proof is this compared to an implementation which runs the unmodified 48-bit binary in a QEMU KVM? See: https://github.com/Botspot/antigravity-48bit-workaround

@hunterice5

Copy link
Copy Markdown

แจ่ม ผมให้ Gemini cli ลง antigravity cli

@lionc2240

Copy link
Copy Markdown

Thanks. But first, maybe we need to install this firstly:

pkg update
pkg install glibc-repo
pkg install glibc
test -f /data/data/com.termux/files/usr/glibc/lib/libc.so.6 && echo "Found!"

@lionc2240

Copy link
Copy Markdown

FYI:

python is already the newest version (3.13.13-1).
proot is already the newest version (5.1.107.72).
curl is already the newest version (8.20.0).
ca-certificates is already the newest version (1:2026.03.19).
0 upgraded, 0 newly installed, 0 to remove and 7 not upgraded.
~/Downloads $ test -x /data/data/com.termux/files/usr/glibc/lib/ld-linux-aarch64.so.1
test -f /data/data/com.termux/files/usr/glibc/lib/libc.so.6
~/Downloads $ 
~/Downloads $ 
~/Downloads $ ll /data/data/com.termux/files/usr/glibc/lib/libc.so.6
.rwx------. u0_a278 u0_a278 2296648  Mon Feb  9 01:55:40 2026  /data/data/com.termux/files/usr/glibc/lib/libc.so.6*
~/Downloads $ test -x ~/.local/bin/agy
file ~/.local/bin/agy
/data/data/com.termux/files/home/.local/bin/agy: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[md5/uuid]=8b410546736cc4377246c571c97eff24, stripped
~/Downloads $ 

but:

~/Downloads $ wget  https://raw.githubusercontent.com/wallentx/antigravity-cli-termux/dev/install.sh
--2026-05-26 10:42:52--  https://raw.githubusercontent.com/wallentx/antigravity-cli-termux/dev/install.sh
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.110.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13543 (13K) [text/plain]
Saving to: ‘install.sh.2’

install.sh.2                                    100%[=====================================================================================================>]  13.23K  --.-KB/s    in 0.001s  

2026-05-26 10:42:52 (18.3 MB/s) - ‘install.sh.2’ saved [13543/13543]

~/Downloads $ bash install.sh.2

                        
                        
         ▄▄▄▄▄▄             Antigravity Termux
        ▄▄▄▄▄▄▄▄            Standalone Installer
       ▄▄▄▄▄▄▄▄▄            ────────────────────
       ▄▄▄▄▄▄▄▄▄▄           Target:  Termux
      ▄▄▄▄▄▄▄▄▄▄▄▄          Arch:    aarch64
      ▄▄▄      ▄▄▄          Status:  Online
     ▄▄▄        ▄▄▄     
   ▄▄▄            ▄▄▄   
                        
                        


────────────────────────────────────────
 [OK] Environment: Termux aarch64
 [..] [█████████████████████████████████████████████████████░░░░░░░]  88%  41.3M / 46.7M
 [OK] [████████████████████████████████████████████████████████████] 100%  46.7M / 46.7M
 [OK] Extracting binaries...
 [OK] Binary found

 [ERR] Binaries failed to execute locally. Check dependencies.
For manual patching and installation:
https://gist.github.com/Brajesh2022/e42160d29b55417db6c18c52dd1d6d37

ref:

u0_a278@localhost
-----------------
OS: Android REL 11 aarch64
Host: realme 8 (RMX3085)
Kernel: Linux 4.14.186+
Uptime: 3 days, 18 hours, 34 mins
Packages: 921 (dpkg), 142 (pacman)
Shell: bash 5.3.9
DE: RMX3085_11_A.26

same here:

~ $ curl -fsSL https://raw.githubusercontent.com/wallentx/antigravity-cli-termux/dev/install.sh | bash



         ▄▄▄▄▄▄             Antigravity Termux
        ▄▄▄▄▄▄▄▄            Standalone Installer
       ▄▄▄▄▄▄▄▄▄            ────────────────────
       ▄▄▄▄▄▄▄▄▄▄           Target:  Termux
      ▄▄▄▄▄▄▄▄▄▄▄▄          Arch:    aarch64
      ▄▄▄      ▄▄▄          Status:  Online
     ▄▄▄        ▄▄▄
   ▄▄▄            ▄▄▄




────────────────────────────────────────
 [OK] Environment: termux (aarch64)
 [..] [░░░░░░░░░░░░░░░░░░░░░░]   0%   0.0M / 46.8 [..] [░░░░░░░░░░░░░░░░░░░░░░]   0%   0.0M / 46.8 [..] [░░░░░░░░░░░░░░░░░░░░░░]   0%   0.0M / 46.8 [..] [░░░░░░░░░░░░░░░░░░░░░░]   0%   0.1M / 46.8 [..] [█░░░░░░░░░░░░░░░░░░░░░]   4%   2.2M / 46.8 [..] [████░░░░░░░░░░░░░░░░░░]  20%   9.8M / 46.8 [..] [███████░░░░░░░░░░░░░░░]  35%  16.7M / 46.8 [..] [███████████░░░░░░░░░░░]  50%  23.4M / 46.8 [..] [██████████████░░░░░░░░]  64%  30.3M / 46.8 [..] [█████████████████░░░░░]  81%  38.1M / 46.8 [..] [█████████████████████░]  96%  45.2M / 46.8 [OK] [██████████████████████] 100%  46.8M / 46.8M
 [OK] Extracting binaries...
 [OK] Binary found

 [ERR] Binaries failed to execute locally. Check dependencies.
For manual patching and installation:
https://gist.github.com/Brajesh2022/e42160d29b55417db6c18c52dd1d6d37

When attempting to run the patched or wrapped agy binary on a Samsung Galaxy S10e, the execution immediately crashes with a SIGILL (Signal 4 / Illegal Instruction) triggered by Go's fast-fail mechanism. The Go runtime detects that the official upstream binary was compiled requiring the rcpc (Release Consistent Processor Consistent) extension, which is not supported by this device's processor.

~ $ agy --version
FATAL ERROR: This binary was compiled with rcpc enabled, but this feature is not available on this processor (go/sigill-fail-fast).
proot info: vpid 1: terminated with signal 4

I opened an issue at: wallentx/antigravity-cli-termux#9 (comment)

@Brajesh2022

Copy link
Copy Markdown
Author

@lionc2240 Bro, I already fixed this issue, but the repository owner is not accepting, merging, or reviewing my PR. Until he reviews the PR, you can use the following command from my fork; it will solve your issue.

curl -fsSL https://raw.githubusercontent.com/Brajesh2022/antigravity-cli-termux/fix-auto-repair/install.sh | bash

@lionc2240

Copy link
Copy Markdown

I built on top of this work to set up: https://github.com/wallentx/antigravity-cli-termux/releases/tag/v1.0.2 It has atomatic releases on update detection. No wrappers, no proot, no /etc/resolve.conf requirement, and custom agy update behavior. I'm not certain on the fragility of this for future releases, but this is working fine for all I've tested.

Credits in the Readme.

Every 6 hours, a GitHub Actions workflow performs the following workflow to produce the release archive:

graph TD
    A[Upstream Release Detected] --> B[Download Linux arm64 Binary]
    B --> C[Apply VA39 Structural Memory Allocation Patches]
    C --> D[Cross-Compile Native Bionic C Bootstrapper]
    D --> E[Package Relocatable Standalone Tarball]
    E --> F[Cryptographically Sign Build via Sigstore OIDC]
Loading

1. VA39 Memory Layout Patching (TCMalloc)

Upstream utilizes Google's TCMalloc, which assumes a standard 48-bit Virtual Address (VA) space. On Android devices with custom kernels or older configurations, the user space utilizes a 39-bit VA space. Running the unmodified binary results in segmentation faults or fatal allocation failures. We run a dedicated Python patching process that:

  • Rewrites specific bitmask and ubfx (unsigned bitfield extract) instructions.
  • Adjusts page-alignment logic and mmap parameters.
  • Rewrites low-level library wrappers (faccessat2) to guarantee absolute compatibility with 39-bit systems.

2. Relocatable Bionic C Bootstrapper

Standard Termux runs under the Android Bionic libc environment, injecting specific preloads (LD_PRELOAD=/data/.../libtermux-exec.so) to intercept calls. However, because our patched binary is built under glibc, loading it directly causes immediate crashes (invalid ELF header) when the glibc dynamic linker processes Bionic preloads. To circumvent this, we compile a native Bionic C bootstrapper (bin/agy):

  • Dynamic Resolution: Resolves its own folder at runtime using /proc/self/exe via readlink, enabling the package to be extracted and executed in any directory without wrappers.
  • Environment Cleansing: Unsets conflicting environment variables (LD_PRELOAD, LD_LIBRARY_PATH) before executing the loader.
  • Redirection: Configures the native Termux CA bundle (SSL_CERT_FILE) and DNS routing (GODEBUG=netdns=cgo), then passes execution cleanly to the glibc loader.

3. In-Place Self-Updating

The C bootstrapper intercepts the update subcommand and queries this fork's GitHub Releases API, providing a seamless in-place update mechanism that updates both the patched engine and itself without needing complex wrappers or manually executing curl commands.

~ $ curl -fsSLO https://github.com/wallentx/antigravity-cli-termux/releases/download/v1.0.2/antigravity-termux-standalone.tar.gz
~ $ tar -xzf antigravity-termux-standalone.tar.gz
~ $ ./bin/agy --help
FATAL ERROR: This binary was compiled with rcpc enabled, but this feature is not available on this processor (go/sigill-fail-fast).
Illegal instruction        ./bin/agy --help
~ $

@Brajesh2022

Copy link
Copy Markdown
Author

@lionc2240 Bro, have you tried using this new command?

curl -fsSL https://raw.githubusercontent.com/Brajesh2022/antigravity-cli-termux/fix-auto-repair/install.sh | bash

@lionc2240

Copy link
Copy Markdown

@lionc2240 Bro, have you tried using this new command?

curl -fsSL https://raw.githubusercontent.com/Brajesh2022/antigravity-cli-termux/fix-auto-repair/install.sh | bash

I ran it, this is the output:

~ $ curl -fsSL https://raw.githubusercontent.com/Brajesh2022/antigravity-cli-termux/fix-auto-repair/install.sh | bash



         ▄▄▄▄▄▄             Antigravity Termux
        ▄▄▄▄▄▄▄▄            Standalone Installer
       ▄▄▄▄▄▄▄▄▄            ────────────────────
       ▄▄▄▄▄▄▄▄▄▄           Target:  Termux
      ▄▄▄▄▄▄▄▄▄▄▄▄          Arch:    aarch64
      ▄▄▄      ▄▄▄          Status:  Online
     ▄▄▄        ▄▄▄
   ▄▄▄            ▄▄▄




────────────────────────────────────────
 [OK] Environment: termux (aarch64)
 [OK] [██████████████████████] 100%  46.8M / 46.8M
 [OK] Extracting binaries...
 [OK] Binary found
 [..] Binary failed. Attempting dependency repair...
 [..] Repair failed. Attempting full package update...

 [ERR] Binaries failed to execute locally. Check dependencies.
For manual patching and installation:
https://gist.github.com/Brajesh2022/e42160d29b55417db6c18c52dd1d6d37

@Brajesh2022

Copy link
Copy Markdown
Author

@lionc2240 Can you test it again? I tried fixing it, and I think it should work now.

@lionc2240

Copy link
Copy Markdown

@Brajesh2022 I tried again. It occurs the same output

@Brajesh2022

Copy link
Copy Markdown
Author

@lionc2240 Can you please confirm whether you are still encountering the following error
[..] Binary failed. Attempting dependency repair...
[..] Repair failed. Attempting full package update...

and whether you have the latest Termux installed from GitHub rather than from the Play Store? If possible, could you clear your Termux data and try again?

@kaliajasih

Copy link
Copy Markdown

~ $ curl -fsSL https://raw.githubusercontent.com/Brajesh2022/antigravity-cli-termux/fix-auto-repair/install.sh | bash

     ▄▄▄▄▄▄             Antigravity Termux
    ▄▄▄▄▄▄▄▄            Standalone Installer
   ▄▄▄▄▄▄▄▄▄            ────────────────────
   ▄▄▄▄▄▄▄▄▄▄           Target:  Termux
  ▄▄▄▄▄▄▄▄▄▄▄▄          Arch:    aarch64
  ▄▄▄      ▄▄▄          Status:  Online
 ▄▄▄        ▄▄▄

▄▄▄ ▄▄▄

────────────────────────────────────────
[OK] Environment: termux (aarch64)
[OK] [██████████████████████] 100% 46.8M / 46.8M
[OK] Extracting binaries...
[OK] Binary found
[..] Binary failed. Attempting dependency repair...
[..] Repair failed. Attempting full package update...

[ERR] Binaries failed to execute locally. Check dependencies.
For manual patching and installation:
https://gist.github.com/Brajesh2022/e42160d29b55417db6c18c52dd1d6d37

@malinovskayakseniya163-ux

Copy link
Copy Markdown

Hello everyone! Can someone please help me with this error:
[ERR] Missing Termux glibc loader: /data/data/com.termux/files/usr/glibc/lib/ld-linux-aarch64.so.1
You may need to install the glibc-repo and glibc packages, then rerun this installer.

I really can't understand what I should do, if you know how to fix it in termux please say me. Thanks for future answers!❤️

@Spectra010s

Copy link
Copy Markdown

@lionc2240 Bro, have you tried using this new command?

curl -fsSL https://raw.githubusercontent.com/Brajesh2022/antigravity-cli-termux/fix-auto-repair/install.sh | bash

I ran this but still encountered this error

[OK] [████████████████████████████] 100% 40.9M / 40.9M
[ERR] Extracting binaries...

[ERR] Installation failed or was cancelled.
For manual patching and installation:
https://gist.github.com/Brajesh2022/e42160d29b55417db6c18c52dd1d6d37

@erlonbie

Copy link
Copy Markdown

Hello everyone! Can someone please help me with this error: [ERR] Missing Termux glibc loader: /data/data/com.termux/files/usr/glibc/lib/ld-linux-aarch64.so.1 You may need to install the glibc-repo and glibc packages, then rerun this installer.

I really can't understand what I should do, if you know how to fix it in termux please say me. Thanks for future answers!❤️

I'm facing the same issue

@thrdchld

thrdchld commented Jun 22, 2026

Copy link
Copy Markdown

if you have older cpu like mine Snapdragon 660 that doesn't supported by antigravity 2.0, you have to use proot to get antigravity-cli working, check here https://github.com/krecod/agy-termux-lse

I don't know why google make this requirment.
I almost sell my Xiaomi Pad 4 because of this issue 🤣
thanks a lot @krecod

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment