uv - Fast Python Package and Project Manager
Overview
This skill provides guidance for using uv, an extremely fast Python package and project manager written in Rust. uv replaces pip, pip-tools, pipx, poetry, pyenv, virtualenv, and more while being 10-100x faster. The skill focuses particularly on uv run for executing code within isolated project environments.
When to Use This Skill
Use this skill when:
- Working in a Python project with a
pyproject.toml file
- Running Python scripts or CLI tools that require dependencies
- Managing project dependencies and virtual environments
- Executing commands within an isolated project environment
- Creating new Python projects or initializing scripts
- Converting from pip, poetry, or other Python tooling to uv
Core Concept: uv run
The most important command in uv is uv run, which executes commands within an isolated project environment.
Why Use uv run
ALWAYS use uv run instead of bare python or direct script execution when:
- Running Python scripts that depend on project dependencies
- Executing Python CLI tools installed in the project
- Working within a uv-managed project (has
pyproject.toml)
- Running commands that need access to the project's virtual environment
Key behavior: uv run automatically ensures the project environment is current before executing the command. It installs the project into .venv and keeps it isolated from the system Python.
Basic Usage
bash
1# Run a Python script
2uv run example.py
3
4# Run a Python module
5uv run python -m mymodule
6
7# Run a CLI tool from project dependencies
8uv run pytest
9uv run ruff check
10uv run black .
11
12# Run external commands that need project access
13uv run bash scripts/deploy.sh
Adding Dependencies Per-Invocation
Use --with to include or override dependencies for a single execution without modifying pyproject.toml:
bash
1# Add a dependency temporarily
2uv run --with httpx python -c "import httpx; print(httpx.__version__)"
3
4# Specify version constraints
5uv run --with 'httpx==0.26.0' python script.py
6
7# Multiple dependencies
8uv run --with httpx --with rich python script.py
This is useful for:
- Testing code with different dependency versions
- One-off operations requiring special packages
- Running scripts without permanently adding dependencies
Running Scripts with Inline Dependencies
Python scripts can declare their own dependencies using inline metadata. This creates isolated environments separate from the project:
python
1# /// script
2# dependencies = [
3# "requests<3",
4# "rich",
5# ]
6# requires-python = ">=3.12"
7# ///
8
9import requests
10import rich
11
12# Script code here...
Important: When a script has inline metadata, uv run uses ONLY those dependencies and ignores the project's dependencies, even when run inside a project directory.
Initialize a script with metadata:
bash
1# Create script with inline metadata
2uv init --script example.py --python 3.12
3
4# Add dependencies to script
5uv add --script example.py 'requests<3' 'rich'
6
7# Run the script (uses its own dependencies)
8uv run example.py
Common Tasks and Workflows
Creating a New Project
bash
1# Create a new application project
2uv init my-project
3cd my-project
4
5# Create a library project
6uv init --lib my-library
7
8# Create project in current directory
9uv init
10
11# Specify Python version
12uv init --python 3.12
This creates:
pyproject.toml - Project configuration and dependencies
.python-version - Python version specification
README.md - Basic documentation
src/my_project/ - Source code directory (for apps)
Managing Dependencies
bash
1# Add a dependency
2uv add requests
3
4# Add with version constraint
5uv add 'httpx>=0.25,<0.27'
6
7# Add development dependency
8uv add --dev pytest
9
10# Add optional dependency group
11uv add --optional docs sphinx
12
13# Remove a dependency
14uv remove requests
15
16# Update all dependencies
17uv lock --upgrade
18
19# Sync environment to match lockfile
20uv sync
Virtual Environment Management
bash
1# uv automatically creates and manages .venv/
2# Most operations don't require manual venv activation
3
4# To manually create a venv (rarely needed)
5uv venv
6
7# To activate manually (usually unnecessary)
8source .venv/bin/activate # Linux/Mac
9.venv\Scripts\activate # Windows
Best practice: Use uv run instead of manually activating virtual environments. This ensures environment consistency and automatic updates.
Python Version Management
bash
1# Install a specific Python version
2uv python install 3.12
3
4# List available Python versions
5uv python list
6
7# Find Python installations
8uv python find
9
10# Pin project to specific Python version
11uv python pin 3.12
bash
1# Run a tool ephemerally (like pipx)
2uvx ruff check .
3uvx black --check .
4
5# Equivalent to:
6uv tool run ruff check .
7
8# Install tool globally
9uv tool install ruff
pip-Compatible Commands
uv provides drop-in pip replacements:
bash
1# Install packages (like pip install)
2uv pip install requests
3
4# Generate requirements.txt (like pip freeze)
5uv pip freeze > requirements.txt
6
7# Install from requirements.txt
8uv pip install -r requirements.txt
9
10# Compile dependencies (like pip-compile)
11uv pip compile pyproject.toml -o requirements.txt
12
13# Show dependency tree
14uv pip tree
Decision Tree: Which Command to Use
Need to run code in this project?
→ Use uv run <command>
Need to add a package to this project?
→ Use uv add <package>
Need to run a tool once without installing?
→ Use uvx <tool> or uv tool run <tool>
Need to create a new project?
→ Use uv init [project-name]
Need to update dependencies to latest versions?
→ Use uv lock --upgrade
Need to sync environment after pulling changes?
→ Use uv sync
Need to install a specific Python version?
→ Use uv python install <version>
Working with legacy pip workflows?
→ Use uv pip commands as drop-in replacements
vs pip
- 10-100x faster due to Rust implementation
- Automatic virtual environment management
- Built-in lockfile support
- No need for pip-tools or virtualenv
vs poetry
- Faster dependency resolution
- Compatible with standard
pyproject.toml
- Simpler command structure
- No separate
poetry.lock format (uses uv.lock)
vs pipx
uvx provides same functionality
- Faster execution
- Better caching and deduplication
vs pyenv
uv python manages Python versions
- Integrated with project management
- Faster installation and switching
Best Practices
-
Always use uv run in projects - Don't manually activate virtual environments; let uv handle environment management automatically.
-
Commit lockfiles - Include uv.lock in version control for reproducible builds.
-
Pin Python versions - Use uv python pin to specify project Python requirements.
-
Use --with for experiments - Test dependencies temporarily without modifying pyproject.toml.
-
Leverage inline metadata for scripts - Single-file scripts should declare dependencies inline for portability.
-
Use uvx for one-off tools - Don't pollute project dependencies with tools you run occasionally.
-
Let uv manage environments - Trust uv sync to keep environments in sync; avoid manual pip installs in uv projects.
-
Check .python-version files - Respect project Python version specifications.
Common Patterns
Running Tests
bash
1# Add pytest as dev dependency
2uv add --dev pytest pytest-cov
3
4# Run tests
5uv run pytest
6
7# Run with coverage
8uv run pytest --cov
bash
1# Add dev tools
2uv add --dev ruff black mypy
3
4# Run tools
5uv run ruff check .
6uv run black .
7uv run mypy src/
Building and Publishing
bash
1# Build distributions
2uv build
3
4# Publish to PyPI
5uv publish
6
7# Publish to test PyPI
8uv publish --index-url https://test.pypi.org/legacy/
Working with Scripts
bash
1# Create standalone script with dependencies
2uv init --script analyze.py
3uv add --script analyze.py pandas numpy
4
5# Run script (uses its inline dependencies)
6uv run analyze.py
7
8# Lock script dependencies for reproducibility
9uv lock --script analyze.py
Troubleshooting
Command not found after uv add
Problem: Added a package with a CLI tool, but command doesn't work.
Solution: Use uv run <command> to execute within project environment:
bash
1uv add ruff
2uv run ruff check . # Not just "ruff check ."
Environment out of sync
Problem: Dependencies changed but environment hasn't updated.
Solution: Run uv sync to synchronize:
Wrong Python version
Problem: Project requires different Python version.
Solution: Install and pin correct version:
bash
1uv python install 3.12
2uv python pin 3.12
Script ignores project dependencies
Problem: Script with inline metadata doesn't use project packages.
Solution: This is intentional. Scripts with inline metadata are isolated. Either:
- Remove inline metadata to use project dependencies
- Add needed dependencies to script's inline metadata
References
For detailed command options and advanced usage, see references/cli_reference.md.