uv
uv is a Python package and project manager written in Rust by Astral, the company behind Ruff. One binary replaces pip, pip-tools, pipx, poetry, pyenv, virtualenv and twine: it creates virtual environments, resolves and installs dependencies 10-100x faster than pip on its benchmarks, installs and pins Python versions themselves, runs single-file scripts with inline dependency metadata, and locks projects with a universal cross-platform lockfile. A pip-compatible interface (uv pip) lets existing workflows switch without rewrites.
The best Python tooling story in years: one fast binary that replaces five tools, with docs to match. Adopt it for new projects and CI; just treat the 0.x label seriously and pin versions, because the interface is still allowed to move under you.
Use it if
- You are starting a Python project and want init, add, lock and sync with a committed lockfile instead of hand-managed requirements files
- CI install time hurts: the global cache and resolver speed cut minutes from cold and warm builds alike
- You juggle Python versions per project and want uv python install/pin instead of maintaining pyenv
- You want pipx-style tool running (uvx ruff) and script execution with inline dependencies
- Your org requires boring, settled tooling: uv is still 0.x (0.12.1) and its own versioning policy allows breaking changes in minor releases, so pin the version and read changelogs
- You live in the conda world: uv installs from PyPI and does not manage conda packages or non-Python binaries like CUDA toolkits that scientific stacks depend on
- Your team is deep into Poetry with plugins and workflows that already work; the speed win may not justify the migration and retraining cost
- You need to avoid tools controlled by a single VC-funded company as a matter of policy; Astral funds and steers uv development
Setup reality
Installation is genuinely easy: a curl script, pip or pipx puts one static binary on the machine, no Rust or Python required, and standalone installs self-update with uv self update. The friction is workflow, not install: uv owns the .venv and expects the uv run / uv sync habit, pyproject.toml becomes the single source of truth, and mixing manual pip installs into a uv-managed environment drifts it out of sync with the lockfile. Because it is pre-1.0, CI should pin the uv version or a minor bump can change resolution behavior mid-week.
Patterns
Start a project and add a dependencynew-project
uv init example
cd example
uv add requests
uv run main.pyuv add creates the .venv and uv.lock automatically; you never activate the venv by hand if you stick to uv run.
Reproduce the environment from the lockfilesync-lockfile
uv sync
# refresh the lockfile after editing pyproject.toml:
uv lockCommit uv.lock; it is cross-platform (one lockfile resolves for all OSes), unlike platform-bound pip freeze output.
Strict, fast installs in CIci-install
uv sync --frozen
uv run pytest--frozen fails the build if uv.lock is out of date instead of silently re-resolving; that is what you want in CI.
Separate dev-only dependenciesdev-dependencies
uv add --dev pytest ruff
# install everything except dev deps:
uv sync --no-devDev deps go into the dependency-groups table in pyproject.toml and are installed by default with uv sync; production images want --no-dev.
Single-file script with its own dependenciesrun-script-inline-deps
uv add --script fetch.py requests
uv run fetch.pyDependencies are written as inline metadata comments inside the script and run in an isolated ephemeral environment, no project or venv needed.
Install and pin Python itselfmanage-python-versions
uv python install 3.12 3.13
uv python pin 3.12
uv run python --versionpin writes a .python-version file that uv respects per directory; no pyenv, no shims on PATH.
Run or install CLI tools (pipx replacement)run-tools
uvx ruff check .
# or keep it on PATH permanently:
uv tool install ruffuvx runs the tool in a throwaway environment each time; uv tool install is for tools you call daily.
Drop-in speedup for pip workflowspip-interface
uv venv
uv pip compile requirements.in --universal -o requirements.txt
uv pip sync requirements.txtThe uv pip commands mirror pip and pip-tools flags, so existing Makefiles usually work by prefixing uv; --universal makes the output platform-independent.
Move an existing requirements.txt project to uvmigrate-requirements
uv init --bare
uv add -r requirements.txt
uv syncThis imports the pins into pyproject.toml and generates uv.lock; delete requirements.txt only after CI is switched over.
Upgrade one package or everythingupdate-dependencies
uv lock --upgrade-package requests
# or re-resolve everything to latest allowed versions:
uv lock --upgrade
uv syncuv add requests@latest also works for bumping the constraint itself, not just the locked version.
Update uv itselfself-update
uv self updateOnly works for standalone-installer installs; if uv came from pip or pipx you upgrade it through that tool instead.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| pip | PyPI | You want the zero-controversy default that every tutorial, image and runbook already assumes |
| poetry | PyPI | You want a mature project manager with a large plugin ecosystem and years of production mileage |
| pdm | PyPI | You want standards-first pyproject management (PEP 582 heritage, PEP 621) without Astral's stack |