How to Install and Use uv: Fast Python Package Manager

By 

Published on

9 min read

Installing and using uv, a fast Python package manager, on Linux

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

CommandDescription
uv init my-projectCreate a new project with pyproject.toml
uv add requestsAdd a dependency and update the lockfile
uv add --dev pytestAdd a development dependency
uv remove requestsRemove a dependency
uv syncInstall dependencies from the lockfile
uv lockUpdate the lockfile
uv run script.pyRun a command in the project environment
uv venvCreate a virtual environment
uv pip install requestsPip-compatible install interface
uv python install 3.12Install a specific Python version
uv python listList installed and available Python versions
uv tool install ruffInstall 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:

Terminal
curl -LsSf https://astral.sh/uv/install.sh | sh

The 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:

Terminal
uv --version
output
uv 0.11.11

If you prefer to install from a package manager, uv is also available through pip, pipx, and Homebrew:

Terminal
pip install uv
Terminal
pipx install uv
Terminal
brew install uv

On 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:

Terminal
uv self update

Creating a Project

uv init scaffolds a new project with a pyproject.toml, a README.md, a .python-version file, and a starter module:

Terminal
uv init my-project
cd my-project
output
Initialized project `my-project`

The generated pyproject.toml looks like this:

pyproject.tomltoml
[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:

Terminal
uv add requests
output
Resolved 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:

Terminal
uv add --dev pytest ruff

They 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:

Terminal
uv remove requests

uv 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:

Terminal
uv run python main.py
Terminal
uv run pytest

Scripts declared in pyproject.toml under [project.scripts] are also available:

Terminal
uv run my-command

If you prefer the classic workflow, activate the venv yourself:

Terminal
source .venv/bin/activate
python main.py

Either 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:

Terminal
uv sync
output
Resolved 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:

Terminal
uv lock

Use 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:

Terminal
uv venv
output
Using Python 3.12.8
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate

Specify a Python version with --python:

Terminal
uv venv --python 3.11

Specify a different path:

Terminal
uv venv /tmp/myenv

Once the venv exists, use uv pip as a fast replacement for the regular pip commands:

Terminal
uv pip install requests
uv pip install -r requirements.txt
uv pip freeze
uv pip list

The 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:

Terminal
uv python list

Install a specific version:

Terminal
uv python install 3.12
Terminal
uv python install 3.11 3.13

The 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:

Terminal
uv venv --python 3.13

When 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:

Terminal
uv tool install ruff
output
Resolved 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:

Terminal
uv tool list
uv tool upgrade ruff
uv tool uninstall ruff

To run a tool without installing it permanently, use uvx (an alias for uv tool run):

Terminal
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.pypy
# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "requests",
# ]
# ///

import requests

response = requests.get("https://api.github.com")
print(response.status_code)

Run the script with:

Terminal
uv run script.py

uv 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 system
uv 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 .

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page