Skip to content

jmpnop/uv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8,938 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

uv

uv image image image Actions status Discord

An extremely fast Python package and project manager, written in Rust.

Installation

macOS and Linux:

curl -LsSf https://github.com/jmpnop/uv/releases/latest/download/uv-installer.sh | sh

Windows:

powershell -ExecutionPolicy ByPass -c "irm https://github.com/jmpnop/uv/releases/latest/download/uv-installer.ps1 | iex"

Prebuilt binaries for Linux (x86_64, aarch64), macOS (Intel, Apple Silicon), and Windows (x86_64) are published on every tag. To pin to a specific version:

UV_VERSION=v0.11.7-fork.1 curl -LsSf https://github.com/jmpnop/uv/releases/download/v0.11.7-fork.1/uv-installer.sh | sh

Update to the latest fork release in-place:

uv self update

uv self update on this fork queries github.com/jmpnop/uv/releases only — never astral's upstream. It's a direct replacement that downloads the installer from the latest release tag and re-runs it against the same directory the current uv binary is installed in.

Uninstall by removing the binary (default location ~/.local/bin/uv). Clean up uv's managed state with uv cache clean && rm -rf "$(uv python dir)" "$(uv tool dir)".

Shows a bar chart with benchmark results.

Installing Trio's dependencies with a warm cache.

Highlights

uv is backed by Astral, the creators of Ruff and ty.

Extra features in this fork

Fork logo

This repository is a fork of astral-sh/uv with additional features layered on top. Everything from upstream continues to work unchanged — the sections below describe only what's been added here.

Custom Python indexes ([[python-indexes]])

uv's managed-Python feature (uv python install) ships with a hard-coded list of distributions from python-build-standalone. This fork lets users point uv at additional JSON manifests that follow the same schema, either to augment the built-in list with custom builds or to replace it entirely.

Configuration surface

