Skip to main content

uv-prune

Clean uv cache by removing non-hardlinked archive entries.

Problem

uv uses hard links to deduplicate package data across different Python versions and projects. When a package is no longer used by any project, its archive entry remains on disk but is no longer referenced by any other hard link.

uv-prune scans the archive-v0 directory in uv's cache and removes entries whose files have a link count of 1 — meaning they are no longer shared and can be safely deleted.

How it works

For each entry in archive-v0, uv-prune:

  1. Looks for a .dist-info subdirectory to identify the package name and version (e.g. anyio-4.0.0 from anyio-4.0.0.dist-info).
  2. Checks the link count of the METADATA file inside that directory — uv hard-links this file across all environments that share the package.
  3. If the link count is 1, the archive entry is no longer shared and is removed. If it is > 1, the entry is still in use and is kept.
  4. Entries without a .dist-info directory are only warned about by default; pass --include-no-dist-info to remove them too.

All entries are processed in parallel (via Rayon) and reported as a table sorted by package name and version.

Installation

From PyPI (pre-built binary)

Every tagged release publishes platform wheels to PyPI (the compiled binary ships inside a thin Python launcher package, so the bin directory gets a small launcher instead of a full copy of the executable), so install with any Python package manager:

uv tool install uv-prune   # recommended — managed by uv
pipx install uv-prune
pip install uv-prune       # then run `uv-prune`

From GitHub Releases

Pre-built binaries for Linux (x86_64 / aarch64, static musl), macOS (arm64 / x86_64) and Windows (x86_64 / arm64) are attached to each release as .tar.gz / .zip archives together with a SHA256SUMS checksum file.

From source

cargo install uv-prune

Or build manually:

git clone https://github.com/QiE2035/uv-prune
cd uv-prune
cargo build --release

Releases

Pushing a v* tag triggers the publish workflow, which:

  1. Builds release binaries for Linux (musl), macOS and Windows (see the platform table in the workflow).
  2. Creates (or updates) a GitHub Release with the archives and SHA256SUMS.
  3. Builds py3-none-{platform} wheels from those binaries and publishes them to PyPI — via trusted publishing (recommended), or the PYPI_API_TOKEN repository secret as fallback.
git tag v0.1.1
git push origin v0.1.1

The workflow can also be run manually via workflow_dispatch to smoke-test the build matrix without publishing.

--version reports build provenance: local development builds get +dev.<short-sha> (e.g. uv-prune 0.1.0+dev.a1b2c3d4), CI builds of main get +ci.<run-number>.<commit-sha-prefix> (e.g. uv-prune 0.1.0+ci.42.a1b2c3d4), and tagged releases stay clean (uv-prune 0.1.0).

Usage

# Prune with default cache path
uv-prune

# Dry-run — see what would be deleted without actually deleting
uv-prune --dry-run

# Verbose output
uv-prune --verbose

# Custom cache directory
uv-prune --cache-dir /path/to/uv/cache

# Also remove entries without .dist-info (default: warn only)
uv-prune --include-no-dist-info

# Disable timing measurement
uv-prune --no-timing

# Set number of parallel workers
uv-prune --jobs 4

Options

Option Short Description
--cache-dir <DIR> -c UV cache directory (overrides UV_CACHE_DIR env var)
--dry-run -d Show what would be deleted without actually deleting
--verbose -v Enable verbose (debug) output
--include-no-dist-info -i Also remove entries without a .dist-info directory
--jobs <N> -j Number of parallel workers (0 = auto-detect, default)
--no-timing -n Disable timing measurement

Exit Codes

Code Meaning
0 Success (even if entries were skipped/warned)
1 One or more errors occurred while pruning

Environment Variables

Variable Description
UV_CACHE_DIR Override the uv cache directory path
RUST_LOG Control log level (e.g., debug, info, warn, error)

Cache Directory Resolution

  1. --cache-dir CLI argument
  2. UV_CACHE_DIR environment variable
  3. Platform default:
    • Windows: %LOCALAPPDATA%\uv\cache
    • Linux / macOS: ~/.cache/uv (or $XDG_CACHE_HOME/uv)

Output Example

$ uv-prune --dry-run --verbose
[INFO  uv_prune] uv-prune v0.1.0 — cache: /home/user/.cache/uv
[INFO  uv_prune::prune] Pruning archive directory: /home/user/.cache/uv/archive-v0
[INFO  uv_prune::prune] Dry-run mode — no files will be deleted
[INFO  uv_prune::prune] [DRY-RUN] Action    ID                     Version   Name       Detail
[INFO  uv_prune::prune] [DRY-RUN] --------  ---------------------  --------  ---------  -----------------------------------------
[INFO  uv_prune::prune] [DRY-RUN] Deleting  abc123def456789abc     4.0.0     anyio
[DEBUG uv_prune::prune] [DRY-RUN] Keeping   ghi012jkl345mnopqr     2.31.0    requests
[WARN  uv_prune::prune] [DRY-RUN] Skipping  deadbeef               -         -          no .dist-info (use --include-no-dist-info to remove)
[INFO  uv_prune::prune] Done: 3 checked, 1 removed, 2 skipped, 1 no-dist-info, 0 errors
[INFO  uv_prune] Elapsed time: 15.2ms

