A thin wrapper for uv that provides seamless external venv management with automatic environment loading.
By default uv will create a virtual environment into .venv folder local to the current project, but that is not always desirable. Other tool like poetry instead create venv in a central location for all projects, outside the project directory. For example a user may want to access a project saved on a network share: either they need to clone the project locally on their machine, or deal with the performance loss due to create a sizeable venv on network, where connection or disk speed may be a bottleneck.
uv can support venvs in any location via the UV_PROJECT_ENVIRONMENT variable, but requires it to be set for every command, or exported at session start, or loaded from a .env file.
While uv won't load environment variables from .env files on its own, it supporto running any command with environment varaiables loaded from a .env file passing the --env-file option, including itself. Indeed this is valid syntax:
uv run --env-file .env -- uv [args] # uv run itself with env variables from fileThat syntax is a bit inconvenient to write for each command a user amy want to run:
- it's a long command to type
- user need to provide the exact path to the
.envfile
To make things easier, prime-uve1 rely on .env.uve file where the UV_PROJECT_ENVIRONMENT variable is defined, for uv to run with. prime-uve provide 2 cli commands:
uve
: almost just an alias for uv run --env-file .env.uve -- uv [args]
prime-uve
: An interface for automating initial setting up (.env.file creation, venv path interpolation, basic venv management, vscode configuration, etc.)
As an intended "side" effect, prime-uve is not limited to just UV_PROJECT_ENVIRONMENT, but any variable defined in .env.uve will also be loaded.
uve is almost an alias for uv run --env-file .env.uve -- uv [args] with two enhancements:
- Automatic
.env.uvediscovery: Searches current directory and walks up parent directories - Platform-aware variable injection: Sets
PRIMEUVE_VENVS_PATHto platform-specific cache location
Example workflow when you run uve sync:
uvefinds.env.uve(walks up directory tree from current location)- Injects
PRIMEUVE_VENVS_PATHenvironment variable:- Linux:
~/.cache/prime-uve/venvs - macOS:
~/Library/Caches/prime-uve/venvs - Windows:
%LOCALAPPDATA%\prime-uve\Cache\venvs
- Linux:
- Runs:
uv run --env-file .env.uve -- uv sync - uv reads
UV_PROJECT_ENVIRONMENT=${PRIMEUVE_VENVS_PATH}/project_hashfrom.env.uve - Variable expands to actual path (e.g.,
~/.cache/prime-uve/venvs/project_hash) - uv creates/uses venv at the expanded external location
This means you can run uve commands from any subdirectory within your project, and the same .env.uve file works across different platforms and users.
prime-uve provides commands to:
Setup and initialization:
prime-uve init- Creates.env.uvewithUV_PROJECT_ENVIRONMENT=${PRIMEUVE_VENVS_PATH}/project_hash
Venv tracking (cache at ~/.local/share/prime-uve/cache.json on Linux):
prime-uve list- Shows all venvs with validation statusprime-uve prune- Removes venvs (--orphan for deleted projects, --all for everything)prime-uve register- Manually add project to cache
Shell integration:
prime-uve activate- Outputs activation commands for current shellprime-uve shell- Spawns new shell with venv activated
IDE integration:
prime-uve configure vscode- Updates workspace files with platform-generic interpreter paths
Utilities:
prime-uve dir- Opens venvs cache directory in file explorer
.env.uve uses the ${PRIMEUVE_VENVS_PATH} variable for cross-platform compatibility:
UV_PROJECT_ENVIRONMENT="${PRIMEUVE_VENVS_PATH}/myproject_abc123"This variable automatically expands to platform-specific cache locations following OS conventions:
| Platform | Environment Variable | Default Location |
|---|---|---|
| Linux | XDG_CACHE_HOME |
~/.cache/prime-uve/venvs |
| macOS | - | ~/Library/Caches/prime-uve/venvs |
| Windows | LOCALAPPDATA |
%LOCALAPPDATA%\prime-uve\Cache\venvs |
Override by setting PRIMEUVE_VENVS_PATH environment variable before running uve commands.
The path includes:
- Project name from
pyproject.toml - Short hash derived from project path (ensures uniqueness)
Install system-wide as a CLI tool:
uv tool install prime-uvecd your-project/
uv init # generate the pyproject.toml
prime-uve init This creates .env.uve with:
UV_PROJECT_ENVIRONMENT="${PRIMEUVE_VENVS_PATH}/myproject_abc123"uve sync # Instead of: uv run --env-file .env.uve -- uv sync
uve add requests # Instead of: uv run --env-file .env.uve -- uv add requests
uve run python script.py # Instead of: uv run --env-file .env.uve -- uv run python script.pyThe lookup logic for .env.uve:
- Start from current directory
- Check for
.env.uvein current directory - If not found, walk up the directory tree checking each parent directory
- Continue until
.env.uveis found or filesystem root is reached
This ensures commands work correctly from any subdirectory within your project.
List all managed venvs with validation:
- Checks if projects still exist
- Verifies paths match
.env.uvemappings - Highlights orphaned venvs
Remove venvs from cache:
--all- Clean everything--orphan- Clean only orphan venvs (deleted or moved projects)path/to/venv- Clean specific venv--current- Clean venv mapped to current project
Output activation commands for current shell:
eval "$(prime-uve activate)" # Activate venv in current shell (bash/zsh)or:
prime-uve activate | Invoke-Expression # Activate venv in current shell (PowerShell)Spawn new shell with venv activated:
prime-uve shell # Auto-detect shell
prime-uve shell --shell bash # Force specific shellOpen venvs directory in file explorer:
prime-uve dir # Opens platform-specific venvs cache directoryManually register current project in cache (rarely needed, current project is registered automatically when prime-uve list or prime-uve prune is run):
prime-uve register # Register current project from existing .env.uveTip
You actually can use use prime-uve itself to launch VS Code:
cd your-project/
uve run code .VS code will pick up the correct venv automatically, on linux, macos, or (to > a lesser extent) also on windows.2
Configure VS Code workspace files with your external venv using platform-generic variables.
cd your-project/
prime-uve configure vscodeUpdates (or creates) .code-workspace file with interpreter path:
- Linux:
${userHome}/.cache/prime-uve/venvs/project_hash/bin/python - macOS:
${userHome}/Library/Caches/prime-uve/venvs/project_hash/bin/python - Windows:
${env:LOCALAPPDATA}/prime-uve/Cache/venvs/project_hash/Scripts/python.exe
For teams working across different operating systems:
# On Linux machine
prime-uve configure vscode --suffix
# Creates: myproject.linux.code-workspace
# On macOS machine
prime-uve configure vscode --suffix
# Creates: myproject.macos.code-workspace
# On Windows machine
prime-uve configure vscode --suffix
# Creates: myproject.windows.code-workspaceAll workspace files can coexist in version control. Team members open the one for their platform.
# Merge settings from another workspace
prime-uve configure vscode --suffix --merge myproject.code-workspace
# Use absolute paths instead of variables (not recommended)
prime-uve configure vscode --expand
# Set default workspace for future merges
prime-uve configure vscode --export-as-default myproject.code-workspace
# Preview changes without applying
prime-uve configure vscode --dry-run
# Suppress output, get JSON result
prime-uve configure vscode --json| Option | Description |
|---|---|
--suffix [VALUE] |
Create platform-specific workspace (auto-detects OS if no value) |
--merge [FILE] |
Merge settings from another workspace (requires --suffix) |
--expand |
Use absolute paths instead of VS Code variables |
--export-as-default [FILE] |
Save workspace as default in .env.uve |
--workspace PATH |
Specific workspace file to update |
--yes |
Skip confirmation prompts |
--dry-run |
Preview changes without applying |
--json |
Output result as JSON |
MIT License - see LICENSE file for details.
Built on top of uv by Astral.
Footnotes
-
yes, it's read like the grappa ↩
-
On windows when entering
codein the terminal, it will not resolve tocode.exebut tocode.cmd, which is a javascript cli wrapper forcode.exe(used to provide more options at the command line). This means thatuve run code .will not actually work, butuve run code.cmd .will. And even if vscode recognize the correct path of the venv, it will label it assyteminterpreter instead ofvenv, which is annoying. Running insteaduve run <path/to/code.exe> .will work as expected, but requires full path to thecode.exebinary, or adding the binary to the PATH environment variable. ↩