You have a thirty-second `pip install` running in your CI pipeline. The team lead keeps asking why the build is slow. Meanwhile, Astral’s uv — a single 2MB Rust binary — installs packages in under a second and replaces pip, pip-tools, pyenv, Poetry, and virtualenv in one shot. The 0.10.0 release makes the case even stronger: stable Python upgrades, workspace discovery, and a new `–bounds` flag that finally makes `uv add` safe for lockfiles. Here is what changed and why teams still on pip should make the switch now.
In this tutorial, you will learn to:
- Understand what uv 0.10.0 changes and whether they affect your projects
- Use the stable
uv python upgradecommand to keep Python versions current - Navigate workspace changes with
uv workspace listanduv workspace dir - Apply the
--boundsflag to safely add dependencies to a locked project - Migrate an existing pip + venv project to uv in under ten minutes
Page Contents
Prerequisites
Basic command-line familiarity. Python 3.9+ installed. No prior uv experience needed — this is a ground-up explainer. If you want a refresher on Python tooling before diving in, start with the Python learning path.
What Is uv and Why Does It Matter?
uv is a Python package manager built by Astral — the same team behind Ruff. It is written in Rust, installs packages 10 to 100 times faster than pip, and consolidates a fragmented Python tooling landscape. One binary replaces:
pipandpip-tools— package installation and lockfilesvirtualenvandvenv— virtual environment managementpyenv— Python version managementPoetry,Pipenv,PDU— project managementpipx— global tool installation
The speed is not a benchmark trick. uv rewrites resolution in Rust, uses a global cache, and symlinks by default. No more watching a progress bar for thirty seconds. For teams, this means CI pipelines that drop 50–80% of their install time, just from swapping pip install for uv pip install.
uv 0.10.0 by the Numbers
| Item | Detail |
|---|---|
| Release date | February 2026 |
| Python upgrades | Now stable (preview removed) |
| New workspace commands | uv workspace list, uv workspace dir |
uv add --bounds | Stabilized (was preview) |
| uv format Ruff version | 0.15.0 with 2026 style guide |
| Breaking: venv requires –clear | Existing venvs not auto-deleted |
| Breaking: multiple default indexes | Now an error (was a warning) |
| Python 3.8 support | Dropped |
Breaking Changes in 0.10.0
1. uv venv Now Requires --clear to Remove Existing Environments
Previously, running uv venv in a directory with an existing virtual environment would silently delete it and create a fresh one. In 0.10.0, this behavior is changed: uv will error if an existing venv is found unless you explicitly pass --clear:
# Old behavior (pre-0.10): silently replaces existing venv
uv venv
# New behavior (0.10+): errors if .venv already exists
uv venv
# Error: Virtual environment already exists at ...
# Use --clear to remove it first: uv venv --clear
# Explicitly clear and recreate
uv venv --clear
This is a safeguard against accidental data loss in CI scripts or shared development environments. Any automation script that runs uv venv without --clear will break — update those scripts now.
2. Multiple Indexes with default = true Is Now an Error
If your pyproject.toml or uv.toml has two package indexes marked default = true, uv used to emit a warning. In 0.10.0, it is a hard error. This catches ambiguous configuration where uv cannot determine which index should supply default packages:
# pyproject.toml — this now errors in uv 0.10.0
[[tool.uv.index]]
url = "https://pypi.org/simple"
default = true
[[tool.uv.index]]
url = "https://pypi.internal.example.com/simple"
default = true # ← ERROR: only one index can be default
Fix by removing default = true from the secondary index, or switch to the extra-index-url approach:
# Correct: only one default, others as extra
[[tool.uv.index]]
url = "https://pypi.org/simple"
default = true
[[tool.uv.index]]
url = "https://pypi.internal.example.com/simple"
extra = true
3. Python 3.8 Docker Images Dropped
uv 0.10.0 no longer supports Python 3.8 in its managed Python installations. If your project still targets Python 3.8, uv will refuse to install it. Python 3.8 reached end-of-life in October 2024, so this is a natural cutoff — but it is a breaking change for anyone who has not migrated yet. Check your requires-python in pyproject.toml:
# Check what Python your project requires
grep requires-python pyproject.toml
# requires-python = ">=3.8" ← change this to ">=3.9" or higher
New Features in uv 0.10.0
1. uv python upgrade — Now Stable
The uv python upgrade command graduates from preview to stable in 0.10.0. It upgrades the Python patch version in a lockfile without changing minor versions — useful for security patching. Combined with uv python install --upgrade, you can now manage Python upgrades entirely through uv:
# Upgrade Python patch version in lockfile (e.g., 3.12.1 → 3.12.3)
uv python upgrade
# Install a specific Python version and set it as default
uv python install 3.12 --upgrade
# List installed Python versions managed by uv
uv python list
For teams that previously used Dependabot or Renovate to patch Python versions, uv python upgrade is a faster, lighter-weight alternative that does not require a full CI trigger.
2. uv workspace list and uv workspace dir
uv workspaces — analogous to Cargo workspaces in Rust — let you manage a monorepo of multiple Python packages from a single pyproject.toml. The two new subcommands make workspace navigation explicit:
# List all workspace members and their paths
uv workspace list
# Show the root directory of the workspace
uv workspace dir
These are especially useful in CI, where you may need to run tests per-package or discover the workspace structure without parsing pyproject.toml manually:
# Example CI script: run tests for each workspace member
for pkg in $(uv workspace list --format toml | grep path | cut -d'"' -f2); do
uv run --directory "$pkg" pytest
done
3. uv add --bounds — Stabilized
The uv add --bounds flag graduates from preview to fully supported. When adding a dependency, it pins upper bounds in the lockfile — useful for CI safety in a team setting where you want to review major version bumps before they enter the lockfile:
# Add a dependency with upper bounds (e.g., requests >=2.32,<3.0)
uv add --bounds requests
# Add without bounds (default, always picks latest compatible)
uv add requests
For teams transitioning from pip-tools with pip-compile --generate-hashes, this is a direct replacement that gives you explicit control over version range strictness without writing a requirements file.
4. uv format Now Uses Ruff 0.15.0 with the 2026 Style Guide
All formatting in uv is handled by Ruff — the fast Python linter and formatter from Astral. With uv 0.10.0, uv format ships Ruff 0.15.0 and adopts the 2026 style guide. Key changes in this release:
- Lambda parameters stay on one line — Ruff no longer breaks long lambdas across multiple lines, which was a long-standing ergonomic frustration with Black
- Improved spacing around magic literals —
type[None]now formats with consistent spacing - Respect for existing line lengths in multi-line constructs — reduces diff churn in large codebases
# Format your entire project
uv format
# Check without modifying (CI use)
uv format --check
# Format specific files
uv format src/**/*.py
Why it matters: Ruff 0.15.0 and the 2026 style guide make
uv formata credible replacement for Black, isort, and parts of Flake8 in a single tool. The formatter is 10–100x faster than Black and ships in the same binary you already use for package management.
Migrating from pip + venv to uv
If your team is still running python -m venv and pip install, here is the migration path. The total time is under ten minutes for a small project.
Step 1: Install uv
# macOS/Linux — single command installer
curl -LsSf https://astral.sh/uv/install.sh | sh
# Or via pip (if you must)
pip install uv
# Verify
uv --version
Step 2: Create a Project and Initialize
If you have an existing project with a requirements.txt, uv can import it directly:
# Import an existing requirements.txt into a uv project
uv init --from requirements.txt myproject
cd myproject
# Or initialize manually
uv init myproject
cd myproject
If you are starting fresh:
uv init myproject --python 3.12
cd myproject
uv add requests fastapi # add packages
uv sync # install all packages into .venv
Step 3: Sync and Replace pip Commands
| Old pip / venv command | uv equivalent |
|---|---|
python -m venv .venv | uv venv |
source .venv/bin/activate | Not needed — use uv run instead |
pip install -r requirements.txt | uv sync or uv pip install -r requirements.txt |
pip install package | uv add package |
pip freeze | uv pip freeze |
pip-compile requirements.in | uv lock |
pip-sync requirements.txt | uv sync |
pip install package --upgrade | uv add package --upgrade |
Step 4: Update CI/CD Pipelines
Most CI pipelines can drop install time significantly by replacing pip with uv:
# Example GitHub Actions — before (pip)
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install -r requirements.txt
# After (uv) — cache the uv cache directory
- uses: astral-sh/setup-uv@v5
with:
python-version: '3.12'
- run: uv sync --frozen
env:
UV_CACHE_DIR: .uv-cache
The --frozen flag refuses to update the lockfile during CI — this ensures reproducible installs and prevents unexpected changes to uv.lock. Require the lockfile in your PR review process.
Common Mistakes / Gotchas
- Running
uv venvin CI without--clear: If your CI creates a venv on every run, it will now fail. Add--clearto the command or setUV_VENV_CREATE_MODE=clear. - Two
default = trueindexes: This was a warning before — now it is an error. Audit yourpyproject.tomlindexes and remove duplicates. - Still targeting Python 3.8: Change
requires-python = ">=3.8"to">=3.9"or higher before upgrading uv. - Using
pip freezefor reproducible environments: Useuv lockinstead — it produces a cross-platform lockfile with hashes, whichpip freezecannot.
Summary & Next Steps
uv 0.10.0 consolidates its position as the definitive replacement for Python’s fragmented packaging toolchain. Python upgrades are now stable, workspaces are more navigable, --bounds makes dependency management safer, and uv format ships a Ruff formatter upgrade that finally fixes the lambda formatting wars. If your team is still on pip, the upgrade cost is under ten minutes — and the CI time savings alone justify the migration. To go further:
- uv Documentation — official docs from Astral
- Migrating from pip to uv — official migration guide
- Ruff 0.15.0 Release Notes — 2026 style guide details
- uv Changelog on GitHub — full release notes for 0.10.0
- 5 Python Libraries That Actually Changed How I Code — related modern Python tooling
- Python Functions: The Complete Guide — core Python concepts that pair well with uv workflows

