Quick Reference · the fast Python package & project manager

uv cheat sheet0.12.x

One Rust binary that replaces pip, pipx, pyenv, poetry, virtualenv & pip-tools. For a project, three files stay in lockstep: pyproject.toml declares what you want, uv.lock pins the exact resolved versions, and .venv holds what's installed. Every command — add, run, sync — keeps all three honest for you.

project / core dependencies run · sync · lock Python versions tools / uvx pip interface & utility gotcha most common

Verified 2026-08-26 against uv 0.12.6 (installed & run) · every command from uv --help, every workflow confirmed by execution — initaddrun, the generated uv.lock, PEP 723 scripts, tools & the pip interface all run live. Structure follows the official docs.astral.sh/uv feature map.

The project loop — three files uv keeps in sync for you
YOU DECLARE INTENT uv RESOLVES & PINS uv INSTALLS pyproject.toml broad requirements — hand-edited or via uv add [project] requires-python = ">=3.12" dependencies = [ "httpx>=0.27", ] [dependency-groups] dev = [...] resolve uv.lock exact, cross-platform, hashed — commit it version = 1 revision = 3 [[package]] name = "httpx" version = "0.28.1" + anyio, certifi, h11,   httpcore, idna … every transitive dep, fully pinned sync .venv/ the real installed environment — git-ignored bin/python → 3.12 site-packages/ httpx anyio certifi httpcore h11 idna hard-linked from the global cache — near-zero copy THE EVERYDAY COMMANDS OPERATE ON THIS LOOP uv add httpx edits pyproject + lock + venv uv lock re-resolve → refresh uv.lock uv sync make .venv match the lock uv run <cmd> verifies lock+venv, THEN runs before every run, uv checks pyproject → lock → venv are all in sync — no manual activate, no stale env $ uv add httpx Using CPython 3.12.3 · Creating virtual environment at: .venv Resolved 8 packages in 345ms · Installed 7 packages in 9ms $ uv run python -c "import httpx" # auto-syncs first, then runs one command did what pip + venv + pip-tools + activate used to — and in milliseconds
Two ways in — a project, or a single script
a project · the poetry / pipenv replacement
uv init myapp && cd myapp   # scaffold
uv add httpx "pytest" --dev   # deps + dev group
uv run python main.py       # auto-syncs, runs
uv run pytest               # in the locked env
uv lock --upgrade            # bump the lockfile
uv sync                     # reproduce it exactly
# commit pyproject.toml + uv.lock
a standalone script · PEP 723 inline deps
uv init --script fetch.py         # add header
uv add --script fetch.py rich       # pin dep
# fetch.py now starts with:
# /// script
# requires-python = ">=3.12"
# dependencies = ["rich>=13"]
# ///
uv run fetch.py     # ephemeral env, just works
uvx ruff check .    # a tool, no install needed
PART I

Projects

pyproject.toml + uv.lock + .venv
01Install uvone binary
02Start a Projectuv init
03Add & Remove Depsuv add / remove
04Run Commandsuv run
05Lock & Syncreproduce exactly
06Inspect & Exporttree / export
07The Files uv Manageswhat's on disk
PART II

Scripts, Tools & Python

the pipx + pyenv replacement
08Standalone ScriptsPEP 723
09Tools & uvxthe pipx replacement
10Python Versionsthe pyenv replacement
11Cache, Auth & Selfuv's own state
PART III

pip Interface, Build & Config

low-level control + publishing
12Virtual Environmentsuv venv
13The pip Interfaceuv pip
14Compile Requirementsthe pip-tools replacement
15Build & Publishthe twine replacement
16WorkspacesCargo-style monorepos
17Sources & Indexeswhere deps come from
18Config & Env Varstune behaviour
19Gotchas & Habitswhat bites
Reading uv Outputthe log lines

Four things worth seeing once

Which command to reach for, why the lockfile matters, how the cache makes installs near-instant, and which classic tool each uv command retires — all drawn from behaviour verified against uv 0.12.6.

uv add vs uv pip install

The single most common confusion. uv add is the project API and touches all three files; uv pip install is a low-level env tool that touches none of them.

uv add httpx pyproject.toml ✓ uv.lock ✓ .venv ✓ all three stay consistent — reproducible uv pip install httpx pyproject — untouched uv.lock — untouched .venv ✓ env now has a package nothing records — not reproducible Rule: in a project use uv add; use uv pip only for raw envs.

pyproject vs lockfile

pyproject says what you'll accept; the lock records what you actually got. That gap is the whole point — loose specs resolve to exact, shared versions.

pyproject.toml what you accept dependencies: httpx>=0.27 one loose line no transitive deps may differ per machine resolve uv.lock what everyone gets httpx ==0.28.1 anyio ==4.14.2 certifi ==2026.7.22 h11 ==0.16.0 httpcore ==1.0.9 idna ==3.18

why installs are near-instant

uv downloads and builds each package once into a global cache, then hard-links it into every project's .venv. The second project pays almost nothing.

global cache each wheel downloaded & built once hard-link hard-link projA/.venv first: ~ms projB/.venv near-zero copy projC/.venv near-zero copy no re-download, no duplicate bytes on disk — that's the speed

one tool, many retired

uv folds a whole toolbox into a single binary. Each classic command maps to a uv equivalent — usually faster and with a shared cache.

pip virtualenv pyenv pipx pip-tools poetry / pipenv twine uv pip uv venv uv python uv tool / uvx uv pip compile uv add / lock / sync uv publish one install, one cache, one lockfile format across all of it

Worth memorizing

three project filespyproject.toml + uv.lock + .venv, kept in sync
commit / ignorecommit lock & pyproject; git-ignore .venv
add, don't pip installuv add in projects; uv pip only for raw envs
uv run auto-syncschecks lock+venv before every command
no activate neededuv run / uv pip target .venv directly
uvx = ephemeral tooluvx ruff runs without installing anything
--dev / --groupdev & named groups stay out of your shipped deps
CI installuv sync --frozen — deterministic, no re-resolve
bump the lockuv lock --upgrade (or --upgrade-package X)
PEP 723 scriptsuv add --script f.py dep — self-contained files
manage Python toouv python install / pin replaces pyenv
global cachehard-links, not copies — installs after the first are ~free
export back outuv export → a classic requirements.txt
reproducible resolves--exclude-newer DATE freezes the index in time
workspacesmany packages, one shared lockfile
pre-1.0pin uv itself in CI; minors can break