Skip to content

How to Add a Dependency to a uv Project

uv manages project dependencies through one command. uv add writes the package into your pyproject.toml, resolves a compatible version into the lockfile, and installs it into the project’s virtual environment. pip splits those three steps across pip install and a hand edit of your project metadata.

These commands assume a uv project, meaning a directory with a pyproject.toml. Run uv init first to create one if you don’t have it yet.

Add a package

Name the package and uv does the rest:

$ uv add httpx
Using CPython 3.12.10 interpreter at: /usr/local/bin/python3.12
Creating virtual environment at: .venv
Resolved 8 packages in 114ms
Prepared 7 packages in 51ms
Installed 7 packages in 18ms
 + anyio==4.14.2
 + certifi==2026.7.22
 + h11==0.16.0
 + httpcore==1.0.9
 + httpx==0.28.1
 + idna==3.18
 + typing-extensions==4.16.0

Three files change. pyproject.toml gains a line in its dependencies array ("httpx>=0.28.1"), uv.lock records the exact resolved version and its hashes, and the .venv directory receives the install. The first uv add in a fresh project also creates that .venv, which is why the Creating virtual environment line appears before anything installs. Anyone who clones the project and runs uv sync reproduces the same set of versions.

Add several at once by listing them:

uv add httpx rich

Pin a version

Pass a version specifier in quotes so the shell doesn’t read > as a redirect:

uv add 'httpx>=0.27,<1.0'

uv writes that range to pyproject.toml and installs the newest version inside it. Without a specifier, uv adds a lower bound at the version it resolved (httpx>=0.28.1), which lets future upgrades move forward freely. To later raise a version ceiling that is blocking an upgrade, see how to upgrade a dependency past its version ceiling.

Add a development dependency

Tools you use while working on the project, but that its users don’t need, belong in a dependency group. Pass --dev to put a package in the dev group:

uv add --dev pytest

This writes to [dependency-groups] in pyproject.toml rather than the main dependencies array. The dev group installs when you run uv sync locally but is left out when someone installs your package as a dependency of theirs. Use --group <name> to target a named group other than dev.

Add an optional dependency

An optional dependency ships as an extra that users opt into (pip install yourpackage[plot]). Add one with --optional and the extra’s name:

uv add --optional plot matplotlib

uv writes matplotlib under a plot key in [project.optional-dependencies]. Unlike a dev dependency, an extra is published with your package, so downstream users can request it.

Add from Git, a URL, or a local path

uv resolves sources beyond the default package index. Point at a Git repository with the package @ git+URL form:

uv add "httpx @ git+https://github.com/encode/httpx"

Pin the reference with --tag, --branch, or --rev to avoid tracking a moving branch:

uv add "httpx @ git+https://github.com/encode/httpx" --tag 0.28.1

uv records the repository under a [tool.uv.sources] table in pyproject.toml and keeps the package name in your dependencies list, so the source and the requirement stay separate.

For a package you develop alongside this project, add it from a local path as an editable install so your edits take effect without reinstalling:

uv add --editable ../my-library

Remove a dependency

uv remove reverses uv add, updating the same three places:

uv remove httpx

It drops the package from pyproject.toml, re-resolves and rewrites uv.lock, and uninstalls it from the virtual environment along with any dependencies no longer needed.

Learn More

Last updated on