> ## 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.

# Caching System

> Learn how uv's global cache works for high-performance package installation and deduplication

uv uses aggressive caching to avoid re-downloading and re-building dependencies that have already been accessed in prior runs.

## How Caching Works

uv maintains a global cache that stores:

* Downloaded wheels from package indexes
* Built wheels from source distributions
* Git repository clones
* Package metadata
* Python installations

<Info>
  The cache enables near-instant installations when packages have been previously downloaded or built.
</Info>

## Dependency Caching

Caching semantics vary by dependency type:

<Tabs>
  <Tab title="Registry Dependencies">
    **From PyPI and other indexes**

    uv respects HTTP caching headers:

    * `Cache-Control`
    * `ETag`
    * `Last-Modified`

    Packages are cached based on version and metadata.
  </Tab>

  <Tab title="Direct URL Dependencies">
    **From direct URLs**

    uv caches based on:

    * HTTP caching headers
    * The URL itself

    Changes to the URL trigger re-download.
  </Tab>

  <Tab title="Git Dependencies">
    **From Git repositories**

    uv caches based on:

    * Fully-resolved Git commit hash

    `uv lock` pins Git dependencies to specific commit hashes in the lockfile.
  </Tab>

  <Tab title="Local Dependencies">
    **From local paths**

    uv caches based on:

    * Last-modified time of source archive (`.whl`, `.tar.gz`)
    * Last-modified time of `pyproject.toml`, `setup.py`, or `setup.cfg` for directories
  </Tab>
</Tabs>

## Cache Commands

### Clearing the Cache

```bash theme={null}
# Remove all cache entries
uv cache clean

# Remove cache entries for specific package
uv cache clean ruff

# Remove all unused cache entries
uv cache prune
```

<CardGroup cols={3}>
  <Card title="clean" icon="trash">
    Removes all cache entries or entries for specific packages
  </Card>

  <Card title="prune" icon="broom">
    Removes only unused entries from previous uv versions
  </Card>

  <Card title="dir" icon="folder">
    Shows the cache directory path
  </Card>
</CardGroup>

### Forcing Revalidation

Force uv to revalidate cached data:

```bash theme={null}
# Revalidate all dependencies
uv sync --refresh

# Revalidate specific package
uv sync --refresh-package ruff

# Force reinstall from cache
uv sync --reinstall
```

<Tabs>
  <Tab title="--refresh">
    Revalidates all cached data but uses cache for unchanged packages.
  </Tab>

  <Tab title="--refresh-package">
    Revalidates only the specified package.
  </Tab>

  <Tab title="--reinstall">
    Forces reinstallation even if packages exist in environment.
  </Tab>
</Tabs>

### Local Directory Dependencies

Local directory dependencies passed explicitly are always rebuilt:

```bash theme={null}
# Always rebuilds current directory
uv pip install .
```

## Dynamic Metadata Caching

By default, uv rebuilds local directory dependencies only when:

* `pyproject.toml`, `setup.py`, or `setup.cfg` changes
* A `src/` directory is added or removed

This heuristic may miss some changes.

### Custom Cache Keys

Incorporate additional information into the cache key with `tool.uv.cache-keys`:

<Tabs>
  <Tab title="Git Commit">
    Rebuild on commit changes:

    ```toml pyproject.toml theme={null}
    [tool.uv]
    cache-keys = [
      { file = "pyproject.toml" },
      { git = { commit = true } }
    ]
    ```
  </Tab>

  <Tab title="Git Tags">
    Rebuild on tag changes:

    ```toml pyproject.toml theme={null}
    [tool.uv]
    cache-keys = [
      { file = "pyproject.toml" },
      { git = { commit = true, tags = true } }
    ]
    ```
  </Tab>

  <Tab title="Additional Files">
    Track requirements.txt:

    ```toml pyproject.toml theme={null}
    [tool.uv]
    cache-keys = [
      { file = "pyproject.toml" },
      { file = "requirements.txt" }
    ]
    ```
  </Tab>
</Tabs>

### Glob Patterns

Use globs to track multiple files:

```toml pyproject.toml theme={null}
[tool.uv]
cache-keys = [
  { file = "**/*.toml" }  # All .toml files
]
```

<Warning>
  Globs can be expensive as uv may need to walk deeply nested directory structures.
</Warning>

### Environment Variables

Invalidate cache on environment variable changes:

```toml pyproject.toml theme={null}
[tool.uv]
cache-keys = [
  { file = "pyproject.toml" },
  { env = "MY_BUILD_VAR" }
]
```

### Directory Existence

Track directory creation/removal:

```toml pyproject.toml theme={null}
[tool.uv]
cache-keys = [
  { file = "pyproject.toml" },
  { dir = "src" }
]
```

<Note>
  The `dir` key only tracks directory creation/removal, not changes within the directory.
</Note>

### Always Rebuild

Force always rebuilding specific packages:

```toml pyproject.toml theme={null}
[tool.uv]
reinstall-package = ["my-package"]
```

## Cache Safety

### Concurrent Access

It's safe to run multiple uv commands concurrently:

* Cache is thread-safe and append-only
* Robust to multiple concurrent readers and writers
* File-based locks prevent concurrent environment modifications

<Warning>
  Never modify the cache directory directly (e.g., by removing files). Always use uv commands.
</Warning>

### Lock Timeouts

Cache-modifying operations block while other uv commands run:

```bash theme={null}
# Default 5-minute timeout
uv cache clean

# Override timeout
UV_LOCK_TIMEOUT=300 uv cache clean

# Force ignore lock (dangerous)
uv cache clean --force
```

## Continuous Integration Caching

Optimize CI caching by storing only built wheels, not pre-built wheels.

