# How UV Custom Indexes Work with PyTorch: A Complete Configuration Guide

> Learn how uv custom indexes simplify PyTorch wheel management. Configure multiple sources in pyproject.toml for easy CPU/CUDA build switching with the --extra flag.

- Repository: [Th3Unknovvn/uv-install-torch](https://github.com/baonguyen6742/uv-install-torch)
- Tags: how-to-guide
- Published: 2026-02-26

---

**UV custom indexes let you configure multiple PyTorch wheel sources in a single [`pyproject.toml`](https://github.com/baonguyen6742/uv-install-torch/blob/main/pyproject.toml), enabling seamless switching between CPU-only and CUDA-enabled builds using the `--extra` flag.**

The `baonguyen6742/uv-install-torch` repository demonstrates how **uv custom indexes** solve PyTorch's split distribution model—where CPU and GPU wheels live on separate URLs—without maintaining multiple configuration files. By mapping specific package versions to distinct index URLs based on optional dependencies, UV resolves the correct wheel architecture automatically.

## Declaring PyTorch Index URLs with [tool.uv.index]

In [`pyproject.toml`](https://github.com/baonguyen6742/uv-install-torch/blob/main/pyproject.toml), **UV custom indexes** are defined under the `[tool.uv.index]` table. For PyTorch, you must register both the CPU and CUDA wheel repositories hosted by PyTorch.org.

The configuration defines two named indexes:

- `pytorch-cpu`: `https://download.pytorch.org/whl/cpu`
- `pytorch-cu124`: `https://download.pytorch.org/whl/cu124`

These entries appear at lines 53-62 in the repository's [`pyproject.toml`](https://github.com/baonguyen6742/uv-install-torch/blob/main/pyproject.toml):

```toml
[[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"

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

```

## Mapping Packages to UV Custom Indexes with [tool.uv.sources]

The `[tool.uv.sources]` table tells UV which index to query for each package based on the active optional dependency (extra). This mapping connects the `torch`, `torchvision`, and `torchaudio` packages to their respective CPU or CUDA indexes.

According to the source configuration at lines 37-50:

```toml
[tool.uv.sources]
torch = [
  { index = "pytorch-cpu", extra = "cpu" },
  { index = "pytorch-cu124", extra = "cu124" },
]
torchvision = [
  { index = "pytorch-cpu", extra = "cpu" },
  { index = "pytorch-cu124", extra = "cu124" },
]
torchaudio = [
  { index = "pytorch-cpu", extra = "cpu" },
  { index = "pytorch-cu124", extra = "cu124" },
]

```

Each source object contains:

- `index`: The name matching a `[tool.uv.index]` entry
- `extra`: The optional-dependency group that activates this source

## Preventing Mixed Environments with Conflicts

To ensure users don't accidentally install both CPU and CUDA variants simultaneously, the repository declares these extras as mutually exclusive using the `conflicts` setting at lines 30-33:

```toml
[tool.uv]
conflicts = [
  [
    { extra = "cpu" },
    { extra = "cu124" },
  ],
]

```

This prevents the resolver from selecting both the `cpu` and `cu124` extras in the same environment.

## Defining Version-Pinned Optional Dependencies

The actual package versions are pinned under `[project.optional-dependencies]`. Both extras reference identical version constraints—UV selects the correct wheel based on the index mapping rather than version differences:

```toml
[project.optional-dependencies]
cpu = ["torch==2.4.1", "torchvision==0.19.1", "torchaudio==2.4.1"]
cu124 = ["torch==2.4.1", "torchvision==0.19.1", "torchaudio==2.4.1"]

```

## Installing PyTorch Using UV Custom Indexes

With the configuration in place, installing PyTorch requires only selecting the appropriate extra:

**CPU-only installation:**

```bash
uv sync --extra cpu

```

**CUDA 12.4 installation:**

```bash
uv sync --extra cu124

```

When you run these commands, UV:

1. Activates the specified extra from `[project.optional-dependencies]`
2. Looks up each package in `[tool.uv.sources]` to find the matching index for that extra
3. Queries the URL defined in `[tool.uv.index]` to resolve the wheel
4. Records the exact download URL in `uv.lock` for reproducibility

## Cache Management for PyTorch Reinstallations

If you need to force a reinstall after driver updates or architecture changes, clear the UV cache before re-syncing:

```bash
uv cache clean torch
uv sync --extra cu124

```

The `uv cache clean torch` command removes only the cached torch wheels, while `uv cache prune` removes all unused entries.

## Summary

- **UV custom indexes** are declared in `[tool.uv.index]` with named URLs pointing to PyTorch's CPU and CUDA wheel repositories.
- The `[tool.uv.sources]` table maps packages to specific indexes based on optional dependency extras.
- The `conflicts` setting prevents simultaneous installation of incompatible CPU and CUDA variants.
- Version pinning occurs in `[project.optional-dependencies]`, while wheel selection happens via index mapping.
- UV records the resolved URLs in `uv.lock`, ensuring reproducible installations across different machines.

## Frequently Asked Questions

### How do UV custom indexes differ from standard PyPI configuration?

Unlike pip's global index URL or extra index URLs, **UV custom indexes** allow per-package index selection based on conditional extras. This lets you define both CPU and CUDA PyTorch sources in the same file, whereas pip would require separate requirements files or manual URL specification.

### Can I install both CPU and CUDA PyTorch using UV custom indexes simultaneously?

No. The repository explicitly prevents this using the `conflicts` array in `[tool.uv]`, which makes the `cpu` and `cu124` extras mutually exclusive. Attempting to sync with both extras (`uv sync --extra cpu --extra cu124`) will result in a resolution error.

### How do I verify which index UV used to install PyTorch?

Check the `uv.lock` file generated after syncing. This lockfile records the exact URL from which each wheel was downloaded, confirming whether the package came from `https://download.pytorch.org/whl/cpu` or `https://download.pytorch.org/whl/cu124`.

### What happens if I run `uv sync` without specifying an extra?

Without the `cpu` or `cu124` extra, UV will not activate the custom index mappings in `[tool.uv.sources]`. The resolver will attempt to find PyTorch packages on the default PyPI index, which typically lacks the platform-specific wheels or contains different builds than the official PyTorch indexes.