> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/astral-sh/uv/llms.txt
> Use this file to discover all available pages before exploring further.

# Workspaces

> Learn how to manage multiple related Python packages in a single repository with uv workspaces

A workspace is a collection of one or more packages (called workspace members) that are managed together. Inspired by [Cargo workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html), uv workspaces organize large codebases by splitting them into multiple packages with shared dependencies.

## What Are Workspaces?

Workspaces are ideal for:

* A web application alongside multiple library packages
* A library with performance-critical extensions in Rust/C++
* A plugin system with separate packages per plugin
* Monorepos with related packages versioned together

<CardGroup cols={2}>
  <Card title="Shared Lockfile" icon="lock">
    Single `uv.lock` for all workspace members ensures consistent dependencies
  </Card>

  <Card title="Independent Packages" icon="boxes-stacked">
    Each member has its own `pyproject.toml` and can be versioned separately
  </Card>
</CardGroup>

## Getting Started

Create a workspace by adding a `tool.uv.workspace` table to a `pyproject.toml`:

```toml pyproject.toml theme={null}
[project]
name = "albatross"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bird-feeder", "tqdm>=4,<5"]

[tool.uv.sources]
bird-feeder = { workspace = true }

[tool.uv.workspace]
members = ["packages/*"]
exclude = ["packages/seeds"]
```

<Tip>
  Running `uv init` inside an existing project automatically adds the new project to the workspace and creates the `tool.uv.workspace` table if needed.
</Tip>

## Workspace Configuration

### Members and Exclusions

The workspace definition requires:

* `members` (required) - Globs matching workspace member directories
* `exclude` (optional) - Globs excluding specific directories

Every directory matched by `members` (and not excluded) must contain a `pyproject.toml` file.

### Workspace Root

Every workspace needs a root, which is also a workspace member:

```text theme={null}
albatross/                    # Workspace root
├── pyproject.toml            # Root member
├── uv.lock                   # Shared lockfile
├── packages/
│   ├── bird-feeder/          # Workspace member
│   │   └── pyproject.toml
│   └── seeds/                # Excluded
│       └── pyproject.toml
└── src/
    └── albatross/
```

In this example:

* `albatross` is the workspace root
* `bird-feeder` is a workspace member
* `seeds` is excluded and not part of the workspace

## Workspace Commands

### Default Behavior

By default, `uv run` and `uv sync` operate on the workspace root:

```bash theme={null}
# These are equivalent
uv run pytest
uv run --package albatross pytest
```

### Running in Specific Members

Use `--package` to target a specific workspace member:

```bash theme={null}
uv run --package bird-feeder pytest
```

This command works from any directory within the workspace.

### Locking the Workspace

`uv lock` operates on the entire workspace at once:

```bash theme={null}
uv lock
```

This updates the shared `uv.lock` with dependencies from all workspace members.

## Workspace Sources

Dependencies on workspace members use `tool.uv.sources`:

```toml pyproject.toml theme={null}
[project]
name = "albatross"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bird-feeder", "tqdm>=4,<5"]

[tool.uv.sources]
bird-feeder = { workspace = true }

[tool.uv.workspace]
members = ["packages/*"]
```

The `workspace = true` indicates the dependency is provided by a workspace member, not PyPI.

<Note>
  Dependencies between workspace members are always editable.
</Note>

### Inherited Sources

Sources defined in the workspace root apply to all members:

```toml pyproject.toml theme={null}
[project]
name = "albatross"
version = "0.1.0"
dependencies = ["bird-feeder", "tqdm>=4,<5"]

[tool.uv.sources]
bird-feeder = { workspace = true }
tqdm = { git = "https://github.com/tqdm/tqdm" }

[tool.uv.workspace]
members = ["packages/*"]
```

Every workspace member will install `tqdm` from GitHub by default.

### Overriding Sources

Members can override workspace sources:

```toml packages/bird-feeder/pyproject.toml theme={null}
[project]
name = "bird-feeder"
dependencies = ["tqdm"]

[tool.uv.sources]
# Override workspace source
tqdm = { version = ">=4.66" }
```

<Warning>
  If a member provides `tool.uv.sources` for a dependency, it ignores the workspace source even if limited by a marker that doesn't match the current platform.
</Warning>

## Workspace Layouts

### Root Project with Libraries

The most common layout has an explicit root with library packages:

```text theme={null}
albatross/
├── pyproject.toml            # Root project
├── uv.lock                   # Shared lockfile
├── src/
│   └── albatross/
│       └── main.py
└── packages/
    ├── bird-feeder/          # Library 1
    │   ├── pyproject.toml
    │   └── src/
    │       └── bird_feeder/
    └── seeds/                # Library 2
        ├── pyproject.toml
        └── src/
            └── seeds/
```

### Virtual Root

A workspace can have a "virtual" root that only aggregates packages:

```toml pyproject.toml theme={null}
[project]
name = "workspace-root"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []  # No direct dependencies

[tool.uv.workspace]
members = ["packages/*"]
```

