Running Claude Code on Android via proot-distro

Published on 7/21/2026

Running Claude Code on Android via proot-distro

Anthropic doesn’t support Android. But it still runs, through an Ubuntu layer inside proot.

Why you can’t just install it directly

Claude Code is a linux-arm64 binary dynamically linked against glibc. Termux runs on Android’s bionic libc. Installing directly via npm gets you:

Unsupported platform: android arm64

The workaround: build an Ubuntu rootfs inside Termux using proot-distro, which has real glibc, then install Claude Code inside it.

Requirements

Installation

In Termux:

pkg update -y && pkg upgrade -y
pkg install proot-distro -y
proot-distro install ubuntu
proot-distro login ubuntu

In Ubuntu:

apt update && apt install -y curl git
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
npm install -g @anthropic-ai/claude-code
claude

The first time you run claude it will open a browser login flow. Use your existing Claude account, no API key needed.

A handy alias

Add this to ~/.bashrc in Termux, not in Ubuntu:

alias cc='proot-distro login ubuntu -- bash -lc "cd ~/projects && claude"'

From then on, just type cc.

A few things worth knowing

Root inside proot is fake root. proot is unprivileged and simulates UID 0 via ptrace. Everything still runs under the Termux app’s UID. Creating a user + sudo inside doesn’t add any protection layer, just extra hassle.

Android will kill the process when you switch apps. Enable the wake-lock from Termux’s notification. Add tmux inside the container if you want the session to survive longer.

Keep repos inside the container. I/O through proot is slow, and git pointing outside often throws confusing permission errors.

chmod 600 ~/.claude*. Credentials live inside Termux’s storage.

Notifications when Claude needs attention

Claude Code has a Notification hook (when it needs permission/input) and a Stop hook (when it’s done). Wire termux-notification into those, and tapping the notification brings you back to Termux.

Install (in Termux, not Ubuntu):

pkg install termux-api -y

And also install the Termux:API app from F-Droid — the termux-api package is just a script that calls out to that app via intent; without the app, the command won’t run.

Tapping the notification doesn’t automatically reopen Termux — this is the part that eats the most time. am start called from the notification’s action runs inside Termux:API’s background service, and Android 10+ blocks activity-starts from the background by default (the Background Activity Launch restriction). Fix it by granting Termux the overlay permission:

Settings → Apps → Termux → Advanced → Display over other apps → Allow

Without this permission, am start runs “successfully” (exit 0) but doesn’t bring the app to the foreground — easy to mistake for a command syntax error.

Use the full path for the command, since termux-notification’s action runs in its own shell without $PATH:

termux-notification --title "Claude Code" --content "..." \
  --action "/data/data/com.termux/files/usr/bin/am start --user 0 -n com.termux/com.termux.app.TermuxActivity"

--user 0 is required — without it, Termux’s am (a self-written reimplementation, not Android’s real am) throws a SecurityException due to missing INTERACT_ACROSS_USERS_FULL.

Wire this into ~/.claude/settings.json inside Ubuntu:

{
  "hooks": {
    "Notification": [
      { "hooks": [ { "type": "command",
        "command": "jq -r '.message // .title // \"Claude needs your attention\"' | { read -r msg; termux-notification --title \"Claude Code\" --content \"$msg\" --action \"/data/data/com.termux/files/usr/bin/am start --user 0 -n com.termux/com.termux.app.TermuxActivity\" --id 42; } 2>/dev/null || true" } ] }
    ],
    "Stop": [
      { "hooks": [ { "type": "command",
        "command": "termux-notification --title \"Claude Code\" --content \"Claude stopped — check the session\" --action \"/data/data/com.termux/files/usr/bin/am start --user 0 -n com.termux/com.termux.app.TermuxActivity\" --id 42 2>/dev/null || true" } ] }
    ]
  }
}

After editing settings.json, open /hooks once (or start a new claude session) so it reloads — editing the file while a session is running doesn’t apply automatically.

Running several Termux tabs at once means the notification won’t automatically pick the right tab. am start only brings the Termux app to the front, showing whichever tab is currently “current” — Termux doesn’t expose any intent for an outside app to select a specific existing session by name/ID (checked the RUN_COMMAND wiki and source; the session-action part only applies when creating a new session). If you want control: merge your projects into a single tmux server (one named window per project), keep exactly one Termux tab attached to it, and have the notification’s action run tmux select-window -t <name> before am start. This part hasn’t been thoroughly verified yet.

Limitations

This is a workaround, not official support. A Claude Code update could break the setup at any time, and you’re on your own to fix it. Phone RAM is a real bottleneck with large codebases.

In exchange: a full dev environment in your pocket.