[BUG] Termux: Background tasks fail with malformed path - HOME sanitization breaks on deep paths

Resolved 💬 7 comments Opened Dec 30, 2025 by salviz Closed Mar 2, 2026

Claude Code Termux Issue: EACCES Permission Denied with Malformed Tasks Path

Summary

Claude Code fails on Termux (Android ARM64) with a permission error and malformed file path when running background tasks. The path construction naively sanitizes the HOME directory by replacing slashes with dashes, creating an invalid path.

Error Message

Error: EACCES: permission denied, mkdir '/tmp/claude/-data-data-com-termux-files-home/tasks'
    at mkdirSync (node:fs:1325:26)
    at ZdB (file:///data/data/com.termux/files/usr/lib/node_modules/@anthropic-ai/claude-code/cli.js:1018:8797)
    at bu (file:///data/data/com.termux/files/usr/lib/node_modules/@anthropic-ai/claude-code/cli.js:1018:9430)
    at Object.spawn (file:///data/data/com.termux/files/usr/bin/node:25.2.1)

Environment

| Variable | Value |
|----------|-------|
| Platform | Termux on Android ARM64 |
| OS | Linux 5.15.178-android13 |
| Node.js | v25.2.1 |
| NPM | 11.6.2 |
| Claude Code | 2.0.76 (latest) |
| Shell | /bin/bash (Termux) |
| HOME | /data/data/com.termux/files/home |
| PWD | /data/data/com.termux/files/home |
| TMPDIR | /data/data/com.termux/files/usr/tmp |

Reproduction Steps

  1. Install Claude Code in Termux
  2. Run any command with run_in_background: true
  3. Or execute a background shell task via Bash tool

Expected: Background task created successfully in /tmp/claude/tasks/

Actual: EACCES: permission denied with malformed path

Root Cause Analysis

Claude Code constructs the tasks directory path by sanitizing the HOME environment variable:

Input:  /data/data/com.termux/files/home
Logic:  Replace all "/" with "-"
Result: -data-data-com-termux-files-home
Path:   /tmp/claude/-data-data-com-termux-files-home/tasks

This naive sanitization works on standard Linux systems (/home/user-home-user) but fails on Termux's deeply nested path structure.

Why This Happens

The code likely attempts to create a unique, filesystem-safe directory name from the HOME path to isolate tasks per user. The simple replace(/\//g, '-') approach:

  • ✅ Works: /home/alice/tmp/claude/-home-alice/
  • ❌ Fails: /data/data/com.termux/files/home/tmp/claude/-data-data-com-termux-files-home/

Additionally, /tmp in Termux has restrictive permissions, making directory creation challenging.

Impact

  • Severity: High
  • Platforms Affected: Termux (Android)
  • Features Blocked: Background task execution
  • Users Affected: Any Claude Code user on Termux

Recommended Fixes

Option 1: Use XDG Base Directory (Recommended)

Follow XDG Base Directory Specification:

const path = require('path');
const tasksDir = path.join(
  process.env.XDG_CACHE_HOME || path.join(process.env.HOME, '.cache'),
  'claude',
  'tasks'
);
// Result: ~/.cache/claude/tasks

Advantages:

  • ✅ Cross-platform compatible (Linux, macOS, Windows, Termux)
  • ✅ Follows standard conventions
  • ✅ Works with deeply nested paths
  • ✅ Persists between sessions
  • ✅ No special permissions needed

Option 2: Use Hash Instead of Path Replacement

const crypto = require('crypto');
const homehash = crypto
  .createHash('sha256')
  .update(process.env.HOME)
  .digest('hex')
  .substring(0, 12);
const tasksDir = path.join(os.tmpdir(), 'claude', homehash, 'tasks');
// Result: /tmp/claude/a1b2c3d4e5f6/tasks

Advantages:

  • ✅ Always produces valid directory names
  • ✅ Still uses /tmp for temporary data
  • ✅ Unique per user

Option 3: Respect $TMPDIR

const tasksDir = path.join(process.env.TMPDIR || '/tmp', 'claude', 'tasks');

Advantages:

  • ✅ Respects user's temporary directory preference
  • ✅ Simple fix

Workaround for Users (Immediate)

Until this is fixed, Termux users can work around the issue by setting TMPDIR:

# Create user temp directory
mkdir -p ~/tmp

# Run Claude Code with custom TMPDIR
TMPDIR=~/tmp claude-code [command]

# Or add to ~/.bashrc
export TMPDIR=~/tmp

Additional Notes

  • This issue is specific to the path construction logic in Claude Code's task spawning system
  • The error is reproducible consistently on Termux with any background operation
  • The /tmp/claude/ directory creation is the first point of failure; permission handling could also be improved

Related Issues

None found in GitHub issue tracker (searched: "EACCES", "tmp/claude", "Termux", "permission denied")

Suggested PR Changes

The fix should be implemented in the CLI's file path construction logic (currently at line 1018 in cli.js based on stack trace):

// BEFORE (problematic):
const taskDir = `/tmp/claude/${process.env.HOME.replace(/\//g, '-')}/tasks`;

// AFTER (recommended):
const path = require('path');
const taskDir = path.join(
  process.env.XDG_CACHE_HOME || path.join(process.env.HOME, '.cache'),
  'claude',
  'tasks'
);

---

Reporter: Termux User on Android ARM64 (Accessibility: TalkBack)
Date: 2025-12-30
Severity: High (Blocks background task execution on Termux)

View original on GitHub ↗

This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