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.2
git push origin v0.1.2

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.2-py3-none-win_arm64.whl (603.1 kB view details)

Uploaded Python 3Windows ARM64

uv_prune-0.1.2-py3-none-win_amd64.whl (659.2 kB view details)

Uploaded Python 3Windows x86-64

uv_prune-0.1.2-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.2-py3-none-musllinux_1_2_aarch64.whl (740.3 kB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

uv_prune-0.1.2-py3-none-macosx_10_12_x86_64.whl (720.7 kB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: uv_prune-0.1.2-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.2-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 0e346236a0ad33d1dd162ba6a91b159e1358980ae88d155b117201dd64738c52
MD5 501838ed882c760aa7dd652ba0aab7c5
BLAKE2b-256 7297005d167b1d1c327a0069e5b7d1394c95ad6ca07d3043aa6ed5421b26aa50

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.2-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.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: uv_prune-0.1.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 659.2 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.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 c64e2b3dea459662254df7bb559a633a6895291699bec3d834eac1d4899d7fb0
MD5 7e4d1e0be055b505011045a94291940a
BLAKE2b-256 0b65b5aff7858a0ae43fc7e9d4f5761b3e07eb7cc137f72cba056b1c8de01289

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.2-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.2-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.2-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5b22e406e18673ba34493b13978b3e580e5313a1a9b91cf6ecbee5845fbe37d8
MD5 a8b7f5371d854dc29b3d0c4e4e4475eb
BLAKE2b-256 0ea5c4546ebd87ef5b854d7ae3e7ce6c93c11c6c00d10169f4061da74369b595

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.2-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.2-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.2-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f9bebecd8e32205852172e0f03d2a74b075fb3aa718f47b0acdafe0601d1ea54
MD5 bd0e8f7251e9e653a654b5b4b848695a
BLAKE2b-256 43c40f8d75b6b10e54aefbc4bd30ddf4e9abf795fdb7f84aac608499eae2d1fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.2-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.2-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.2-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 af76233a63e93cdbb680bad5e74fdf132567cb7d6d1d02aafb249d6f3f2fd74a
MD5 30421991d329ea94743f14cea4bea008
BLAKE2b-256 f199baa7c6da470ea0459aeabee7275f05c87e2e282483382ac8b9b7413209f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.2-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.2-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for uv_prune-0.1.2-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3faba83624ecf684f58d7f7fd2248fa7c7f9971218d2e501054ae3fefc8fa740
MD5 d2ef8b93c969addacdcccb6cd85e2562
BLAKE2b-256 0e95c65f51f083b857fe31f57abc3fad7672b6e21bb254c573572734451bfd51

See more details on using hashes here.

Provenance

The following attestation bundles were made for uv_prune-0.1.2-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