TL;DR: uv is an extremely fast Python package manager, written in Rust.

We first released uv in February as a drop-in replacement for common pip workflows.

Today, we're announcing a series of features that extend uv beyond a pip alternative, and into an end-to-end solution for managing Python projects, command-line tools, single-file scripts, and even Python itself.

It's Cargo, for Python: a unified interface that's fast, reliable, and easy to use.


At Astral, we build high-performance developer tools for the Python ecosystem. We're best known for Ruff, an extremely fast Python linter and formatter.

In February, we released uv, an extremely fast Python package installer and resolver, initially designed as a drop-in replacement for common pip workflows.

Today, we're announcing the largest expansion in uv's capabilities since that initial release:

  • End-to-end project management: uv run, uv lock, and uv sync. uv can now generate and install from cross-platform lockfiles based on standards-compliant metadata, making it a high-performance, unified alternative to tools like Poetry, PDM, and Rye.

  • Tool management: uv tool install and uv tool run (aliased to uvx). uv can now install command-line tools in isolated virtual environments and execute one-off commands without explicit installation (e.g., uvx ruff check), making it a high-performance, unified alternative to tools like pipx.

  • Python installation: uv python install. uv can now bootstrap and install Python for you, making it a high-performance, unified alternative to tools like pyenv.

  • Script execution: uv can now manage hermetic, single-file Python scripts with inline dependency metadata based on PEP 723. Execute standalone Python scripts with nothing more than uv run.

...all powered by an extremely fast, cross-platform dependency resolver.

uv poetry pdm uv poetry pdm 0s 50s 100s 7.48s 47.91s 91.91s 0s 20s 40s 60s 0.14s 4.32s 58.61s

Resolving the Transformers project with all optional dependencies enabled, without (top) and with (bottom) caching.

And all covered in new, comprehensive documentation.

Each of these interfaces represent a significant expansion in scope for uv. But what's unique is how they come together. As a whole, they comprise a new, unified toolchain that takes the complexity out of Python development.

Combined with uv pip (which we'll continue to maintain and improve as a first-class feature), uv fits into any Python workflow, from one-off scripting to large, multi-package workspace development.

You can install uv today via our standalone installers, or from PyPI.

curl
win
pip
pipx
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
$ pip install uv
$ pipx install uv

Projects

uv is now capable of managing entire Python projects. If you've used Poetry, PDM, or Rye, you'll find uv's project API to be a familiar alternative.

The project API is built atop Python standards, starting with the use of pyproject.toml for declaring project metadata.

For example, you can run uv init && uv add "fastapi>=0.112" to generate the following:

[project]
name = "hello-world"
version = "0.1.0"
readme = "README.md"
dependencies = ["fastapi>=0.112"]

From there, uv will create a lockfile based on the project's dependencies — here's a snippet:

[[package]]
name = "fastapi"
version = "0.112.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
    { name = "pydantic" },
    { name = "starlette" },
    { name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2c/09/71a961740a1121d7cc90c99036cc3fbb507bf0c69860d08d4388f842196b/fastapi-0.112.1.tar.gz", hash = "sha256:b2537146f8c23389a7faa8b03d0bd38d4986e6983874557d95eed2acc46448ef", size = 291025 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/39/b0/0981f9eb5884245ed6678af234f2cbcd40f44570718caddc0360bdb4015d/fastapi-0.112.1-py3-none-any.whl", hash = "sha256:bcbd45817fc2a1cd5da09af66815b84ec0d3d634eb173d1ab468ae3103e183e4", size = 93163 },
]

[[package]]
name = "fastapi-cli"
version = "0.0.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
    { name = "typer" },
    { name = "uvicorn", extra = ["standard"] },
]
sdist = { url = "https://files.pythonhosted.org/packages/c5/f8/1ad5ce32d029aeb9117e9a5a9b3e314a8477525d60c12a9b7730a3c186ec/fastapi_cli-0.0.5.tar.gz", hash = "sha256:d30e1239c6f46fcb95e606f02cdda59a1e2fa778a54b64686b3ff27f6211ff9f", size = 15571 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/24/ea/4b5011012ac925fe2f83b19d0e09cee9d324141ec7bf5e78bb2817f96513/fastapi_cli-0.0.5-py3-none-any.whl", hash = "sha256:e94d847524648c748a5350673546bbf9bcaeb086b33c24f2e82e021436866a46", size = 9489 },
]

uv's lockfile is a snapshot of the project's fully-resolved dependencies at a moment in time, and ensures that the project's environment is consistent across machines.

Critically, the lockfile is cross-platform, in that it can be used to install a given project on any platform, regardless of where it was generated. uv defines a unique solution for every platform, producing a readable and auditable lockfile that defines exactly which packages will be installed.

For example: if you run uv lock on macOS, uv still generates resolutions for Linux and Windows, even if the set of required dependencies is slightly different on each platform.

And it does this very quickly. uv can resolve the Jupyter project's dependencies in about half a second without any caching (and in around 20 milliseconds with a warm cache).

uv poetry pdm uv poetry pdm 0s 5s 10s 0.57s 7.59s 9.43s 0s 2s 4s 6s 0.02s 0.78s 6.27s

Resolving the Jupyter project without (top) and with (bottom) caching.

The center point of the project API is uv run, which runs a command in the project's environment (without requiring explicit activation of a virtual environment).