## When to Use Workspaces

### Good Use Cases

<CardGroup cols={2}>
  <Card title="Monorepos" icon="folder-tree">
    Multiple related packages in one repository
  </Card>

  <Card title="Extension Modules" icon="code">
    Pure Python with Rust/C++ performance modules
  </Card>

  <Card title="Plugin Systems" icon="plug">
    Core library with separate plugin packages
  </Card>

  <Card title="Shared Testing" icon="vial">
    Common test suite across multiple packages
  </Card>
</CardGroup>

### Example: Core + Plugins

```toml pyproject.toml theme={null}
[project]
name = "myapp"
version = "0.1.0"
dependencies = []

[tool.uv.workspace]
members = ["plugins/*"]
```

Each plugin depends on the core:

```toml plugins/auth/pyproject.toml theme={null}
[project]
name = "myapp-auth"
version = "0.1.0"
dependencies = ["myapp"]

[tool.uv.sources]
myapp = { workspace = true }
```

## When NOT to Use Workspaces

### Conflicting Requirements

Workspaces share a single lockfile. If members have conflicting requirements, use path dependencies instead:

```toml pyproject.toml theme={null}
[project]
name = "albatross"
version = "0.1.0"
dependencies = ["bird-feeder"]

[tool.uv.sources]
bird-feeder = { path = "packages/bird-feeder" }
```

This approach:

* Allows separate virtual environments per package
* Enables fine-grained dependency resolution
* Loses `uv run --package` convenience

### Different Python Versions

Workspaces enforce a single `requires-python` for all members (the intersection of all members' `requires-python` values).

If you need to test a member on a Python version unsupported by other members:

```bash theme={null}
# Use uv pip in a separate environment
uv venv --python 3.9
uv pip install -e packages/old-member
```

## Workspace Isolation

<Warning>
  Python doesn't provide dependency isolation. uv cannot ensure that:

  * A package only uses its declared dependencies
  * Packages don't import dependencies from other workspace members

  Proper dependency declarations in each member's `pyproject.toml` are the responsibility of the developer.
</Warning>

## Single requires-python

Workspaces take the intersection of all members' `requires-python` values:

```toml albatross/pyproject.toml theme={null}
[project]
requires-python = ">=3.10"
```

```toml packages/bird-feeder/pyproject.toml theme={null}
[project]
requires-python = ">=3.11"
```

The workspace `requires-python` becomes `>=3.11` (the intersection).

## Advanced Configuration

### Workspace-wide Settings

Some settings in the root `pyproject.toml` apply workspace-wide:

```toml pyproject.toml theme={null}
[tool.uv]
# Global cache directory
cache-dir = ".cache/uv"

# Workspace-wide indexes
index-url = "https://pypi.org/simple"

# Development groups default
default-groups = ["dev", "test"]
```

### Member-specific Overrides

Members can override workspace settings:

```toml packages/bird-feeder/pyproject.toml theme={null}
[tool.uv]
# Override for this member only
default-groups = ["dev"]
```

## Workspace vs Path Dependencies

<Tabs>
  <Tab title="Workspaces">
    **Advantages:**

    * Shared lockfile ensures consistency
    * Single `uv run --package` command
    * Unified dependency resolution
    * Automatic member discovery

    **Disadvantages:**

    * Single `requires-python` for all members
    * All members must be compatible
    * Shared virtual environment
  </Tab>

  <Tab title="Path Dependencies">
    **Advantages:**

    * Separate virtual environments
    * Independent `requires-python`
    * Can have conflicting dependencies
    * More flexible versioning

    **Disadvantages:**

    * Must run commands from member directory
    * Separate lockfiles per project
    * Manual dependency coordination
  </Tab>
</Tabs>

## Migration Strategies

### From Single Project

Convert a single project to a workspace:

```bash theme={null}
# 1. Create workspace structure
mkdir packages
mv src packages/original

# 2. Create package pyproject.toml
cd packages/original
uv init --lib

# 3. Add workspace table to root
cd ../..
# Edit pyproject.toml to add [tool.uv.workspace]
```

### From Path Dependencies

Convert path dependencies to workspace:

```toml pyproject.toml theme={null}
# Before
[tool.uv.sources]
foo = { path = "packages/foo" }
bar = { path = "packages/bar" }

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

[tool.uv.workspace]
members = ["packages/*"]
```

## Related Documentation

<CardGroup cols={2}>
  <Card title="Projects" icon="folder" href="/concepts/projects">
    Learn about individual project structure
  </Card>

  <Card title="Dependencies" icon="box" href="/concepts/dependencies">
    Understand dependency management and sources
  </Card>

  <Card title="Python Versions" icon="python" href="/concepts/python-versions">
    Learn about Python version requirements
  </Card>

  <Card title="Cache" icon="database" href="/concepts/cache">
    Understand how uv caches workspace dependencies
  </Card>
</CardGroup>
