
Uv
- 17 installs
- 25 repo stars
- Updated July 31, 2026
- hyperb1iss/hyperskills
Manages Python projects, packages, scripts, environments, and dependencies with uv, a Rust tool replacing pip, pipx, pyenv, virtualenv, and poetry.
About
Covers Python package and project management with uv via a workflow decision tree. A developer uses it for uv add/sync/run/lock/init, standalone scripts, workspaces, or managing Python versions.
- Decision tree: scripts vs projects vs pip-compatible workflows
- Replaces pip, pip-tools, pipx, pyenv, virtualenv, poetry
Uv by the numbers
- 17 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #190 of 290 Python skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hyperb1iss/hyperskills --skill uvAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 17 |
|---|---|
| repo stars | ★ 25 |
| Last updated | July 31, 2026 |
| Repository | hyperb1iss/hyperskills ↗ |
What it does
Manages Python projects, packages, scripts, environments, and dependencies with uv, a Rust tool replacing pip, pipx, pyenv, virtualenv, and poetry.
Files
uv: Python Package & Project Manager
uv (v0.11.11, May 2026) replaces pip, pip-tools, pipx, pyenv, virtualenv, and poetry. Written in Rust, 10-100x faster than alternatives. It is stable production software; minor versions can contain breaking changes, while patch releases are intended to be non-breaking.
Workflow Decision Tree
What are you doing?
├─ Running a standalone script? ──────────────────── Scripts workflow
│ (single .py file, no project context needed)
├─ Working in a project with pyproject.toml? ─────── Projects workflow
│ (adding deps, running commands, building)
├─ Running a CLI tool (ruff, ty, pytest)? ────────── Tools workflow
│ (one-off execution, not project-scoped)
├─ Managing Python versions? ─────────────────────── Python workflow
│ (installing, pinning, upgrading interpreters)
├─ Legacy requirements.txt workflow? ─────────────── Pip interface
│ (no pyproject.toml, existing req files)
└─ Building/publishing a package? ────────────────── Build/Publish workflow
(sdist, wheel, PyPI upload)Critical rule: If pyproject.toml exists, use project commands (uv add, uv sync, uv run). Never uv pip install in a project, it bypasses the lockfile.
Projects
Initialization
uv init # App (main.py, no build system)
uv init --lib # Library (src/ layout, uv_build backend, py.typed)
uv init --package # Packaged app (src/ layout, entry points)
uv init --build-backend uv_build # Explicit backend choice
uv init --build-backend maturin # Rust extension module
uv init --python 3.13 # Specific Python version
uv init --bare # pyproject.toml onlyDependency Management
uv add httpx # Add to project.dependencies
uv add httpx --dev # Add to dependency-groups.dev
uv add httpx --group lint # Add to dependency-groups.lint
uv add httpx --optional network # Add to project.optional-dependencies.network
uv add -r requirements.txt # Import from requirements file
uv remove httpx # Remove dependency
# Version bounds (configurable default via add-bounds setting)
uv add 'httpx>=0.27' # Lower bound (default behavior)
uv add 'httpx~=0.27.0' # Compatible releaseDependency Groups (PEP 735)
[dependency-groups]
dev = ["pytest>=8", "ruff"]
lint = ["ruff"]
test = ["pytest", {include-group = "lint"}] # Nest groups
[tool.uv]
default-groups = ["dev", "lint"] # Synced by defaultSync & Run
uv sync # Install from lockfile
uv sync --locked # Error if lockfile stale (use in CI)
uv sync --frozen # Use lockfile as-is, no update
uv sync --no-dev # Skip dev dependencies
uv sync --all-extras # All optional dependencies
uv sync --all-groups # All dependency groups
uv sync --group lint # Include specific group
uv sync --no-install-project # Deps only (Docker layer caching)
uv sync --inexact # Don't remove extraneous packages
uv run pytest # Run in project environment
uv run --with hypothesis pytest # Ad-hoc extra dependency
uv run -p 3.12 pytest # Specific Python versionLocking
uv lock # Resolve and lock dependencies
uv lock --upgrade # Upgrade all to latest compatible
uv lock --upgrade-package httpx # Upgrade specific package
uv lock --check # Verify lockfile current (CI)
uv lock --resolution lowest # Minimum compatible versionsExport
uv export --format requirements-txt # requirements.txt
uv export --format pylock-toml # PEP 751 (preview)Scripts (PEP 723)
Single-file scripts with inline dependency metadata. Scripts with metadata run in complete isolation, project dependencies are ignored even inside a project directory.
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx", "rich>=13"]
# [tool.uv]
# exclude-newer = "2026-03-01T00:00:00Z"
# ///
import httpxuv run script.py # Run with inline deps
uv add --script script.py 'click' # Add dep to script metadata
uv lock --script script.py # Create script.py.lock
uv init --script example.py # Create script with metadata template
echo 'print("hi")' | uv run - # Read from stdinTools
uvx ruff check . # Run tool in isolated env
uvx ruff@0.15.12 check . # Specific version
uvx --from 'httpie' http # Package name differs from command
uvx --python 3.12 ruff # With specific Python
uv tool install ruff # Persistent install to PATH
uv tool upgrade --all # Upgrade all installed tools
uv tool list --outdated # Show available updates (0.10.10+)Key distinction: uvx creates isolated environments, tools are CLI-only, not importable. For tools needing project context (pytest, mypy), use uv run inside a project.
Python Management
uv python install 3.13 # Install latest patch
uv python install 3.13t # Free-threaded (no GIL)
uv python install pypy # PyPy implementation
uv python upgrade 3.13 # Upgrade to latest patch (0.10.0+)
uv python pin 3.13 # Create .python-version
uv python list --only-installed # Show installed versions| Preference Setting | Behavior |
|---|---|
managed (default) | Prefer uv-installed Python |
only-managed | Never use system Python |
system | Prefer system Python |
only-system | Never use managed Python |
Workspaces
# Root pyproject.toml
[tool.uv.workspace]
members = ["packages/*"]
exclude = ["packages/experimental"]
[tool.uv.sources]
my-lib = { workspace = true }Key behaviors:
- Single lockfile across all members
- Single `requires-python`: intersection of all members
- Workspace members are always editable
- Root
tool.uv.sourcesapply to all members unless overridden - Config in
uv.tomlis read only from workspace root, member-level config is ignored
uv workspace dir # Print workspace root
uv workspace list # List members
uv run --package my-lib pytest # Run in specific member context
uv build --package my-lib # Build specific memberVirtual workspaces (no root package):
[tool.uv]
package = false
[tool.uv.workspace]
members = ["packages/*"]Publishing
uv version # Read current version
uv version --bump minor # 1.0.0 -> 1.1.0
uv version --bump patch --dry-run # Preview change
uv build # Build sdist + wheel
uv build --list # Preview included files
uv publish # Publish to PyPI
uv publish --token pypi-xxx # With API token
uv publish --index testpypi # Custom registry
uv publish --check-url https://pypi.org/simple/ # Skip if existsTrusted publishing (GitHub Actions, no credentials):
permissions:
id-token: write
steps:
- run: uv build && uv publishPreview Features (0.10+)
Enable with --preview or UV_PREVIEW=1, or selectively with --preview-features:
| Feature | Flag | Description |
|---|---|---|
uv audit | --preview | Security vulnerability scanning (OSV database) |
uv format | format | Code formatting via Ruff |
pylock | pylock | Install from pylock.toml (PEP 751) |
native-auth | native-auth | System keychain credentials |
uv audit --preview # Scan for vulnerabilitiesConfiguration Quick Reference
Precedence: CLI flags > env vars > project uv.toml > project pyproject.toml [tool.uv] > user ~/.config/uv/uv.toml > system /etc/uv/uv.toml
In a workspace, config search starts at workspace root. uv.toml takes precedence over pyproject.toml in the same directory.
| Setting | Default | Purpose |
|---|---|---|
required-version | — | Enforce uv version (PEP 440) |
add-bounds | "lower" | Default bounds for uv add |
compile-bytecode | false | Compile .pyc on install |
fork-strategy | "requires-python" | Resolution fork behavior |
exclude-newer | — | Date/duration cutoff for reproducibility |
environments | [] | Limit lockfile platforms |
torch-backend | — | PyTorch backend (cpu/cu126/auto) |
default-groups | ["dev"] | Groups installed by default |
.env file support: uv run automatically loads .env files. Control with --env-file or UV_NO_ENV_FILE=1.
For full configuration reference, see references/configuration.md. For Docker and CI/CD patterns, see references/docker-ci.md. For dependency resolution deep dive, see references/resolution.md.
Non-Obvious Gotchas
| Gotcha | Explanation |
|---|---|
uv pip install in a project | Bypasses lockfile and pyproject.toml. Use uv add instead |
| Scripts with metadata ignore project | Even inside a project dir, PEP 723 scripts run in isolation |
--locked vs --frozen | --locked errors on stale lockfile; --frozen silently uses whatever's there |
uv venv needs --clear (0.10+) | No longer auto-removes existing venvs |
tool.uv.sources stripped on publish | Sources are development-only; published packages use project.dependencies |
| Workspace config inheritance | Member-level uv.toml is ignored; only workspace root config applies |
link-mode in Docker | Must use copy with cache mounts (hardlinks fail across filesystem boundaries) |
exclude-newer accepts durations | "30 days", "1 week", "PT24H", not just RFC 3339 timestamps |
uv run uses inexact sync | Won't remove extraneous packages by default; use --exact to enforce |
Anti-Patterns
| Anti-Pattern | Fix |
|---|---|
pip install / python -m pip in uv project | uv add <package> for deps, uv run for commands |
python script.py | uv run script.py (ensures correct environment) |
python -m venv .venv && source .venv/bin/activate | uv run <command> (auto-manages venv) |
Manual requirements.txt for new projects | uv init + uv add + uv.lock |
uv pip compile for project deps | uv lock (universal resolution) |
uv tool install pytest | uv add --dev pytest + uv run pytest (project-scoped) |
uvx for project-scoped tools | uv run <tool> (picks up project context) |
What This Skill is NOT
- Not a replacement for reading
uv --helpfor flag discovery - Not for Poetry/PDM projects (those have their own lock formats)
- Not for building C/Rust extensions (see uv-build skill for backend limitations)
- Not for ruff/ty configuration (see dedicated ruff and ty skills)
uv Configuration Reference
File Locations
| Location | Format | Scope |
|---|---|---|
pyproject.toml [tool.uv] | Nested under [tool.uv] | Project |
uv.toml | Top-level (no [tool.uv] prefix) | Project |
~/.config/uv/uv.toml | Top-level | User |
/etc/uv/uv.toml | Top-level | System |
uv.toml takes precedence over pyproject.toml in the same directory. In workspaces, only workspace root config is read.
All Settings
Project Settings
| Setting | Type | Default | Description |
|---|---|---|---|
required-version | str | — | Enforce uv version (PEP 440 specifier) |
package | bool | true | Treat as Python package vs virtual project |
managed | bool | true | Whether uv manages this project |
default-groups | list | ["dev"] | Groups installed by default |
add-bounds | str | "lower" | Default bounds for uv add (lower/major/minor/exact) |
Resolution Settings
| Setting | Type | Default | Description |
|---|---|---|---|
resolution | str | "highest" | highest/lowest/lowest-direct |
fork-strategy | str | "requires-python" | requires-python/fewest |
prerelease | str | "if-necessary-or-explicit" | Pre-release strategy |
exclude-newer | str | — | Date, duration, or ISO 8601 cutoff |
environments | list | [] | Limit lockfile to these platforms |
required-environments | list | [] | Require wheels for these platforms |
conflicts | list | [] | Mutually exclusive extras/groups |
override-dependencies | list | [] | Replace declared dependency ranges |
constraint-dependencies | list | [] | Narrow acceptable version ranges |
extra-build-dependencies | map | {} | Additional build deps per package |
Installation Settings
| Setting | Type | Default | Description |
|---|---|---|---|
compile-bytecode | bool | false | Compile .pyc after install |
link-mode | str | platform default | clone/copy/hardlink/symlink |
concurrent-downloads | int | 50 | Max parallel downloads |
concurrent-builds | int | CPU cores | Max parallel builds |
concurrent-installs | int | CPU cores | Max parallel installs |
reinstall | bool | false | Force reinstall all packages |
Python Settings
| Setting | Type | Default | Description |
|---|---|---|---|
python-preference | str | "managed" | managed/only-managed/system/only-system |
python-downloads | str | "automatic" | automatic/manual/never |
torch-backend | str | — | PyTorch backend (cpu/cu126/cu128/auto) |
Index Settings
| Setting | Type | Default | Description |
|---|---|---|---|
index-strategy | str | "first-index" | How to search multiple indexes |
keyring-provider | str | "disabled" | Keyring auth provider |
no-build-isolation-package | list | [] | Skip build isolation for these |
Preview Settings
| Setting | Type | Default | Description |
|---|---|---|---|
preview | bool | false | Enable all preview features |
preview-features | list | [] | Enable specific preview features |
Critical Environment Variables
| Variable | Purpose |
|---|---|
UV_PROJECT_ENVIRONMENT | Override venv location (default .venv) |
UV_PYTHON | Default Python interpreter |
UV_TORCH_BACKEND | PyTorch backend selection |
UV_CACHE_DIR | Cache directory |
UV_LINK_MODE | Installation link mode |
UV_NO_DEV | Exclude dev deps |
UV_FROZEN | Don't update lockfile |
UV_LOCKED | Assert lockfile unchanged |
UV_SYSTEM_PYTHON | Use system Python |
UV_PYTHON_DOWNLOADS | Control Python auto-download |
UV_PYTHON_INSTALL_MIRROR | Custom Python download mirror |
UV_PREVIEW | Enable all preview features |
UV_PREVIEW_FEATURES | Enable specific preview features |
UV_VENV_RELOCATABLE | Make venvs relocatable |
UV_INDEX_{name}_USERNAME | Per-index auth username |
UV_INDEX_{name}_PASSWORD | Per-index auth password |
UV_GIT_LFS | Enable Git LFS fetching |
UV_WORKING_DIR | Override working directory |
UV_ENV_FILE | Dotenv files to load (space-separated) |
UV_NO_ENV_FILE | Disable .env loading |
UV_COMPILE_BYTECODE | Compile .pyc on install |
UV_NO_CACHE | Disable caching entirely |
Example: Complete Project Config
[tool.uv]
required-version = ">=0.11"
python-preference = "managed"
compile-bytecode = true
add-bounds = "lower"
default-groups = ["dev", "lint"]
fork-strategy = "requires-python"
[[tool.uv.index]]
name = "internal"
url = "https://pypi.internal.com/simple/"
default = true
[tool.uv.sources]
my-lib = { workspace = true }
torch = { index = "pytorch-cpu" }Example: uv.toml (Standalone)
# No [tool.uv] prefix — top-level keys
required-version = ">=0.11"
python-preference = "managed"
compile-bytecode = true
[[index]]
name = "internal"
url = "https://pypi.internal.com/simple/"
[pip]
index-url = "https://pypi.org/simple"Docker & CI/CD Patterns for uv
Docker — Optimized Multi-Stage Build
FROM python:3.13-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:0.11.7 /uv /uvx /bin/
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
WORKDIR /app
# Layer 1: Install deps only (cached unless lock changes)
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project --no-editable
# Layer 2: Install project code
COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-editable
# Final stage: just the venv
FROM python:3.13-slim
COPY --from=builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
CMD ["my_app"]Docker Environment Variables
| Variable | Value | Purpose |
|---|---|---|
UV_COMPILE_BYTECODE | 1 | Faster startup in production |
UV_LINK_MODE | copy | Required for cache mounts (hardlinks fail across FS boundaries) |
UV_NO_CACHE | 1 | Reduce image size (if not using cache mounts) |
UV_PYTHON_DOWNLOADS | 0 | Don't download Python in container (use base image's) |
UV_NO_DEV | 1 | Exclude dev dependencies |
UV_FROZEN | 1 | Don't update lockfile during build |
Docker Tips
- Add
.venvto.dockerignore— prevents local environments from being copied - Use
--no-editablein production images — avoids.pthfile overhead - The
--mount=type=bindpattern avoids COPY for lock/pyproject — better cache hits - For workspace builds, bind the entire workspace root
Hardened Images (0.10.8+)
Astral publishes hardened Docker images with SBOM attestations:
FROM ghcr.io/astral-sh/uv:0.11.7 # Full image with uv
FROM ghcr.io/astral-sh/uv:0.11.7-python3.13-bookworm # With PythonGitHub Actions
Basic Test Matrix
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
- run: uv sync --locked --all-extras --all-groups
- run: uv run pytest testsLockfile Verification
- run: uv lock --check # Fails if lockfile is staleTrusted Publishing (No Credentials)
name: Publish
on:
push:
tags: [v*]
jobs:
publish:
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- run: uv python install 3.13
- run: uv build
- run: uv publishPEP 740 attestations are discovered and uploaded automatically. Use --no-attestations if a registry rejects them.
Pre-commit Integration
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.11.7
hooks:
- id: uv-lock # Keep uv.lock in sync
- id: uv-export # Keep requirements.txt in syncPyTorch Configuration
Automatic GPU Detection
uv pip install torch --torch-backend=auto # Detects CUDA/ROCm/CPU
UV_TORCH_BACKEND=cu128 uv sync # Explicit backendProject-Level Per-Platform Config
[tool.uv.sources]
torch = [
{ index = "pytorch-cpu", marker = "sys_platform != 'linux'" },
{ index = "pytorch-cu128", marker = "sys_platform == 'linux'" },
]
[[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
[[tool.uv.index]]
name = "pytorch-cu128"
url = "https://download.pytorch.org/whl/cu128"
explicit = trueConflict-Based Extras (Recommended)
[project.optional-dependencies]
cpu = ["torch>=2.9.1"]
cu128 = ["torch>=2.9.1"]
[tool.uv]
conflicts = [[{extra = "cpu"}, {extra = "cu128"}]]
[tool.uv.sources]
torch = [
{ index = "pytorch-cpu", extra = "cpu" },
{ index = "pytorch-cu128", extra = "cu128" },
]Install with: uv sync --extra cu128
Dependency Resolution Deep Dive
Resolution Strategies
| Strategy | Flag | Behavior |
|---|---|---|
highest (default) | — | Latest compatible versions |
lowest | --resolution lowest | Minimum versions for all deps |
lowest-direct | --resolution lowest-direct | Minimum for direct, highest for transitive |
Universal vs Platform-Specific
Universal (uv.lock, default): Portable across all platforms and Python versions. Lists packages multiple times with different versions per platform via fork markers.
Platform-specific (uv pip compile): Resolves for current platform only. Cross-compile with --python-platform and --python-version.
Fork Strategy
[tool.uv]
fork-strategy = "requires-python" # Default: latest per Python version
# fork-strategy = "fewest" # Minimize version count across platformsEnvironment Constraints
[tool.uv]
# Narrow resolution to these platforms only
environments = ["sys_platform == 'darwin'", "sys_platform == 'linux'"]
# REQUIRE wheels to exist for these (fail if missing)
required-environments = ["sys_platform == 'linux' and platform_machine == 'aarch64'"]Overrides vs Constraints
| Feature | Overrides | Constraints |
|---|---|---|
| Purpose | Replace declared deps | Narrow acceptable versions |
| Adds packages? | No | No |
| Can expand versions? | Yes | No |
| Affects undeclared deps? | No | No |
[tool.uv]
override-dependencies = ["numpy>=1.24,<2"] # Force version range
constraint-dependencies = ["requests>=2.28"] # Floor onlyUse overrides when a transitive dependency declares an incorrect upper bound. Use constraints to enforce minimum versions globally.
Dependency Metadata (Skip Source Builds)
[[tool.uv.dependency-metadata]]
name = "chumpy"
version = "0.70"
requires-dist = ["numpy>=1.8.1", "scipy>=0.13.0"]Provides static metadata without building source distributions — useful for packages with exotic build requirements (CUDA, Fortran, etc.).
Conflict Declaration
[tool.uv]
conflicts = [
[
{ extra = "cpu" },
{ extra = "gpu" },
]
]Tells the resolver these extras are mutually exclusive — prevents impossible resolution.
Reproducibility
[tool.uv]
exclude-newer = "2026-03-01T00:00:00Z" # RFC 3339 timestamp
exclude-newer = "30 days" # Relative duration
exclude-newer = "PT24H" # ISO 8601 durationPer-package: exclude-newer-package setting.
Pre-release Handling
Pre-releases accepted only when:
1. Directly specified with pre-release qualifier (e.g., flask>=2.0.0rc1) 2. All published versions are pre-releases 3. --prerelease allow flag used
Sources
[tool.uv.sources]
# Workspace member
my-lib = { workspace = true }
# Git (tag, branch, or rev)
httpx = { git = "https://github.com/encode/httpx", tag = "0.27.0" }
langchain = { git = "https://github.com/langchain-ai/langchain", subdirectory = "libs/langchain" }
# Local path (editable or not)
my-lib = { path = "../libs/my-lib", editable = true }
# URL
httpx = { url = "https://example.com/httpx-0.27.0.tar.gz" }
# Index (explicit registry)
torch = { index = "pytorch" }
# Platform-specific sources
httpx = [
{ git = "https://github.com/encode/httpx", tag = "0.27.2", marker = "sys_platform == 'darwin'" },
{ git = "https://github.com/encode/httpx", tag = "0.24.1", marker = "sys_platform == 'linux'" },
]`tool.uv.sources` are development-only. They are stripped when building (uv build --no-sources) and publishing. Published packages only see project.dependencies.
Index Configuration
[[tool.uv.index]]
name = "internal"
url = "https://pypi.internal.com/simple/"
default = true # Use as default instead of PyPI
[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true # Only used when explicitly referenced in sources| Setting | Behavior |
|---|---|
default = true | Replaces PyPI as the default index |
explicit = true | Only packages explicitly sourced from this index use it |
| Neither | Searched after default index |
`index-strategy` controls multi-index search:
first-index(default): Use first index that has the packageunsafe-first-match: Search all indexes, use first matchunsafe-best-match: Search all indexes, use best version
Lockfile Schema
- TOML format, schema-versioned by minor uv releases
revisionfield tracks backwards-compatible changes- uv rejects lockfiles with newer schema versions — pin
required-versionto avoid surprises