uvreplacespip,pip-tools,virtualenv,pyenv, andpipx— one tool for all of it- 10–100× faster than pip because it’s written in Rust and resolves in parallel
uv init→uv add <pkg>→uv run <script>is the full project workflowuv python install 3.12manages Python versions without pyenvuvx <tool>runs CLI tools (likenpx) without permanently installing them
Quick reference tables
Installation
| Method | Command |
|---|---|
| macOS / Linux (curl) | curl -LsSf https://astral.sh/uv/install.sh \| sh |
| Windows (PowerShell) | powershell -c "irm https://astral.sh/uv/install.ps1 \| iex" |
| Homebrew | brew install uv |
| pip (if you must) | pip install uv |
| Upgrade uv itself | uv self update |
Project workflow — most common commands
| Command | What it does |
|---|---|
| uv init myproject | Create a new project with pyproject.toml |
| uv init --lib mylib | Create a library project (with src/ layout) |
| uv add requests | Add a dependency and install it |
| uv add "fastapi>=0.110" | Add with version constraint |
| uv add --dev pytest | Add a dev-only dependency |
| uv remove requests | Remove a dependency |
| uv sync | Install all deps from uv.lock |
| uv sync --frozen | Install exactly what’s in lockfile (CI use) |
| uv lock | Update uv.lock without installing |
| uv run python main.py | Run a script in the project venv |
| uv run pytest | Run a tool installed in the project venv |
| uv tree | Show full dependency tree |
Python version management
| Command | What it does |
|---|---|
| uv python list | Show available Python versions |
| uv python install 3.12 | Download and install CPython 3.12 |
| uv python install 3.11 3.12 3.13 | Install multiple versions |
| uv python pin 3.12 | Pin project to Python 3.12 (writes .python-version) |
| uv python find | Show path of the active Python |
| uv python uninstall 3.11 | Remove a Python version |
Virtual environments
| Command | What it does |
|---|---|
| uv venv | Create .venv in current directory |
| uv venv --python 3.12 | Create venv with specific Python |
| uv venv myenv | Create venv with custom name |
| source .venv/bin/activate | Activate (Linux/macOS) |
| .venv\Scripts\activate | Activate (Windows) |
With uv run, you never need to activate the venv manually. uv run python and uv run pytest use the project venv automatically.
One-off tool execution (uvx)
uvx runs CLI tools from PyPI in isolated environments — equivalent to npx for Python:
| Command | What it does |
|---|---|
| uvx ruff check . | Run ruff linter without installing it |
| uvx black . | Format with black |
| uvx mypy src/ | Type-check with mypy |
| uvx httpie GET https://api.example.com | HTTP client |
| uvx --from 'ruff==0.4.0' ruff check . | Run a pinned version |
pip compatibility mode
If you need pip syntax (scripts, Docker layers, CI), uv supports it:
| Command | What it does |
|---|---|
| uv pip install requests | Same as pip install requests |
| uv pip install -r requirements.txt | Install from requirements file |
| uv pip freeze | Print installed packages |
| uv pip list | List installed packages (table) |
| uv pip show requests | Package metadata |
| uv pip compile requirements.in | Pin deps to requirements.txt |
| uv pip sync requirements.txt | Sync venv to exact requirements file |
Project structure
When you run uv init myproject, you get:
myproject/
├── pyproject.toml # Project metadata and dependencies
├── uv.lock # Exact locked versions (commit this)
├── .python-version # Python version pin (commit this)
├── .venv/ # Virtual environment (gitignore this)
└── src/
└── myproject/
└── __init__.py A typical pyproject.toml managed by uv:
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"fastapi>=0.110",
"httpx>=0.27",
]
[dependency-groups]
dev = [
"pytest>=8",
"ruff>=0.4",
"mypy>=1.10",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build" Common workflows
Starting a new project from scratch
uv init myapi # Create project
cd myapi
uv python pin 3.12 # Pin Python version
uv add fastapi uvicorn # Add runtime deps
uv add --dev pytest ruff # Add dev deps
uv run uvicorn main:app --reload # Run without activating venv Adding dependencies with version constraints
uv add "sqlalchemy>=2.0,<3" # Range constraint
uv add "pydantic==2.7.*" # Wildcard patch
uv add "numpy ; python_version>='3.10'" # Conditional
uv add "torch --index https://download.pytorch.org/whl/cu121" # Custom index Running scripts without a project
For quick one-off scripts, uv run works without uv init:
# Script with inline dependency metadata (PEP 723)
cat > script.py << 'EOF'
# /// script
# requires-python = ">=3.11"
# dependencies = ["requests", "rich"]
# ///
import requests
from rich import print
print(requests.get("https://httpbin.org/get").json())
EOF
uv run script.py # uv installs deps in isolated env, then runs it CI/CD — fast, reproducible installs
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install project deps from lockfile (no resolver overhead)
uv sync --frozen
# Run tests
uv run pytest GitHub Actions shorthand:
- uses: astral-sh/setup-uv@v4
- run: uv sync --frozen
- run: uv run pytest Migration cheat sheet — pip / poetry / pyenv → uv
| Old tool | Old command | uv equivalent |
|---|---|---|
| pip | pip install requests | uv add requests |
| pip | pip install -r requirements.txt | uv pip install -r requirements.txt |
| pip | pip freeze > requirements.txt | uv pip freeze > requirements.txt |
| pip-tools | pip-compile requirements.in | uv pip compile requirements.in |
| pip-tools | pip-sync requirements.txt | uv pip sync requirements.txt |
| poetry | poetry new myproject | uv init myproject |
| poetry | poetry add requests | uv add requests |
| poetry | poetry add --group dev pytest | uv add --dev pytest |
| poetry | poetry install | uv sync |
| poetry | poetry run pytest | uv run pytest |
| poetry | poetry lock | uv lock |
| poetry | poetry shell | source .venv/bin/activate |
| pyenv | pyenv install 3.12 | uv python install 3.12 |
| pyenv | pyenv local 3.12 | uv python pin 3.12 |
| pyenv | pyenv versions | uv python list |
| pipx | pipx install ruff | uvx ruff (no install needed) |
| pipx | pipx run black . | uvx black . |
| virtualenv | python -m venv .venv | uv venv |
uv.lock is a cross-platform, human-readable lockfile — commit it to version control. Never hand-edit it. If a teammate on Windows and you on macOS both run uv sync --frozen, you both get the same logical packages but the right platform-specific wheels.
Speed comparison
| Task | pip | uv | |---|---|---| | Install Django cold | ~8s | ~0.3s | | Install Django cached | ~3s | ~0.05s | | Resolve 200 deps | ~45s | ~1.2s | | Create virtualenv | ~1.2s | ~0.05s |
uv downloads wheels in parallel, uses a global content-addressable cache, and avoids redundant resolver passes. The cache is stored at ~/.cache/uv (Linux/macOS) or %LOCALAPPDATA%\uv\cache (Windows).
Global tools and uv tool
uv tool manages globally installed CLI tools — separate from project dependencies:
| Command | What it does |
|---|---|
| uv tool install ruff | Install ruff globally (adds to PATH) |
| uv tool install --python 3.12 ruff | Install with a specific Python |
| uv tool upgrade ruff | Upgrade a global tool |
| uv tool list | Show globally installed tools |
| uv tool upgrade-all | Upgrade all global tools |
| uv tool uninstall ruff | Remove a global tool |
Tools installed via uv tool are placed in ~/.local/bin/uv-tools/ (Linux/macOS) or %LOCALAPPDATA%\uv\tools\ (Windows). Add that directory to your PATH to use them from anywhere.
Use uvx for one-off runs (always gets latest version). Use uv tool install when you want a persistent, pinned installation accessible from any shell.
Workspaces and monorepos
uv supports workspaces — a single pyproject.toml at the root with multiple packages beneath it:
myorg/
├── pyproject.toml # Workspace root
├── packages/
│ ├── core/
│ │ ├── pyproject.toml
│ │ └── src/core/
│ └── api/
│ ├── pyproject.toml
│ └── src/api/
├── uv.lock # Single lockfile for all packages
└── .python-version Root pyproject.toml:
[workspace]
members = ["packages/core", "packages/api"]
[tool.uv.workspace] uv sync # Sync all workspace packages
uv sync --all-packages # Include all members
uv add --package api requests # Add to specific package
uv run --package api uvicorn # Run from specific package Lockfile deep dive
uv.lock is a human-readable, human-editable lockfile. Key sections:
[[package]]
name = "fastapi"
version = "0.115.0"
source = { registry = "https://pypi.org/simple" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/.../fastapi-0.115.0-py3-none-any.whl" },
] - Platform-specific wheels — uv picks the right wheel for Linux/macOS/Windows automatically
- No source distribution builds — uv avoids compiling from source unless necessary
- Reproducible across machines — two people on different OSes get the same logical packages
- Commit it —
uv.lockgoes into version control;.venv/goes into.gitignore
uv lock --upgrade # Upgrade all packages to latest
uv lock --upgrade-package fastapi # Upgrade specific package
uv lock --verify # Verify lockfile matches pyproject.toml Real-world project examples
FastAPI API project
uv init myapi
cd myapi
uv python pin 3.13
uv add fastapi "uvicorn[standard]" sqlalchemy pydantic-settings
uv add --dev pytest httpx
uv run uvicorn main:app --reload --host 0.0.0.0 --port 8000 Data science notebook setup
uv init ds-project --lib
cd ds-project
uv python pin 3.12
uv add numpy pandas matplotlib jupyterlab
uv add --dev ruff mypy
uv run jupyter lab Script with inline dependencies (no project needed)
# Create a standalone script with its own dependencies
cat > analyze.py << 'EOF'
# /// script
# requires-python = ">=3.11"
# dependencies = ["pandas", "plotly", "typer"]
# ///
import pandas as pd
import plotly.express as px
import typer
def main(csv_path: str):
df = pd.read_csv(csv_path)
px.histogram(df).show()
if __name__ == "__main__":
typer.run(main)
EOF
uv run analyze.py data.csv Cross-platform notes
| Platform | Cache location | Tool location |
|---|---|---|
| Linux | ~/.cache/uv/ | ~/.local/bin/ |
| macOS | ~/.cache/uv/ | ~/.local/bin/ |
| Windows | %LOCALAPPDATA%\uv\cache\ | %LOCALAPPDATA%\uv\tools\ |
On Linux/macOS, add ~/.local/bin to PATH. On Windows, add %LOCALAPPDATA%\uv\tools\ to PATH.
# Linux / macOS — add to ~/.bashrc or ~/.zshrc
export PATH="$HOME/.local/bin:$PATH"
# Verify uv is found
which uv
uv --version Troubleshooting
Permission errors on macOS (SIP)
macOS restricts writing to /usr/local. Use brew install uv or the official installer (which installs to $HOME/.local/bin):
curl -LsSf https://astral.sh/uv/install.sh | sh Windows: “uv is not recognized”
The installer should add to PATH automatically. If not, manually add %USERPROFILE%\.local\bin\ to your system PATH.
”Python version not found”
uv python list # Shows available versions
uv python install 3.12 # Install missing version Lockfile out of sync
uv sync # Auto-updates lockfile if needed
uv lock --check # Fails if lockfile is stale Slow first install
uv downloads wheels in parallel. If you’re behind a slow proxy or VPN, try:
UV_HTTP_TIMEOUT=60 uv sync Summary
- One tool replaces the entire Python toolchain: pip + pip-tools + virtualenv + pyenv + pipx
uv add/uv removemanagespyproject.tomlanduv.lockautomaticallyuv runexecutes in the right environment without manual activationuvxruns any PyPI CLI tool ephemerally — no global installs neededuv sync --frozenis the CI command — fast, reproducible, no network surprises- Workspaces enable monorepo support with a single lockfile
uv tool installprovides persistent global tools;uvxfor one-off runs
FAQ
Does uv work with existing requirements.txt projects?
Yes. uv pip install -r requirements.txt is a drop-in replacement for pip install -r requirements.txt. Migrate to pyproject.toml at your own pace.
Should I commit uv.lock?
Yes, always commit uv.lock for applications. For libraries, commit it for reproducible CI but do not publish it to PyPI. This matches the poetry.lock convention.
Does uv support private PyPI servers (Artifactory, Nexus)?
Yes. Set [[tool.uv.index]] in pyproject.toml or use --index-url and --extra-index-url flags.
What Python distributions does uv install? CPython from python-build-standalone (Greg Price / Astral) by default. These are statically linked, fast-starting binaries. PyPy support is on the roadmap.
Is uv production-stable? As of 2025, uv is used by major projects including Ruff, Pydantic, FastAPI, and Astral’s own tooling. Astral backs it commercially. It follows semver and has a stability policy.
What to read next
- Python Cheat Sheet — language fundamentals
- GitHub Actions Cheat Sheet — run
uv sync --frozenin CI - Docker Cheat Sheet — containerize Python projects built with uv
Related Articles
Deepen your understanding with these curated continuations.
mise Cheat Sheet: Unified Runtime & Tool Manager (2026)
Complete mise reference — install and switch Node, Python, Rust, Go versions, manage tools, activate via shell, Docker, and CI/CD with working commands.
Regex Cheat Sheet: Patterns, Groups & Real-World Examples
Master regular expressions with this guide to anchors, groups, lookaheads, and quantifiers. Includes real-world patterns for emails, URLs, and passwords.
Warp Terminal Cheat Sheet: Shortcuts, Workflows & AI Features
Complete Warp reference — block-based terminal, command palette, workflow commands, AI autocomplete, custom themes, and team features in 2026.