TOML (uv.toml or pyproject.toml's [tool.uv]):

[[python-indexes]]
name = "mycorp"
url = "https://python.mycorp.example.com/versions.json"
# default = true  # set to replace the built-in list

Environment variable (equivalent to one [[python-indexes]] entry):

export UV_PYTHON_INDEX="https://python.mycorp.example.com/versions.json"

CLI flag (repeatable, available on uv python list, find, install, upgrade, pin):

uv python install 3.14 --python-index https://experimental.example.com/jit/versions.json

Use cases

  1. Corporate fork / internally-signed builds. Platform teams that build and sign their own Python distributions can publish a manifest alongside the binaries and have every developer's uv python install pick them up transparently without changing build scripts or docs.
  2. Experimental Python builds. Evaluating a JIT, free-threaded, or LTO-tuned build that hasn't landed upstream yet. Point a dev workstation at the experimental index for the duration of the evaluation; remove or toggle default = true when finished.
  3. Air-gapped CI. CI runners that cannot reach github.com/releases/... host the same distributions on an internal file or HTTP server. Configure the index URL once in shared uv.toml and every subsequent install hits the internal mirror.
  4. One-off version override. Project X needs a patched 3.12.3 build. Set the override in the project's uv.toml only; other projects on the same machine continue using upstream.
  5. Multi-tier layering. A system-wide uv.toml defines name = "mycorp" at the corporate mirror. A user's home config redefines name = "mycorp" to their own fork during local development without touching the system config.

Semantics

  • Layered config. Higher-priority layers (CLI > env > project > user > system) override lower-priority layers by name. A name = "mycorp" entry in the project config replaces the user or system name = "mycorp" entry; distinct names coexist.
  • Merge with built-in. By default, custom indexes add to the built-in list. Entries with the same PythonInstallationKey (implementation + version + platform) as a built-in override it. Entries with a distinct key coexist.
  • Full replacement. A single [[python-indexes]] entry with default = true suppresses the built-in list entirely. Useful for air-gapped environments.
  • Precedence on find(). After merging sources, find() returns the highest-versioned entry matching a request regardless of which source contributed it — a lower-versioned custom entry never shadows a higher-versioned built-in one.

Safety invariants

  • HTTPS required. Index JSON must be served over HTTPS. Plain HTTP is rejected unless the host is loopback (localhost, 127.0.0.0/8, or ::1), which emits a one-shot warning for local testing.
  • Per-entry sha256 required. Every entry must carry a 64-character hex sha256. Missing or malformed hashes fail fast at load time with a clear error instead of surfacing later as an opaque HashMismatch at extraction time.
  • Scheme allow-list. Only http, https, and file schemes are accepted. Typos like ftp:// or mailto: are rejected up-front rather than silently interpreted as filesystem paths.
  • Reserved $ prefix. Names starting with $ are reserved for internally-synthesized entries ($env from the env var, $cli-0, $cli-1, etc. from CLI flags). User-supplied TOML names starting with $ are rejected at deserialization.
  • At-most-one default. Multiple [[python-indexes]] with default = true across the merged configuration is an error — exactly one index may fully replace the built-in list.
  • Per-file uniqueness. Duplicate names within a single config file are errors; cross-file duplicates are resolved by higher-layer-wins.
  • Offline respect. In --offline mode, HTTP sources are skipped with a visible warn_user_once! warning naming each skipped index — so uv run against an already-installed interpreter still succeeds without the user being confused about why their index "vanished."
  • --only-system / --only-installed skip fetching. uv python list --only-system and --only-installed don't consult downloads, so the remote index isn't fetched in those modes.

Error UX

Every error variant names the offending index (by name) so the user knows which entry to fix:

  • UnsupportedIndexScheme { name, scheme } — scheme outside http/https/file.
  • CustomIndexInsecureScheme { name, url } — plain HTTP to a non-loopback host.
  • CustomIndexMissingHash { name, key } — entry has no sha256.
  • CustomIndexInvalidHash { name, key, value }sha256 is the wrong length or non-hex.
  • MultipleDefaultPythonIndexes(count, names) — more than one default = true.
  • DuplicatePythonIndexName(name) — same name twice in one config file.
  • InvalidFileUrl(url) — malformed file:// URL.

Names starting with $ fail at TOML parse time via a serde Error::custom message rather than a dedicated enum variant — the TOML diagnostic points at the offending [[python-indexes]] block and reads: "Python index name $x uses the reserved $ prefix; $-prefixed names are synthesized internally (e.g. for UV_PYTHON_INDEX or --python-index)."

Index format

Identical to python-build-standalone's download-metadata.json. Example entry:

{
  "cpython-3.14.0-linux-x86_64-gnu": {
    "name": "cpython",
    "arch": { "family": "x86_64", "variant": null },
    "os": "linux",
    "libc": "gnu",
    "major": 3,
    "minor": 14,
    "patch": 0,
    "prerelease": "",
    "url": "https://python.mycorp.example.com/cpython-3.14.0-linux-x86_64-gnu.tar.gz",
    "sha256": "c3223d5924a0ed0ef5958a750377c362d0957587f896c0f6c635ae4b39e0f337",
    "variant": null,
    "build": "20260101"
  }
}

Test coverage

  • 23+ integration tests in crates/uv/tests/it/python_list.rs and python_find.rs covering: happy-path merge, same-key override, higher-version protection, multiple defaults, missing / malformed / null sha256, unsupported scheme, plain-HTTP rejection, loopback exception (IPv4+localhost), IPv6 loopback, file:// URLs, file-not-found, duplicate names, unknown TOML fields, reserved $ prefix, CLI+config merge, env var, offline skip, malformed URLs.
  • Unit tests for PythonInstallMirrors::combine (layer dedup) and is_loopback_http (all host kinds).

Relation to existing options

  • python-install-mirror / UV_PYTHON_INSTALL_MIRROR — swaps just the hostname of built-in python-build-standalone download URLs. Narrower scope.
  • python-downloads-json-url / UV_PYTHON_DOWNLOADS_JSON_URL — replaces the built-in manifest with a single JSON URL. Effectively equivalent to a single [[python-indexes]] entry with default = true. Kept for backwards compatibility.

Documentation

uv's documentation is available at docs.astral.sh/uv.

Additionally, the command line reference documentation can be viewed with uv help.

Features

Projects

uv manages project dependencies and environments, with support for lockfiles, workspaces, and more, similar to rye or poetry:

$ uv init example
Initialized project `example` at `/home/user/example`

$ cd example

$ uv add ruff
Creating virtual environment at: .venv
Resolved 2 packages in 170ms
   Built example @ file:///home/user/example
Prepared 2 packages in 627ms
Installed 2 packages in 1ms
 + example==0.1.0 (from file:///home/user/example)
 + ruff==0.5.0

$ uv run ruff check
All checks passed!

$ uv lock
Resolved 2 packages in 0.33ms

$ uv sync
Resolved 2 packages in 0.70ms
Checked 1 package in 0.02ms

See the project documentation to get started.

uv also supports building and publishing projects, even if they're not managed with uv. See the publish guide to learn more.

Scripts

uv manages dependencies and environments for single-file scripts.

Create a new script and add inline metadata declaring its dependencies:

$ echo 'import requests; print(requests.get("https://astral.sh"))' > example.py

$ uv add --script example.py requests
Updated `example.py`

Then, run the script in an isolated virtual environment:

$ uv run example.py
Reading inline script metadata from: example.py
Installed 5 packages in 12ms
<Response [200]>

See the scripts documentation to get started.

Tools

uv executes and installs command-line tools provided by Python packages, similar to pipx.

Run a tool in an ephemeral environment using uvx (an alias for uv tool run):

$ uvx pycowsay 'hello world!'
Resolved 1 package in 167ms
Installed 1 package in 9ms
 + pycowsay==0.0.0.2
  """

  ------------
< hello world! >
  ------------
   \   ^__^
    \  (oo)\_______
       (__)\       )\/\
           ||----w |
           ||     ||

Install a tool with uv tool install:

$ uv tool install ruff
Resolved 1 package in 6ms
Installed 1 package in 2ms
 + ruff==0.5.0
Installed 1 executable: ruff

$ ruff --version
ruff 0.5.0

See the tools documentation to get started.

Python versions

uv installs Python and allows quickly switching between versions.

Install multiple Python versions:

$ uv python install 3.12 3.13 3.14
Installed 3 versions in 972ms
 + cpython-3.12.12-macos-aarch64-none (python3.12)
 + cpython-3.13.9-macos-aarch64-none (python3.13)
 + cpython-3.14.0-macos-aarch64-none (python3.14)

Download Python versions as needed:

$ uv venv --python 3.12.0
Using Python 3.12.0
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate

$ uv run --python pypy@3.8 -- python --version
Python 3.8.16 (a9dbdca6fc3286b0addd2240f11d97d8e8de187a, Dec 29 2022, 11:45:30)
[PyPy 7.3.11 with GCC Apple LLVM 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>>

Use a specific Python version in the current directory:

$ uv python pin 3.11
Pinned `.python-version` to `3.11`

See the Python installation documentation to get started.

The pip interface

uv provides a drop-in replacement for common pip, pip-tools, and virtualenv commands.

uv extends their interfaces with advanced features, such as dependency version overrides, platform-independent resolutions, reproducible resolutions, alternative resolution strategies, and more.

Migrate to uv without changing your existing workflows — and experience a 10-100x speedup — with the uv pip interface.

Compile requirements into a platform-independent requirements file:

$ uv pip compile requirements.in \
   --universal \
   --output-file requirements.txt
Resolved 43 packages in 12ms

Create a virtual environment:

$ uv venv
Using Python 3.12.3
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate

Install the locked requirements:

$ uv pip sync requirements.txt
Resolved 43 packages in 11ms
Installed 43 packages in 208ms
 + babel==2.15.0
 + black==24.4.2
 + certifi==2024.7.4
 ...

See the pip interface documentation to get started.

Contributing

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in the project. See the contributing guide to get started.

FAQ

How do you pronounce uv?

It's pronounced as "you - vee" (/juː viː/)

How should I stylize uv?

Just "uv", please. See the style guide for details.

What platforms does uv support?

See uv's platform support document.

Is uv ready for production?

Yes, uv is stable and widely used in production. See uv's versioning policy document for details.

Acknowledgements

uv's dependency resolver uses PubGrub under the hood. We're grateful to the PubGrub maintainers, especially Jacob Finkelman, for their support.

uv's Git implementation is based on Cargo.

Some of uv's optimizations are inspired by the great work we've seen in pnpm, Orogene, and Bun. We've also learned a lot from Nathaniel J. Smith's Posy and adapted its trampoline for Windows support.

License

uv is licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in uv by you, as defined in the Apache-2.0 license, shall be dually licensed as above, without any additional terms or conditions.

About

uv fork with extra features (custom Python indexes)

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors