[Bug] Sandbox env exports UV_CACHE_DIR=~/.cache/uv with literal tilde, causing uv to create stray '~' directories in cwd

Open 💬 0 comments Opened Jun 19, 2026 by zettaittenani

Summary

Inside the Claude Code Bash tool, UV_CACHE_DIR is exported as the literal string ~/.cache/uv (tilde not expanded), while HOME is correctly set to the absolute path. uv treats UV_CACHE_DIR as a literal path, so every uv sync / uv run invocation creates a directory literally named ~ (single tilde character) under the current working directory.

Reproduction

Inside Claude Code's Bash tool:

echo "HOME=$HOME"
echo "UV_CACHE_DIR=$UV_CACHE_DIR"
# → HOME=/Users/<user>
# → UV_CACHE_DIR=~/.cache/uv      ← literal tilde

mkdir -p /tmp/repro && cd /tmp/repro && uv init -q && uv sync
ls
# → ~/  (a directory literally named '~')
find '~' -maxdepth 3
# → ~/.cache/uv/{interpreter-v4,sdists-v9,simple-v18,wheels-v5,archive-v0}/...

Outside Claude Code (user's normal terminal), UV_CACHE_DIR is unset and uv uses \$HOME/.cache/uv correctly. Verified by running printenv UV_CACHE_DIR in a Ghostty / zsh session — empty output. So the variable is being injected somewhere inside the Claude Code launch / sandbox path, not inherited from the user's shell.

Expected

UV_CACHE_DIR should either be:

  • unset (uv falls back to \$HOME/.cache/uv), or
  • exported with ~ expanded to the actual home directory.

Actual

UV_CACHE_DIR=~/.cache/uv is exported with literal tilde. uv does not perform shell-style tilde expansion on this variable (by design — env vars are paths, not shell expressions), so it creates <cwd>/~/.cache/uv/... — leaving stray ~ directories in every project where uv was invoked.

Impact

  • Mostly harmless but messy: every uv sync / uv run inside Claude Code leaves a ~/ dir behind in the project root. Users discover them later and wonder if they're sensitive.
  • Cache duplication: each project gets its own ~/.cache/uv instead of sharing the global one, multiplying disk usage with downloaded wheels.
  • git status may flag them as untracked (or worse, get committed) if ~ isn't in .gitignore.

Environment

  • Claude Code version: 2.1.161
  • Host: macOS 25.0.0 (Darwin), /bin/zsh user shell
  • uv: any version (behavior is the same — uv doesn't expand ~ in env vars)

Suggested fix

In whatever script / VM image / launcher path sets UV_CACHE_DIR for the sandbox, either:

  • drop the export (let uv use its default), or
  • expand ~ ahead of time, e.g. UV_CACHE_DIR=\"\$HOME/.cache/uv\".

Workaround until then

Pass an expanded UV_CACHE_DIR per invocation:

UV_CACHE_DIR=\"\$HOME/.cache/uv\" uv sync

View original on GitHub ↗