Skip to main content
Dependencies of a project are defined in several fields in pyproject.toml. uv supports modifying dependencies with uv add and uv remove, or by editing the pyproject.toml directly.

Dependency Fields

Dependencies are organized into different tables:

project.dependencies

Published runtime dependencies

project.optional-dependencies

Published optional dependencies (extras)

dependency-groups

Local development dependencies (PEP 735)

tool.uv.sources

Alternative dependency sources
The project.dependencies and project.optional-dependencies fields can be used even if the project isn’t going to be published. dependency-groups is a recently standardized feature that may not be supported by all tools yet.

Adding Dependencies

Add a dependency to your project:
uv add httpx
This updates pyproject.toml:
pyproject.toml
[project]
name = "example"
version = "0.1.0"
dependencies = ["httpx>=0.27.2"]

Version Constraints

By default, uv adds a constraint for the most recent compatible version. Customize the bound type:
# Add with specific constraint
uv add "httpx>=0.20"

# Add exact version
uv add "httpx==0.27.2"

# Add with different bound type
uv add httpx --bounds ">=,<"

Importing from requirements.txt

Import dependencies from a requirements.txt file:
uv add -r requirements.txt

Removing Dependencies

Remove a dependency:
uv remove httpx
Remove from specific tables with flags:
uv remove httpx --dev
uv remove httpx --optional network
uv remove httpx --group test

Changing Dependencies

Update an existing dependency’s constraints:
uv add "httpx>0.1.0"
This changes constraints in pyproject.toml. The locked version only changes if necessary to satisfy new constraints. To force an upgrade, use --upgrade-package:
uv add "httpx>0.1.0" --upgrade-package httpx
Change dependency source (e.g., to local development version):
uv add "httpx @ ../httpx"

Platform-Specific Dependencies

Use environment markers for platform-specific dependencies:
# Linux only
uv add "jax; sys_platform == 'linux'"

# Python 3.11+
uv add "numpy; python_version >= '3.11'"
Resulting pyproject.toml:
pyproject.toml
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
  "jax; sys_platform == 'linux'",
  "numpy; python_version >= '3.11'",
]

Available Markers

Common environment markers:
  • sys_platform - OS platform (“linux”, “darwin”, “win32”)
  • platform_machine - Architecture (“x86_64”, “aarch64”)
  • python_version - Python version (“3.11”, “3.12”)
  • implementation_name - Python implementation (“cpython”, “pypy”)

Project Dependencies

The project.dependencies table represents dependencies used when:
  • Publishing to PyPI
  • Building wheels
  • Installing the package

Dependency Specifier Syntax

Dependency specifiers follow PEP 508 syntax:
pyproject.toml
[project]
name = "albatross"
version = "0.1.0"
dependencies = [
  # Version range
  "tqdm >=4.66.2,<5",
  # Exact version
  "torch ==2.2.2",
  # With extras
  "transformers[torch] >=4.39.3,<5",
  # Platform-specific
  "importlib_metadata >=7.1.0,<8; python_version < '3.10'",
]

Version Specifier Operators

  • >=1.2.3 - Greater than or equal
  • <2.0 - Less than
  • ==1.2.3 - Exact version
  • !=1.4.0 - Not equal
Specifiers can be combined:
dependencies = ["foo >=1.2.3,<2,!=1.4.0"]

Dependency Sources

The tool.uv.sources table extends standard dependencies with alternative sources during development.

Why Use Sources?

Sources enable patterns not supported by project.dependencies:
  • Editable installations
  • Relative paths
  • Git repositories
  • Local development versions
Sources are uv-specific and ignored by other tools. If another tool is used, source metadata must be re-specified in that tool’s format.

Index Sources

Install from a specific package index:
uv add torch --index pytorch=https://download.pytorch.org/whl/cpu
Resulting configuration:
pyproject.toml
[project]
dependencies = ["torch"]