The report is a table with the following columns:

  • ActionDeleting, Keeping, Skipping or Failed.
  • ID — the uv cache archive directory name; - when it could not be read.
  • Version / Name — parsed from the .dist-info directory name; - when there is no .dist-info.
  • Detail — the reason for Skipping / Failed entries, if any.

In dry-run mode every table line is prefixed with [DRY-RUN] and nothing is actually deleted. Keeping rows are logged at debug level, so pass --verbose to see them, and column widths adapt to the longest entry.

Platform Support

Platform Hard link detection
Windows GetFileInformationByHandlenNumberOfLinks
Linux statst_nlink via std::os::unix::fs::MetadataExt
macOS statst_nlink via std::os::unix::fs::MetadataExt

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

uv_prune-0.1.1-py3-none-win_arm64.whl (603.1 kB view details)

Uploaded Python 3Windows ARM64

uv_prune-0.1.1-py3-none-win_amd64.whl (659.1 kB view details)

Uploaded Python 3Windows x86-64

uv_prune-0.1.1-py3-none-musllinux_1_2_x86_64.whl (819.3 kB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

uv_prune-0.1.1-py3-none-musllinux_1_2_aarch64.whl (740.1 kB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

uv_prune-0.1.1-py3-none-macosx_11_0_arm64.whl (637.0 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

uv_prune-0.1.1-py3-none-macosx_10_12_x86_64.whl (720.8 kB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file uv_prune-0.1.1-py3-none-win_arm64.whl.

File metadata

  • Download URL: uv_prune-0.1.1-py3-none-win_arm64.whl
  • Upload date:
  • Size: 603.1 kB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for uv_prune-0.1.1-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 bc7e8201c3021ea33779c8d76e96c013db3e8e468a7599e6eef88eff77d79611
MD5 6666ee4fc8ce5db09ad6d53a52e210f4
BLAKE2b-256 6f36316d872431e0e49c938d34f228afd6819286eb7f3a17c53af48d9af8ca0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.1-py3-none-win_arm64.whl:

Publisher: publish.yml on QiE2035/uv-prune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uv_prune-0.1.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: uv_prune-0.1.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 659.1 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for uv_prune-0.1.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ba9551828404133c7080b763b7f1636ac9da44decd168d57d3ee3f0079c61fa3
MD5 4b1b7c09c80326875b7b97cc3b55462a
BLAKE2b-256 a9af96750378446feb261cf981dc9a8d2ab6fd15966c0c2953e66694e1f47e8a

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.1-py3-none-win_amd64.whl:

Publisher: publish.yml on QiE2035/uv-prune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uv_prune-0.1.1-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.1-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 353a5b724cd81eadce79936216cc2c56f4cf74fc4f2032b5999d6cbf2245fba8
MD5 6fa50f2c42171f247f9f738008ff3baa
BLAKE2b-256 d883b39373f84b247e3913b8159d89e10dee324bfd114e5dfb18c6e6f6fae24e

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.1-py3-none-musllinux_1_2_x86_64.whl:

Publisher: publish.yml on QiE2035/uv-prune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uv_prune-0.1.1-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.1-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b17641cf70ec558569be5ec5a73ce8fa80b44466f141c96a5a8221320e7b1c81
MD5 788ba59038ba7eaf5d89a366689721a9
BLAKE2b-256 6d80a71a55b2e6b73193bfc068b63296ed03d4de0207ee666fd41b9f184d4bb9

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.1-py3-none-musllinux_1_2_aarch64.whl:

Publisher: publish.yml on QiE2035/uv-prune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uv_prune-0.1.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6d712d42f5081c0db89355d05b54cdf6d09352a2c7895997c416316e85e5bad6
MD5 092bd6df8974734757f14db4038ce0e9
BLAKE2b-256 5ad964cbc8c6320c1ee6ff6e70a07eeaa4bc944ba29dcfc759a02e456a2c3155

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.1-py3-none-macosx_11_0_arm64.whl:

Publisher: publish.yml on QiE2035/uv-prune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uv_prune-0.1.1-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8dc9fbd72bf37b9e8d6fa09897239eb5aaf3dcde0fbff9c8e1ed8fb1234e4e99
MD5 f0edf0ca4772d9b42a2cff19d1999d13
BLAKE2b-256 ed70a00d8a05fe735334dfa4eda1f35b4f0803b770f95882df9f6b1ddda965a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.1-py3-none-macosx_10_12_x86_64.whl:

Publisher: publish.yml on QiE2035/uv-prune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page