uv run is fast enough that every invocation will implicitly re-lock and re-sync the project, ensuring that your environment is up-to-date without the need for manual intervention.

In other words, uv run guarantees that your command is executed in a consistent, locked environment.

Running a FastAPI server via uv run.

With uv run, you don't have to think about activating virtual environments, managing dependencies, or keeping your project up-to-date. It just works.

For more, see the project documentation.

Dependency sources: editables, relative paths, and more

uv is built on Python standards, like PEP 621. But it also adds features that are essential to local development but not covered by the standards, like relative paths and editable dependencies.

So while a project's dependencies (and publishable metadata) are defined in the standards-compliant project.dependencies table, uv allows you to define alternate "sources" for each dependency to use during development via tool.uv.sources.

For example, to use a local, editable version of anyio, you can run uv add --editable ../anyio to produce the following pyproject.toml:

[project]
name = "hello-world"
version = "0.1.0"
readme = "README.md"
dependencies = ["anyio"]

[tool.uv.sources]
anyio = { path = "../anyio", editable = true }

When published to PyPI, the above package would declare a dependency on anyio; but when synced locally via uv run, the editable package at ../anyio would be included in the development environment instead. While the project's dependencies haven't changed, the sources from which those dependencies are drawn have.

For more, see the dependency sources documentation.

Workspaces

Inspired by the Cargo concept of the same name, uv supports workspaces: collections of one or more packages that are managed together.

Think: a FastAPI-based web application, alongside a series of libraries that are versioned and maintained as separate Python packages, all in the same Git repository.

Most large Python projects end up implementing their own version of this concept, with hand-rolled scripts and custom tooling to manage the relationships between packages. uv's workspace API provides a consistent, high-performance, and opinionated solution to the kinds of development challenges that appear at scale.

In a workspace, each package has its own pyproject.toml, but the workspace shares a single lockfile, ensuring that the workspace operates with a consistent set of dependencies.

[project]
name = "fastapi"
version = "0.1.0"
readme = "README.md"
dependencies = ["uvicorn"]

[tool.uv.sources]
uvicorn = { workspace = true }

[tool.uv.workspace]
members = ["libraries/*"]

From the workspace root, you can run commands within any given workspace member with (e.g.) uv run --package fastapi or uv run --package uvicorn.

For more, see the workspace documentation.

Tools

uv is now capable of installing command-line tools (like Ruff) in dedicated, isolated virtual environments (uv tool install) – and running one-off commands without any explicit installation step (uvx).

If you've used pipx or npx, you'll find uv's tool API to be a familiar alternative.

For example, you can run Darren Burns' posting TUI with nothing more than uvx posting.

Running the posting TUI in a terminal via uvx.

The tool API enables you to centrally manage the Python applications that live on your system. For example, you can run uv tool list to view all installed tools (along with the executables they expose), or uv tool upgrade --all to upgrade all installed tools to their latest supported versions.

uv's tool API is extremely fast. Executing commands via uvx adds virtually no overhead.

For more, see the tools documentation.

Python bootstrapping

uv is now capable of installing and managing Python itself, making it entirely self-bootstrapping:

$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ uv python install 3.12

In addition to any explicit uv python invocations, uv can automatically download Python versions as needed (on uv run, uv venv, etc.), e.g., if you're yet to install Python on a machine, or are lacking a specific, requested Python version.

For example, here's the entire sequence of commands necessary to run posting on a fresh Ubuntu Docker image – there are no hidden steps:

$ apt-get update && apt-get install -y curl
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ source $HOME/.cargo/env
$ uvx posting

Upon invoking uvx, uv will automatically install Python 3.12.4, create an ephemeral virtual environment, install the package, and invoke the posting CLI. It's really easy.

Single-file scripts

Finally: uv now includes first-class support for single-file Python scripts with inline dependency metadata, as defined in PEP 723.

For example, consider the following main.py, which fetches the first ten PEPs from the Python Enhancement Proposal index:

import requests
from rich.pretty import pprint

resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])

This script depends on requests and rich, but doesn't include any explicit dependency metadata. Historically, you'd need to manage these dependencies separately from the script, e.g., in a dedicated requirements.txt file.

Now, you can use uv add to automatically embed the dependency declarations within the script itself:

$ uv add --script main.py "requests<3" "rich"
$ cat main.py
# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "requests<3",
#     "rich",
# ]
# ///
import requests
from rich.pretty import pprint

resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])

From there, uv run main.py will execute the script in an isolated, ephemeral virtual environment with all of its dependencies installed.

Running a single-file script with embedded dependencies via uv run.

You can also pull arbitrary dependencies into a uv run invocation via with the --with flag, as in: uv run --with "requests<3" --with rich main.py.

Combined with uv's built-in Python bootstrapping, you can now run hermetic, redistributable, single-file Python scripts with nothing more than uv (and without worrying about virtual environments, dependency management, or Python versions).

For more, see the scripts documentation.

Built for scale

At Astral, one of our guiding principles is: "Design for everyone, build for scale."

We want to build tools that are accessible to beginners, but that can scale up to the needs of the largest Python projects.

With uv, we think we've achieved both.

If you're using uv internally and are interested in collaborating with us as we take on our next set of Python packaging challenges, get in touch. We'd love to build with you.