[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
Using index source pins the package to that index exclusively.

Explicit Indexes

Mark an index as explicit to use it only for pinned packages:
pyproject.toml
[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true

Git Sources

Install from Git repositories:
# HTTPS
uv add git+https://github.com/encode/httpx

# SSH
uv add git+ssh://[email protected]/encode/httpx
With specific references:
uv add git+https://github.com/encode/httpx --tag 0.27.0
pyproject.toml
[tool.uv.sources]
httpx = { git = "https://github.com/encode/httpx", tag = "0.27.0" }

Git Subdirectories

For packages not in the repository root:
uv add git+https://github.com/langchain-ai/langchain#subdirectory=libs/langchain

Git LFS Support

Configure Git LFS per source:
uv add --lfs git+https://github.com/astral-sh/lfs-cowsay
pyproject.toml
[tool.uv.sources]
lfs-cowsay = { git = "https://github.com/astral-sh/lfs-cowsay", lfs = true }
  • lfs = true - Always fetch LFS objects
  • lfs = false - Never fetch LFS objects
  • Omitted - Use UV_GIT_LFS environment variable

URL Sources

Install from direct URLs (wheels or source distributions):
uv add "https://files.pythonhosted.org/packages/.../httpx-0.27.0.tar.gz"
pyproject.toml
[tool.uv.sources]
httpx = { url = "https://files.pythonhosted.org/packages/.../httpx-0.27.0.tar.gz" }

Path Sources

Install from local paths:
uv add ./foo-0.1.0-py3-none-any.whl
Path sources support absolute and relative paths:
pyproject.toml
[tool.uv.sources]
foo = { path = "./packages/foo" }
bar = { path = "/absolute/path/to/bar" }

Editable Path Dependencies

Request editable installation for directories:
uv add --editable ./packages/foo
pyproject.toml
[tool.uv.sources]
foo = { path = "./packages/foo", editable = true }
For multiple related packages, consider using workspaces instead.

Workspace Sources

Declare dependencies on workspace members:
pyproject.toml
[project]
dependencies = ["foo==0.1.0"]

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

[tool.uv.workspace]
members = ["packages/foo"]
Workspace members are always editable.

Platform-Specific Sources

Limit sources to specific platforms using markers:
pyproject.toml
[tool.uv.sources]
httpx = {
  git = "https://github.com/encode/httpx",
  tag = "0.27.2",
  marker = "sys_platform == 'darwin'"
}
On macOS, httpx installs from GitHub. On other platforms, it falls back to PyPI.

Multiple Sources

Provide multiple sources disambiguated by environment markers:
pyproject.toml
[project]
dependencies = ["httpx"]

[tool.uv.sources]
httpx = [
  { git = "https://github.com/encode/httpx", tag = "0.27.2", marker = "sys_platform == 'darwin'" },
  { git = "https://github.com/encode/httpx", tag = "0.24.1", marker = "sys_platform == 'linux'" },
]
Platform-specific indexes:
pyproject.toml
[tool.uv.sources]
torch = [
  { index = "torch-cpu", marker = "platform_system == 'Darwin'"},
  { index = "torch-gpu", marker = "platform_system == 'Linux'"},
]

[[tool.uv.index]]
name = "torch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true

[[tool.uv.index]]
name = "torch-gpu"
url = "https://download.pytorch.org/whl/cu124"
explicit = true

Disabling Sources

Ignore tool.uv.sources (e.g., to test published metadata):
uv lock --no-sources

Optional Dependencies

Optional dependencies (extras) reduce the default dependency tree for libraries.

Defining Optional Dependencies

pyproject.toml
[project]
name = "pandas"
version = "1.0.0"

[project.optional-dependencies]
plot = ["matplotlib>=3.6.3"]
excel = [
  "odfpy>=1.4.1",
  "openpyxl>=3.1.0",
  "xlrd>=2.0.1",
]

Adding Optional Dependencies

uv add httpx --optional network

Installing with Extras

Users install extras with bracket syntax:
uv pip install "pandas[plot,excel]"

Extra-Specific Sources

Use different sources for different extras:
pyproject.toml
[project.optional-dependencies]
cpu = ["torch"]
gpu = ["torch"]

[tool.uv.sources]
torch = [
  { index = "torch-cpu", extra = "cpu" },
  { index = "torch-gpu", extra = "gpu" },
]

Development Dependencies

Development dependencies are local-only and not published to PyPI.

Adding Development Dependencies

uv add --dev pytest
This creates a dev group in [dependency-groups] (PEP 735):
pyproject.toml
[dependency-groups]
dev = ["pytest >=8.1.1,<9"]

The dev Group

The dev group is special:
  • Has dedicated flags: --dev, --only-dev, --no-dev
  • Synced by default with uv sync and uv run

Dependency Groups

Organize development dependencies into multiple groups:
uv add --group lint ruff
uv add --group test pytest
uv add --group docs mkdocs
Resulting configuration:
pyproject.toml
[dependency-groups]
dev = ["pytest"]
lint = ["ruff"]
test = ["pytest", "coverage"]
docs = ["mkdocs", "mkdocs-material"]

Using Groups

# Install all groups
uv sync --all-groups

# Install specific groups
uv sync --group lint --group test

# Install only one group
uv sync --only-group docs

# Exclude specific groups
uv sync --no-group lint
The --dev, --only-dev, and --no-dev flags are equivalent to --group dev, --only-group dev, and --no-group dev.

Nesting Groups

Groups can include other groups:
pyproject.toml
[dependency-groups]
dev = [
  {include-group = "lint"},
  {include-group = "test"}
]
lint = ["ruff"]
test = ["pytest"]

Default Groups

Configure which groups are installed by default:
pyproject.toml
[tool.uv]
default-groups = ["dev", "lint"]

# Or enable all groups
default-groups = "all"
Disable defaults during commands:
uv sync --no-default-groups
uv sync --no-group lint

Group requires-python

Groups can have different Python version requirements:
pyproject.toml
[project]
name = "example"
version = "0.0.0"
requires-python = ">=3.10"

[dependency-groups]
dev = ["pytest"]

[tool.uv.dependency-groups]
dev = {requires-python = ">=3.12"}

Build Dependencies

Build dependencies are required to build the project, but not to run it.

Defining Build Dependencies

pyproject.toml
[project]
name = "example"
version = "0.1.0"

[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"

Build Dependencies with Sources

By default, tool.uv.sources applies to build dependencies:
pyproject.toml
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"

[tool.uv.sources]
setuptools = { path = "./packages/setuptools" }
When publishing, run uv build --no-sources to verify the package builds without custom sources.

Editable Dependencies

Editable installations link source directories directly into the virtual environment.

How Editable Works

1

Regular Installation

Builds wheel, copies files to venv
2

Editable Installation

Adds .pth file linking to source directory
3

Result

Source changes immediately reflected without reinstall

Limitations

  • Build backend must support editable installs
  • Native modules aren’t recompiled before import
  • Some packaging features may not work

Using Editable Dependencies

uv uses editable installation for workspace packages by default. For path dependencies:
uv add --editable ./path/foo
Opt-out for workspace members:
uv add --no-editable ./path/foo

Virtual Dependencies

Virtual dependencies don’t install the package itself, only its dependencies.

When to Use

Useful for:
  • Dependency-only projects without installable code
  • Aggregating multiple packages’ dependencies
  • Build-only dependency sets

Marking Dependencies as Virtual

pyproject.toml
[project]
dependencies = ["bar"]

[tool.uv.sources]
bar = { path = "../projects/bar", package = false }
With package = false, only bar’s dependencies are installed, not bar itself.

Projects

Learn about project structure and pyproject.toml

Workspaces

Manage dependencies across multiple related packages

Python Versions

Understand how Python versions affect dependency resolution

Cache

Learn how uv caches dependencies

Build docs developers (and LLMs) love