uv replaces pip, virtualenv, poetry, pyenv, and pipx with a single tool. By 2026 the patterns are settled. This post is the cookbook.

A new project

uv init my-app
cd my-app
uv add fastapi pydantic httpx
uv add --dev pytest ruff mypy
uv run pytest

Five commands; project ready. No virtualenv activation, no pip install, no pyenv use.

A script with inline deps (PEP 723)

#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.13"
# dependencies = [
#   "httpx>=0.28",
#   "rich>=13",
# ]
# ///
import httpx
from rich.console import Console

c = Console()
r = httpx.get("https://api.github.com/users/AlzyWelzy")
c.print(r.json())
chmod +x script.py
./script.py

uv reads the inline deps; sets up a temporary venv; runs. No project setup. PEP 723 standard; works across tools.

Lockfiles

uv lock              # update lockfile from pyproject
uv sync              # install exact versions from lockfile
uv sync --frozen     # CI: error if lockfile is out of date

Lockfile (uv.lock) is committed. Reproducible installs across machines.

Workspaces

# pyproject.toml at root
[tool.uv.workspace]
members = ["api", "core", "cli"]

[tool.uv.sources]
core = { workspace = true }
api = { workspace = true }
# api/pyproject.toml
[project]
name = "api"
dependencies = ["core", "fastapi"]

[tool.uv.sources]
core = { workspace = true }

uv sync at root resolves the whole workspace. Each package can be installed independently for tests / build.

Python version pinning

uv python install 3.13
uv python pin 3.13     # writes .python-version

Per-project Python. Replaces pyenv. The .python-version is honored automatically by uv run.

CLI tools

uv tool install ruff       # globally available
uv tool install black
uvx ruff check .            # one-shot run

uv tool replaces pipx. uvx runs without installing.

Docker

# syntax=docker/dockerfile:1.7
FROM python:3.13-slim AS builder
WORKDIR /app
RUN pip install --no-cache-dir uv
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --frozen --no-dev

FROM python:3.13-slim
WORKDIR /app
COPY --from=builder /app/.venv /app/.venv
COPY . .
ENV PATH="/app/.venv/bin:$PATH"
CMD ["python", "-m", "app"]

Two-stage. Cache-friendly. ~150 MB final image. See Dockerfile Best Practices .

CI

- uses: astral-sh/setup-uv@v3
  with: { enable-cache: true }
- run: uv python install 3.13
- run: uv sync --all-extras --frozen
- run: uv run ruff check .
- run: uv run mypy src/
- run: uv run pytest

enable-cache: true is the magic. Subsequent runs are seconds.

Editable installs

uv add --editable ./local-package

Develop a local package while it’s a dependency of the main project. Changes reflected immediately.

Optional dependencies

[project.optional-dependencies]
dev = ["pytest", "ruff", "mypy"]
ml = ["torch", "transformers"]
uv sync --extra ml
uv sync --all-extras

Group deps by use case. Don’t install ML deps in your API container.

Migrating from poetry

uvx migrate-to-uv

Reads pyproject.toml and poetry.lock; produces uv.lock. Some manual cleanup typically needed (poetry-specific config). Good enough for 80% of projects.

Migrating from requirements.txt

uv init
uv add $(cat requirements.txt | grep -v '^#')

Quick. Won’t preserve hash pins; review and add back if you had them.

Common mistakes

1. Mixing uv and pip in the same venv

uv and pip both modify .venv. Pick one per project. Mixing causes resolution conflicts.

2. uv add without commit

Adds to pyproject.toml and uv.lock. Commit both. Otherwise teammates’ uv sync fails.

3. uv pip install for new deps

uv pip install doesn’t update pyproject.toml. Use uv add instead.

4. Forgetting --frozen in CI

CI installs whatever’s resolvable. If lockfile is stale, you get drift. Always --frozen.

5. Slow CI without caching

enable-cache: true plus the actions/cache for uv’s dir. 90% time saved.

Read this next

If you want my uv project templates per use case, it’s at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .