Hardcoded /tmp/claude paths break on Termux (Android)
Open 💬 16 comments Opened Dec 29, 2025 by renxida
Summary
Claude Code hardcodes /tmp/claude/ paths in multiple places, which fails on Termux (Android terminal emulator) where /tmp is not accessible due to Android's permission model.
Environment
- Platform: Termux on Android
- Claude Code version: latest npm install
Problem
The bundled cli.js contains hardcoded references like:
"/tmp/claude"for sandbox TMPDIR"/tmp/claude_cli_latest_screenshot.png"for screenshots"/tmp/claude/cwd-..."for working directory tracking- Various other
/tmp/claude/paths
On Termux, /tmp returns "Permission denied" because Android restricts access to system paths. Termux provides $TMPDIR pointing to /data/data/com.termux/files/usr/tmp which is the correct location.
Expected Behavior
Claude Code should respect the TMPDIR environment variable (or os.tmpdir() in Node.js) instead of hardcoding /tmp/claude.
Workaround
Currently patching cli.js with:
sed -i "s|/tmp/claude|/data/data/com.termux/files/usr/tmp/claude|g" cli.js
But this breaks on updates.
Suggested Fix
Replace hardcoded /tmp/claude with something like:
const CLAUDE_TMP = process.env.TMPDIR
? path.join(process.env.TMPDIR, 'claude')
: '/tmp/claude';
Or use Node's os.tmpdir() which already respects TMPDIR.
16 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
See #15628 for comprehensive root cause analysis identifying 6 distinct hardcoded
/tmppatterns in cli.js, including the critical sandbox TMPDIR override. The fix requires usingos.tmpdir()instead of hardcoded paths.Additional Real-World Impact Report
Environment: Termux on Android (claude-code CLI)
Date: 2026-01-12
Issue Confirmed
Can confirm hardcoded
/tmp/claude/paths completely block SSH command execution on Termux:Reproduction Steps
``
bash
``gcloud compute ssh instance --zone=us-central1-a --command='...'
/tmp/claude/mkdirImpact
Suggested Fix
Replace hardcoded
/tmp/claudewith:This respects Termux's $TMPDIR=/data/data/com.termux/files/usr/tmp and fixes the issue universally.
Testing Environment Available
Can provide detailed logs/debugging if needed. Running c4d-highcpu-4 instance on GCP currently - unable to check status due to this bug.
Suggested Solution Confirmed ✅
The fix proposed in this issue is correct. Using
process.env.TMPDIRor Node'sos.tmpdir()would resolve this.Tested workaround (partial): Setting
export TMPDIR="\$HOME/.cache/tmp"in.bashrcworks for direct commands but does NOT fix background agents or long-running operations - Claude Code must be respecting hardcoded paths internally.Recommendation: Claude Code should replace all hardcoded
/tmp/claudereferences with:This would:
Even correctly determining the valid system TMPDIR is not sufficient to avoid clashes between different instances of Claude, all making the same type of temporary files.
So within the selected temp dir, Claude should make a session-based subdir
And maybe
$XDG_RUNTIME_DIR(if set should) be the tempdir in which the session-based subdir is created, not simplyrequire('os').tmpdir()If this should be a fresh report, rather than direction on this fix, please forgive my igorance and give me a nudge.
Status Update: Verified on Latest Claude Code v2.1.11
Test Environment
Findings
PARTIAL FIX CONFIRMED:
/tmp/claudeerrorsEACCES: permission denied, mkdir '/tmp/claude/-data-data-com-termux-files-home/tasks'Test Results
Test 1: Direct Bash Commands
Result: ✅ Works fine, no path errors
Test 2: Agent Spawning (Explore)
Result: ❌
EACCES: permission denied, mkdir '/tmp/claude/-data-data-com-termux-files-home/tasks'Test 3: Agent Spawning (General-purpose)
Result: ❌ Same error as Test 2
Root Cause
The update fixed direct command execution but did NOT fix the task spawning infrastructure. Agents require
/tmp/claude/{workspace-hash}/tasks/directory creation, which fails on Termux where/tmplacks write permissions for non-root users.Recommended Fix
Implement environment variable detection as suggested in this issue:
Workaround (Current)
Users can work around agent failures by:
TMPDIR=~/tmpbefore launching Claude CodeBlocking Issues
This significantly impacts Termux/Android accessibility despite the Bash command fix.
export CLAUDE_CODE_TMPDIR=$HOME/tmp/claude
source ~/.bashrc
@HEYANGLI23 It worked thanks 🙏
Edit: its inconsistent. Sometimes still getting the same spawn errors.
More importantly this change broke my slash commands. Claude cant recognize them. Even though I ask claude to debug, it checks and says everything looks right.
Anyway. An official and proper fix needed from claude team.
Confirming: Hardcoded /tmp paths ignore all environment variables
Adding another data point - I have both suggested workarounds configured:
Neither works. Claude Code still attempts to create
/tmp/claude/-data-data-com-termux-files-home/tasks.System Info
The Fix Needed
As you correctly identified, the fix should be:
Or simply use Node's
os.tmpdir()which already respects TMPDIR.Current Status
Could the team prioritize this fix? It's a one-line change that would unblock all Termux/Android users.
---
Tested on Termux with TalkBack accessibility
Working Workaround: Direct cli.js Patching (No proot overhead)
For anyone hitting this on Termux, here's a faster alternative to the proot bind mount:
1. Patch cli.js directly
2. Create a repatch script (survives updates)
Run
claude-patchafter everynpm update -g @anthropic-ai/claude-code.Why not proot?
proot intercepts every syscall via ptrace → 10-50% performance overhead. Direct patching has zero overhead.
Environment
+1 for fixing this upstream with
os.tmpdir(). It's a one-line fix that would help all Termux/Android/HPC users.Workaround: https://github.com/anthropics/claude-code/pull/31701#issuecomment-4017294725
Adding an Android 16 specific data point — kernel 6.12, Samsung Galaxy S26 Ultra, One UI 8.5.
On Android 16 the proot-distro approach is completely broken — the kernel's updated security model breaks stdout file descriptor binding inside guest distributions. Processes launch but hang or produce no output. This is not a config issue.
Working solution on Android 16: native Termux install, skip proot-distro entirely, use proot bind mount only for /tmp at runtime.
Node v25+ required — v24 hangs on ARM64 under Termux on this kernel.
Hoping the upstream fix in #31701 lands soon — that's the real solution for everyone.
Full Android 16 setup guide and troubleshooting reference: https://github.com/ferrumclaudepilgrim/claude-code-android
Correction to my earlier comment: I previously stated proot-distro was "completely broken" on Android 16. That was wrong.
The issue was a TCGETS2 ioctl bug in proot that was fixed in version 5.1.107-66 (October 2025). Current proot versions (5.1.107-70+) handle guest distros correctly on kernel 6.12. We verified this on three devices — Samsung Galaxy S26 Ultra, Google Pixel 10 Pro, and Samsung Galaxy S23+.
Two working approaches verified on real hardware:
Path A (native Termux):
proot -b $PREFIX/tmp:/tmp claude— binds a writable tmp directory at the syscall level. This resolves the EACCES for basic operation AND subagent task directories (/tmp/claude/{hash}/tasks/). Verified working with subagents on Android 16.Path B (proot-distro Ubuntu): Install Ubuntu via proot-distro, then use Anthropic's native installer (
curl -fsSL https://claude.ai/install.sh | bash). No /tmp workaround needed — Ubuntu has native /tmp. No ripgrep symlink needed. No Node.js version management needed.CLAUDE_CODE_TMPDIRis also documented as an alternative for users who prefer not to use proot.Full guide with troubleshooting, verification test suite, and three-device compatibility data: https://github.com/ferrumclaudepilgrim/claude-code-android
Just tried it with npm install and it worked. No env variable or proot, maybe because i am using glibc buit nodejs and termux glibc userland is my default. I also permennatly unset LD_PRELOAD.
Simple workaround using
termux-chroot:For those who don't want to mess with
proot -bbind mounts or environment variables, the simplest fix is:This gives you a proper
/tmpdirectory (and standard Linux filesystem layout) inside the chroot. Then just launch Claude Code as normal. The Bash tool works fine after this — no need forCLAUDE_CODE_TMPDIRor manual symlinks.Tested on Android with kernel 4.19 (aarch64).
Follow-up: Confirmed that subagents (Task tool) also work correctly with the
termux-chrootapproach on Claude Code v2.1.112. The/tmp/claude/{hash}/tasks/directory creation succeeds inside the chroot, so background tasks and subagent invocations run withoutEACCESerrors.Setup recap for anyone hitting this:
Tested with Explore subagent and Bash tool — both functional.