uv Python Package Manager: Install, Commands and Versions
What uv is, why developers say it is faster than pip and Poetry, and how to install it, manage Python versions, and run the core uv commands.

uv is a Python package and project manager built by Astral, the company behind the Ruff linter, written in Rust to replace pip, pip-tools, pipx, poetry, virtualenv and pyenv with a single, much faster tool. It installs packages, resolves dependencies, manages a project's lockfile, and can even download and switch between Python interpreter versions, all through one uv command line interface.
- Maker: Astral, the team behind the Ruff linter and the ty type checker.
- Install (macOS/Linux):
curl -LsSf https://astral.sh/uv/install.sh | sh - Install (Windows):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" - Core promise: a pip-compatible interface plus project, lockfile and Python-version management, claimed at 10-100x pip's install speed with a warm cache.
- License: dual Apache-2.0 / MIT, per the uv GitHub repository.
What is uv?
uv describes itself, in Astral's own documentation, as "an extremely fast Python package and project manager, written in Rust." It is built by Astral, a company also known for Ruff, a fast Python linter, and ty, a type checker. uv is designed to be a near-total replacement for the patchwork of tools a Python developer previously needed: pip for installing packages, pip-tools or Poetry for locking dependencies, virtualenv for environments, pipx for installing command-line tools, and pyenv for managing multiple Python versions.
Instead of stitching those together, uv folds project management, a pip-compatible command set, standalone script execution, global tool installation, and Python version management into one static binary that installs without needing Rust or Python already present on the machine, and runs on macOS, Linux and Windows.
Why developers are switching from pip, Poetry and conda
The headline reason is speed. Astral's own documentation states that uv is "10-100x faster" than pip, citing benchmarks that install the dependency tree of the Trio library with a warm cache; the project publishes its fuller benchmark methodology in the repository. That speed comes from uv being written in Rust rather than Python, from a global cache that deduplicates packages across every project on a machine instead of re-downloading them each time, and from a dependency resolver designed for the kind of large, nested requirement sets that make pip's resolver slow.
Beyond raw speed, the other draw is consolidation. Teams that previously ran pip plus pip-tools plus virtualenv plus pyenv (or Poetry, or conda, each with its own environment and lockfile behavior) can run uv for all of it, with one lockfile format and one CLI vocabulary. uv's project workflow is comparable to what Poetry and Rye offer, while its Python-version management covers what pyenv does and its one-off tool installs cover what pipx does.
How to install uv
Astral publishes several installation paths, documented in full at docs.astral.sh/uv. The standalone installer scripts are the method Astral recommends, since they don't require an existing Python installation and enable uv's self-updater:
macOS and Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv is also published on PyPI and via Homebrew, for developers who prefer to manage it through an existing package manager:
pipx install uv # Astral's recommended PyPI route, isolates uv
pip install uv # also works, but won't self-update
brew install uv # Homebrew, macOS/Linux
Once installed via the standalone script, uv can update itself in place with uv self update. Versions installed through pip, pipx or Homebrew should instead be upgraded through that same package manager, since self-updates are disabled for those installation methods.
Managing Python versions: uv python install and uv python pin
One of uv's more unusual features for a "package manager" is that it can also install and pin the Python interpreter itself, a job normally left to pyenv or a system installer. uv downloads these interpreters from Astral's python-build-standalone project, since Python.org does not publish official portable binaries, and it will fetch one automatically the first time a project needs a version that isn't already present (automatic downloads can be turned off for locked-down environments).
The core commands, per Astral's Python installation guide:
uv python install # installs the latest Python version
uv python install 3.12 # installs a specific version
uv python install 3.11 3.12 # installs several versions at once
uv python list # lists available and installed versions
uv python pin 3.12 # writes a .python-version file for this project
uv python pin --global 3.12 # sets a global default version
uv python upgrade 3.12 # upgrades one managed version to its latest patch
uv python pin writes the requested version into a .python-version file. uv searches the working directory and its parents, then a user configuration directory, for that file and treats it as the default version request for commands like uv run and uv venv run inside that project, which is what makes it possible to pin a different Python version per project without touching global system settings.
Core uv commands: init, add, run and lock
For an actual Python project (as opposed to a one-off script or global tool), uv centers on a pyproject.toml file plus a lockfile. Astral's project guide walks through the basic loop:
uv init hello-world # scaffolds a new project directory
uv add requests # adds a dependency, updates pyproject.toml, the lockfile and the venv
uv add 'requests==2.31.0' # pin an exact version
uv run example.py # runs a script inside the project's environment
uv run -- flask run -p 3000 # runs an arbitrary command the same way
uv lock --upgrade-package requests # updates one package in the lockfile
uv add is the recommended way to bring in a new dependency rather than installing by hand, because it keeps pyproject.toml and the lockfile in sync automatically. uv run is the command most developers reach for day to day: it creates the project's virtual environment if one doesn't exist yet, makes sure it matches the lockfile, and then executes whatever script or command follows it, which means there's rarely a need to manually activate a virtual environment at all.
uv.lock and reproducible installs
Alongside pyproject.toml, uv's project workflow creates a uv.lock file. According to Astral's documentation on project layout, this is a "universal," cross-platform lockfile: it records exact resolved versions across operating systems, architectures and Python versions in one file, rather than needing separate locks per platform. It's meant to be committed to version control so that every machine and CI runner installing the project gets identical dependency versions, and it's managed entirely by uv, so it shouldn't be hand-edited. uv lock, uv sync and uv run all keep it current automatically; uv sync specifically updates the local .venv directory to match whatever the lockfile specifies.
Running scripts and global tools: uv run, uvx and uv tool install
uv also covers two jobs that sit outside a full project: running a quick standalone script that needs a dependency or two, and installing a command-line tool globally without polluting a project's own environment, which is the role pipx previously played. For a script that declares its own dependencies inline, following the PEP 723 metadata format, uv can add that metadata and then run the script in an isolated, disposable environment built just for it:
uv init --script example.py --python 3.12 # scaffolds inline metadata in the script
uv add --script example.py 'requests<3' 'rich' # declares dependencies inside the script
uv run example.py # installs them and runs the script
uv run --with rich example.py # or add a one-off dependency without editing the script
The resulting file carries a small comment block at the top (# /// script ... dependencies = [...] ///) that any later uv run reads automatically, so a single .py file stays fully reproducible without needing its own pyproject.toml.
For command-line tools published as Python packages, such as Ruff itself, uvx runs one in a temporary, throwaway environment without installing it anywhere permanent:
uvx ruff check # runs Ruff once, in an isolated temp environment
uv tool install ruff # installs it persistently, puts `ruff` on PATH
uvx is shorthand for uv tool run, and is the closest uv equivalent to pipx run, while uv tool install mirrors a persistent pipx install.
The pip-compatible interface: uv venv and uv pip install
For developers who aren't ready to adopt uv's full project workflow, or who are working inside an existing pip-based setup, uv also ships a command set that mirrors pip and virtualenv closely enough to be a near drop-in replacement, documented at docs.astral.sh/uv/pip:
uv venv # creates a .venv in the current directory
uv venv --python 3.11 # creates one against a specific Python version
uv pip install ruff # installs a package into that environment
source .venv/bin/activate # macOS/Linux
.venv\Scripts\activate # Windows PowerShell
This is the easiest on-ramp for teams migrating an existing codebase: the day-to-day pip install habit barely changes, only the speed does, and uv venv will install a managed Python interpreter automatically if the environment needs one that isn't already on the machine.
| Feature | uv | pip | Poetry | conda |
|---|---|---|---|---|
| Language it's written in | Rust | Python | Python | Python/C |
| Install speed (per Astral's benchmarks) | 10-100x pip, warm cache | Baseline | Comparable to pip for raw installs | Can be slower, especially solving environments |
| Lockfile | Universal uv.lock | None built in (needs pip-tools) | poetry.lock | conda-lock (separate tool) |
| Manages Python versions | Yes, via uv python | No | No | Yes |
| Installs non-Python dependencies | No | No | No | Yes (C libraries, etc.) |
| Global tool installs (pipx-style) | Yes, uv tool install | No | No | No |
| Package source | PyPI and custom indexes | PyPI and custom indexes | PyPI and custom indexes | conda channels (plus pip) |
The practical takeaway: pip remains the baseline every Python installation ships with, and pip's own documentation describes it simply as "the package installer for Python." uv is positioned as a faster, more batteries-included layer that can sit on top of or replace that baseline, while conda's niche — bundling non-Python binaries and scientific libraries — is one uv does not attempt to cover. Background on the broader packaging landscape, including how resolvers and lockfiles fit together, is covered by the Python Packaging Authority's own guide at packaging.python.org, and more general history on Python's installer tooling is on Wikipedia.
uv in CI and automated workflows
Because uv resolves and installs from a committed lockfile, it fits naturally into CI pipelines where reproducibility matters as much as speed: a uv sync against a locked uv.lock gives every runner the same dependency graph instead of re-resolving it on each build. That same lockfile discipline is the same principle behind GitHub's own move to lock dependencies in its Actions workflows, covered in Pandromeda's report on GitHub Actions workflow lockfiles going generally available. Teams building or evaluating AI coding agents that shell out to run tests and installs, a workflow compared in Pandromeda's Claude Code vs. Gemini CLI comparison, are increasingly finding uv's speed cuts meaningful time off repeated dependency installs inside those agent loops.
Common friction points when adopting uv
A few habits catch developers moving from pip or Poetry. First, the .venv directory uv creates is meant to be left alone and not edited with plain pip install once a project is managed by uv, since that can desync it from the lockfile; Astral's documentation explicitly calls out uv pip install against a project's .venv as something to avoid once a project uses the full uv add/uv sync workflow. Second, uv.lock is described as universal across platforms, so there's no need to generate or commit separate lockfiles per operating system, unlike some older pip-tools setups. Third, developers who skip uv python pin should expect uv to default to the latest available Python version whenever it needs to install one, which can surprise a project that implicitly depended on an older interpreter.
What to do next
For a single existing project, the lowest-friction starting point is the pip-compatible path: run uv venv, activate it, and swap pip install for uv pip install to get the speed benefit without changing a workflow. For a new project, or one ready to commit to a lockfile, uv init followed by uv add for each dependency and uv run for execution covers most day-to-day needs, with uv python pin used once up front to lock in the interpreter version. The full command reference, including less common flags for workspaces, indexes and tool installs, is maintained by Astral, with the source and issue tracker on the project's GitHub page.
Frequently asked questions
What is uv in Python?
uv is a Python package and project manager made by Astral, the company behind the Ruff linter. It is written in Rust and handles dependency installation, virtual environments, project lockfiles, running scripts and tools, and installing Python versions themselves, aiming to replace pip, pip-tools, pipx, poetry, virtualenv and pyenv with one tool.
How do I install uv?
On macOS or Linux, run curl -LsSf https://astral.sh/uv/install.sh | sh. On Windows, run powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" in PowerShell. uv is also installable via pipx install uv, pip install uv, or brew install uv.
How do I install and pin a Python version with uv?
Use uv python install 3.12 to download a specific interpreter version, and uv python pin 3.12 to write a .python-version file that sets the default Python version uv uses for that project. Add --global to uv python pin to set a system-wide default instead.
Is uv a replacement for pip?
uv ships a pip-compatible command set, including uv venv to create a virtual environment and uv pip install to install packages into it, so it can be used as a faster drop-in replacement for pip and virtualenv without changing an existing workflow.
What is uv.lock and why does it matter?
uv.lock is the lockfile uv creates for a project, recording exact resolved dependency versions across operating systems, architectures and Python versions in a single universal file. It is meant to be committed to version control so installs stay reproducible across machines and CI.
How is uv different from Poetry or conda?
uv's project workflow (dependency management plus a lockfile) is similar in purpose to Poetry's, but uv is written in Rust and adds Python version management and global tool installs that Poetry doesn't handle. Unlike conda, uv only manages Python packages and interpreters, not non-Python system libraries.
Sources
- Astral: uv documentationdocs.astral.sh
- uv on GitHub (astral-sh/uv)github.com
- pip documentation (pip.pypa.io)pip.pypa.io
- Python Packaging User Guide (packaging.python.org)packaging.python.org
- Wikipedia: pip (package manager)en.wikipedia.org
Felix Moreau writes Pandromeda's software coverage and how-to guides. He covers Windows, macOS and Linux updates, the apps people rely on, emulators and developer tools, and turns official documentation into clear, numbered steps that work on the current version.