### CI Cache Strategy

<Steps>
  <Step title="Run uv commands">
    ```yaml .github/workflows/ci.yml theme={null}
    - run: uv sync
    - run: uv run pytest
    ```
  </Step>

  <Step title="Prune pre-built wheels">
    ```yaml .github/workflows/ci.yml theme={null}
    - run: uv cache prune --ci
    ```
  </Step>

  <Step title="Cache the directory">
    ```yaml .github/workflows/ci.yml theme={null}
    - uses: actions/cache@v4
      with:
        path: ~/.cache/uv
        key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
    ```
  </Step>
</Steps>

### Why Prune Pre-built Wheels?

In CI environments:

* **Re-downloading** pre-built wheels is often faster than restoring from cache
* **Building** from source is expensive and worth caching
* `uv cache prune --ci` removes pre-built wheels but keeps built-from-source wheels

<Tip>
  See the [GitHub Actions integration guide](/integrations/github-actions) for complete CI examples.
</Tip>

## Cache Directory

uv determines the cache directory in this order:

1. **Temporary cache** (if `--no-cache` was requested)
2. **Explicit path** from:
   * `--cache-dir` flag
   * `UV_CACHE_DIR` environment variable
   * `tool.uv.cache-dir` in `pyproject.toml`
3. **System default**:
   * Unix: `$XDG_CACHE_HOME/uv` or `$HOME/.cache/uv`
   * Windows: `%LOCALAPPDATA%\uv\cache`

### View Cache Directory

```bash theme={null}
uv cache dir
```

### Custom Cache Location

```bash theme={null}
# Via environment variable
export UV_CACHE_DIR=/custom/cache/path

# Via flag
uv sync --cache-dir /custom/cache/path

# Via config file
[tool.uv]
cache-dir = "/custom/cache/path"
```

<Warning>
  uv always requires a cache directory. With `--no-cache`, uv uses a temporary cache for that invocation. Use `--refresh` instead to update the persistent cache.
</Warning>

### Performance Considerations

<Info>
  For best performance, the cache directory should be on the same filesystem as Python environments. This allows uv to use hard links instead of copying files.
</Info>

## Cache Versioning

The cache is organized into versioned buckets:

<CardGroup cols={2}>
  <Card title="Wheels" icon="circle">
    Built and downloaded wheel files
  </Card>

  <Card title="Source Distributions" icon="file-archive">
    Downloaded source distributions
  </Card>

  <Card title="Git Repositories" icon="git">
    Cloned Git repositories
  </Card>

  <Card title="Metadata" icon="info">
    Package metadata and manifests
  </Card>
</CardGroup>

### Version Compatibility

Each bucket has a version number:

* Breaking cache format changes increment the version
* Changes within a version are forwards and backwards compatible
* Multiple uv versions can safely share the same cache directory

### Version Changes Example

uv 0.4.13 increased the metadata bucket version from v12 to v13:

* uv 0.4.12 and 0.4.13 can share a cache directory
* The cache may contain duplicate metadata entries
* Old entries from v12 remain but are unused

### Cleaning Old Versions

Remove unused bucket versions:

```bash theme={null}
uv cache prune
```

This is safe to run periodically to reclaim disk space.

## Cache Deduplication

uv uses deduplication to minimize disk usage:

### Hard Links

On Unix systems, uv uses hard links:

* Same file content referenced from multiple locations
* Zero additional disk space
* Requires cache and environment on same filesystem

### Symbolic Links

For Python installations, uv uses symbolic links:

* Points to the actual installation
* Enables transparent upgrades
* Links minor versions to specific patch versions

### Fallback to Copy

When hard links aren't available (different filesystems):

* uv falls back to copying files
* Slower installation
* More disk usage

## Cache Contents

The cache stores:

### Package Artifacts

* **Wheels** - Both downloaded and built from source
* **Source distributions** - Downloaded `.tar.gz`, `.zip` files
* **Git clones** - Repository checkouts at specific commits

### Python Installations

* **Managed Python versions** - Downloaded interpreters
* **Python executables** - Installed to `~/.local/bin` (Unix)

### Metadata

* **Package metadata** - Version info, dependencies, markers
* **Index metadata** - PyPI and custom index data
* **Resolution data** - Cached dependency resolutions

## Troubleshooting

### Cache Issues

If experiencing cache-related problems:

```bash theme={null}
# Clear cache completely
uv cache clean

# Clear specific package
uv cache clean <package-name>

# Force refresh on next install
uv sync --refresh

# Reinstall everything
uv sync --reinstall
```

### Disk Space

Monitor cache size:

```bash theme={null}
# View cache directory
uv cache dir

# Check disk usage
du -sh $(uv cache dir)
```

Reclaim space:

```bash theme={null}
# Remove unused entries
uv cache prune

# Clear everything
uv cache clean
```

### Stale Cache

For local dependencies, ensure cache keys are properly configured:

```toml pyproject.toml theme={null}
[tool.uv]
cache-keys = [
  { file = "pyproject.toml" },
  { git = { commit = true } },
  { file = "src/**/*.py" }  # Track source changes
]
```

## Related Documentation

<CardGroup cols={2}>
  <Card title="Projects" icon="folder" href="/concepts/projects">
    Learn about project environments and how they use the cache
  </Card>

  <Card title="Dependencies" icon="box" href="/concepts/dependencies">
    Understand how dependencies are cached
  </Card>

  <Card title="Python Versions" icon="python" href="/concepts/python-versions">
    Learn where Python installations are cached
  </Card>

  <Card title="CI/CD Integration" icon="github" href="/guides/integration/github">
    Optimize caching in continuous integration
  </Card>
</CardGroup>
