[Bug] Sandbox env exports UV_CACHE_DIR=~/.cache/uv with literal tilde, causing uv to create stray '~' directories in cwd
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 runinside 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/uvinstead of sharing the global one, multiplying disk usage with downloaded wheels. git statusmay 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/zshuser 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