How to Install and Use uv: Fast Python Package Manager
If you have worked with Python for a while, you have probably juggled pip, virtualenv, pip-tools, pipx, and pyenv just to keep a few projects running. Each tool does one thing, and wiring them together is slow and fragile. uv is a single binary that replaces all of them. It is written in Rust, published by Astral (the team behind ruff), and is typically ten to a hundred times faster than pip for common workflows.
This guide explains how to install uv on Linux, create and manage Python projects with it, add dependencies, work with virtual environments, and install specific Python versions.
Quick Reference
| Command | Description |
|---|---|
uv init my-project |
Create a new project with pyproject.toml
|
uv add requests |
Add a dependency and update the lockfile |
uv add --dev pytest |
Add a development dependency |
uv remove requests |
Remove a dependency |
uv sync |
Install dependencies from the lockfile |
uv lock |
Update the lockfile |
uv run script.py |
Run a command in the project environment |
uv venv |
Create a virtual environment |
uv pip install requests |
Pip-compatible install interface |
uv python install 3.12 |
Install a specific Python version |
uv python list |
List installed and available Python versions |
uv tool install ruff |
Install a CLI tool globally |
uvx ruff check . |
Run a tool without installing it permanently |
Installing uv
The recommended install path on Linux is the standalone script from Astral. It downloads a prebuilt binary, places it in ~/.local/bin, and does not require Python to be installed first:
curl -LsSf https://astral.sh/uv/install.sh | shThe script prints where it put the binary and whether it updated your shell rc file. Reload your shell or run source ~/.bashrc so the new PATH takes effect, then verify the install:
uv --versionuv 0.11.11
If you prefer to install from a package manager, uv is also available through pip, pipx, and Homebrew:
pip install uvpipx install uvbrew install uvOn Ubuntu, Debian, and Derivatives, pip may refuse a system-wide install because the Python environment is marked as externally managed. In that case, use pipx install uv or the standalone installer.
If you installed uv with the standalone installer, update it to the latest release with:
uv self updateCreating a Project
uv init scaffolds a new project with a pyproject.toml, a README.md, a .python-version file, and a starter module:
uv init my-project
cd my-projectInitialized project `my-project`
The generated pyproject.toml looks like this:
[project]
name = "my-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []uv has not created a virtual environment yet. That happens the first time you add a dependency or run a command in the project.
Adding and Removing Dependencies
To add a package, use uv add:
uv add requestsResolved 5 packages in 320ms
Installed 5 packages in 45ms
+ certifi==2025.1.31
+ charset-normalizer==3.4.1
+ idna==3.10
+ requests==2.32.3
+ urllib3==2.3.0
On the first run, uv creates a .venv directory in the project root, resolves the dependency graph, writes a uv.lock file that pins every package and its transitive dependencies, and installs everything into the venv. The requests line is also added to pyproject.toml under dependencies.
Development-only dependencies go into a separate group with --dev:
uv add --dev pytest ruffThey are recorded under a dev dependency group in pyproject.toml and are installed into the same venv, but they are excluded when your project is published or installed as a library.
Remove a dependency with uv remove:
uv remove requestsuv updates pyproject.toml, updates uv.lock, and uninstalls the package along with any dependencies that are no longer needed.
Running Code in the Project Environment
You do not have to activate the virtual environment manually. uv run executes a command inside the project venv and syncs dependencies first if needed:
uv run python main.pyuv run pytestScripts declared in pyproject.toml under [project.scripts] are also available:
uv run my-commandIf you prefer the classic workflow, activate the venv yourself:
source .venv/bin/activate
python main.pyEither approach works, but uv run has the advantage of keeping the environment in sync with uv.lock every time you invoke it.
Syncing and Reproducing an Environment
When you clone a project that uses uv, run uv sync to install exactly the versions pinned in uv.lock:
uv syncResolved 12 packages in 5ms
Installed 12 packages in 110ms
uv sync is deterministic: given the same uv.lock, it produces the same environment on any machine. This is the command to run in CI, in Docker builds, and on every fresh checkout.
If pyproject.toml changes but the lockfile is out of date, refresh the lock with:
uv lockUse uv lock --upgrade to bump every dependency to the latest version allowed by the version constraints in pyproject.toml, and uv lock --upgrade-package requests to bump a single package.
Working with Virtual Environments Directly
uv can also be used as a faster drop-in for virtualenv. To create a standalone venv in the current directory:
uv venvUsing Python 3.12.8
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
Specify a Python version with --python:
uv venv --python 3.11Specify a different path:
uv venv /tmp/myenvOnce the venv exists, use uv pip as a fast replacement for the regular pip commands:
uv pip install requests
uv pip install -r requirements.txt
uv pip freeze
uv pip listThe uv pip interface is intentionally compatible with pip, which makes it easy to adopt uv in existing projects without restructuring them as pyproject.toml-based projects.
For a refresher on classic virtual environments, see the guide on Python virtual environments .
Installing and Managing Python Versions
uv can download and manage Python interpreters without touching your system Python. List the versions available and installed:
uv python listInstall a specific version:
uv python install 3.12uv python install 3.11 3.13The downloaded interpreters live under ~/.local/share/uv/python/ and are independent of the system package manager. To use a specific version in a project, set it in the .python-version file or pass --python when creating the venv:
uv venv --python 3.13When uv run starts a project, it reads .python-version and the requires-python constraint in pyproject.toml, then picks or downloads a matching interpreter automatically.
Installing CLI Tools
uv ships with a tool manager similar to pipx. It installs Python-based CLIs in isolated environments so they do not pollute your system Python:
uv tool install ruffResolved 1 package in 80ms
Installed 1 package in 12ms
+ ruff==0.9.2
Installed 1 executable: ruff
The ruff binary is now on your PATH. List, upgrade, or remove tools:
uv tool list
uv tool upgrade ruff
uv tool uninstall ruffTo run a tool without installing it permanently, use uvx (an alias for uv tool run):
uvx ruff check .uvx downloads the tool into a cached environment, runs it, and reuses the cache on subsequent invocations. This is the fastest way to try a CLI without making it permanent.
Running Single-File Scripts
A Python script can declare its dependencies inline with a PEP 723 comment block. uv run reads that block and sets up an ephemeral environment before executing the script:
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests",
# ]
# ///
import requests
response = requests.get("https://api.github.com")
print(response.status_code)Run the script with:
uv run script.pyuv creates a temporary venv, installs requests, runs the script, and keeps the environment in a cache for next time. This pattern is useful for small utilities and one-off automation where a full project is overkill.
Troubleshooting
uv: command not found after install
The installer places the binary in ~/.local/bin, which may not be on your PATH. Add it in your shell rc file: export PATH="$HOME/.local/bin:$PATH", then reload the shell. Verify with which uv.
Installation fails with “error: externally-managed-environment”
This message comes from system pip, not from uv. Use pipx install uv or the standalone installer instead. Installing Python packages into the system Python is discouraged on modern Ubuntu and Debian releases.
uv sync installs different versions than expected
Check that uv.lock is committed to your repository. Without the lockfile, uv sync falls back to resolving from pyproject.toml and may pick newer versions. Commit uv.lock to keep environments reproducible across machines.
uv cannot find a suitable Python interpreter
Run uv python install 3.12 (or whichever version your project requires) to let uv download a matching interpreter. The requires-python field in pyproject.toml tells uv which versions are acceptable.
Permission denied when installing to the systemuv does not need root. If a command prompts for sudo, the destination path is wrong. Use a project virtual environment or uv tool install for CLIs instead of writing to system directories.
FAQ
How is uv different from pip?pip installs packages into an existing Python environment. uv is a full project manager: it creates and manages virtual environments, locks dependencies, installs Python interpreters, and runs scripts and tools. uv pip also provides a drop-in pip-compatible command for teams that want just the speed without adopting the full workflow.
Does uv replace Poetry or Hatch?
For most projects, yes. uv reads the standard pyproject.toml format used by Poetry and Hatch, manages lockfiles, and handles dependency groups. If you depend on specific features of Poetry plugins or Hatch build hooks, evaluate those needs before migrating.
Is uv compatible with existing requirements.txt workflows?
Yes. uv pip install -r requirements.txt works as a faster replacement for pip install -r, and uv pip compile generates a pinned requirements file from your unpinned input, similar to pip-compile from pip-tools.
Can I use uv with Docker?
Yes, and it is a good fit. The recommended pattern is to copy pyproject.toml and uv.lock first, run uv sync --frozen --no-install-project to install dependencies, then copy the rest of the source and run uv sync --frozen. This keeps the dependency layer cached across builds.
Where does uv store downloaded interpreters and package cache?
Interpreters go under ~/.local/share/uv/python/ and the package cache lives in ~/.cache/uv/. Both paths respect the XDG environment variables, so you can override them by setting XDG_DATA_HOME and XDG_CACHE_HOME.
Conclusion
uv rolls together the jobs that previously required pip, virtualenv, pip-tools, pipx, and pyenv into one fast binary. The speed is the headline feature, but the real payoff is a single, consistent workflow for projects, tools, scripts, and Python versions.
For related Python tooling on Linux, see the guide on installing Python on Ubuntu 24.04 and the guide on Python virtual environments .
![]()
