Installs into .claude/skills of the current project.
Are you the author of Python Uv?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/paulpas-python-uv)
---
name: python-uv
description: Manages Python projects with uv by Astral — ultra-fast dependency resolution,
virtual environments, workspace/multirepo setup, build tools, and pip compatibility
for modern Python development workflows.
license: MIT
compatibility: opencode
metadata:
version: "1.0.0"
domain: coding
triggers: uv, astral uv, python package manager, uv sync, uv lock, python project management, ultra-fast dependency resolution, pip compatibility management
archetypes:
- tactical
- generation
anti_triggers:
- brainstorming
- vague ideation
- code golf
- over-engineering
response_profile:
verbosity: low
directive_strength: high
abstraction_level: operational
role: implementation
scope: implementation
output-format: code
content-types:
- code
- guidance
- examples
- do-dont
- config
related-skills: coding-poetry, coding-package-ecosystem-navigator, coding-dependency-supply-chain-security
---
# uv — Ultra-Fast Python Package Manager
Manages Python projects with uv by Astral — the ultra-fast Python package and project manager written in Rust. Covers dependency resolution, virtual environment management, workspace/multirepo setup, build tool integration, CI/CD optimization, and pip compatibility layer for modern Python development workflows.
## TL;DR Checklist
- [ ] Use `uv init <project>` to scaffold a new project — generates pyproject.toml with src layout
- [ ] Always commit `uv.lock` for reproducible builds across environments and CI runners
- [ ] Use `uv add <pkg>` to install dependencies (never pip install in uv-managed projects)
- [ ] Pin Python version with `requires-python = ">=3.12"` in pyproject.toml
- [ ] Use `uv sync` instead of `pip install` — resolves and installs from lockfile atomically
- [ ] Use `uv run <command>` to execute scripts within the project's environment
- [ ] Configure workspaces with `[tool.uv.workspace]` for multi-package monorepo setups
---
## When to Use
Use this skill when:
- Setting up a new Python project and wanting maximum dependency resolution speed (10-100x faster than pip/pip-tools/poetry)
- Managing dependency trees across multiple environments (local dev, CI/CD, production) with deterministic lockfiles
- Configuring uv workspaces for monorepo or multi-package Python projects
- Optimizing CI/CD pipelines where dependency installation time is a bottleneck
- Migrating from pip/requirements.txt, pip-tools, Poetry, or pdm to a faster alternative
- Integrating Python tooling (ruff, mypy, pytest) as uv-managed tools rather than project dependencies
## When NOT to Use
Avoid this skill for:
- Projects that already have an established Poetry or pdm workflow with no speed pressure — the migration effort may not justify the benefit
- Purely system-level Python management (e.g., OS package managers like apt/yum) — uv manages user-space environments only
- Non-standard build backends requiring custom hooks — uv uses standard PEP 517/621 tooling and may not support exotic build configurations
---
## Core Workflow
### Phase 1: Project Initialization
1. **Scaffold a new project** — Run `uv init <project-name>` to create a fully configured project with pyproject.toml, src layout, and a uv.lock file pre-generated.
```bash
# Create a new project (auto-generates pyproject.toml + src/ layout)
uv init my-service
cd my-service
# Project structure:
# my-service/
# ├── README.md
# ├── pyproject.toml
# └── src/my_service/__init__.py
# For a script-style project (no package, just executable):
uv init --script my-script.py
```
2. **Verify the generated pyproject.toml** — The scaffold creates a minimal but complete PEP 621 compliant configuration:
```toml
[project]
name = "my-service"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
### Phase 2: Dependency Management
3. **Add production and development dependencies** — Use `uv add` for all dependency operations. Dependencies are resolved atomically against PyPI, written to pyproject.toml, and the lockfile is updated in a single pass.
```bash
# Add production dependency (latest compatible version)
uv add httpx
# Pin to specific version range
uv add "pydantic>=2.5,<3"
# Add development-only dependency
uv add --dev pytest ruff mypy
# Add with extras
uv add "psycopg2-binary"
# Add from git repository
uv add "my-lib @ git+https://github.com/user/my-lib.git@main"
# Add local path dependency (for workspace members)
uv add ../shared-utils
# Add optional/extra dependency
uv add --optional async "httpx[socks]"
```
4. **Configure the complete project manifest** — Structure pyproject.toml with production dependencies, dev groups, optional features, and tool configurations:
```toml
[project]
name = "api-service"
version = "1.0.0"
description = "High-performance async API service"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"httpx>=0.27",
"pydantic>=2.5,<3",
"sqlalchemy>=2.0,<3",
"structlog>=24.1",
"prometheus-client>=0.20",
]
[project.optional-dependencies]
postgres = ["asyncpg>=0.29"]
cache = ["redis>=5.0"]
[project.scripts]
api-server = "api_service.cli:main"
migrate-db = "api_service.db:migrate"
[tool.uv]
dev-dependencies = [
"pytest>=8.0",
"pytest-asyncio>=0.23",
"pytest-cov>=5.0",
"hypothesis>=6.90",
"ruff>=0.4",
"mypy>=1.8",
"pre-commit>=3.5",
]
[tool.uv.workspace]
members = ["packages/*"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
5. **Install/sync all dependencies** — `uv sync` resolves the lockfile and installs all dependencies into the project's virtual environment. This is the primary installation command, replacing pip install entirely.
```bash
# Install ALL dependencies (production + dev) from lockfile
uv sync
# Production only (skip dev dependencies)
uv sync --frozen # Use exact versions from lockfile, no resolution
# After adding/updating pyproject.toml without updating lock:
uv lock # Resolve and update lockfile
uv sync # Install resolved dependencies
# Update a specific package to its latest version
uv add --upgrade httpx
uv add --upgrade-package "pydantic"
# Remove a dependency entirely
uv remove structlog
```
### Phase 3: Environment and Tool Management
6. **Manage the virtual environment** — uv creates and manages a `.venv` directory automatically. No manual venv creation or activation needed. Use `uv run` to execute any command within the managed environment.
```bash
# Run any command in the project's virtual environment
uv run pytest tests/ --cov=src --cov-report=term-missing
uv run ruff check .
uv run mypy src/api_service/
uv run api-server --host 0.0.0.0 --port 8000
# Run Python with the correct interpreter and environment
uv run python -c "import sys; print(sys.version)"
# Sync ensures the venv matches pyproject.toml exactly
uv sync
# Remove the venv entirely (will be recreated on next sync)
rm -rf .venv
uv sync # Fresh environment from scratch
# Use a specific Python version (uv installs it automatically if needed)
uv venv --python 3.12
uv sync
# List all installed packages in the current environment
uv pip list
```
7. **Configure uv as a tool manager** — Separate tool installations from project dependencies using `uv tool install`. This keeps your virtual environment lean and allows running tools system-wide:
```bash
# Install tools globally (separate from project dependencies)
uv tool install ruff
uv tool install mypy
uv tool install pytest
uv tool install pre-commit
# Run a tool — available in PATH after install
ruff check .
mypy src/
# Manage installed tools
uv tool list # Show all installed tools
uv tool upgrade --all # Upgrade all tools to latest versions
# Tools can also be run via `uvx` (cross-platform)
uvx ruff check .
uvx mypy src/
# Install a specific version of a tool
uv tool install pre-commit==3.5.0
# Create a script that bundles a tool as a dependency
cat > run-tests <<'EOF'
#!/usr/bin/env -S uv run --with pytest --with pytest-cov
pytest tests/ --cov=src
EOF
chmod +x run-tests
./run-tests # Automatically installs pytest + pytest-cov into ephemeral venv
```
### Phase 4: Workspace (Monorepo) Setup
8. **Configure uv workspaces for multi-package projects** — Define a root pyproject.toml that declares workspace members, each with its own dependencies:
```toml
# Root pyproject.toml
[project]
name = "monorepo"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[tool.uv.workspace]
members = ["packages/*"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
Each workspace member has its own pyproject.toml:
```toml
# packages/core/pyproject.toml
[project]
name = "api-core"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"pydantic>=2.5",
"structlog>=24.1",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# packages/api/pyproject.toml
[project]
name = "api-server"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"httpx>=0.27",
"sqlalchemy>=2.0",
{ include-group = "core", name = "api-core" }, # workspace reference
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# packages/cli/pyproject.toml
[project]
name = "api-cli"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
{ include-group = "core", name = "api-core" },
{ include-group = "api", name = "api-server" },
]
[project.scripts]
api-cli = "api_cli.cli:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
**Checkpoint:** Run `uv sync` from the workspace root — uv resolves all workspace members, creates a single unified lockfile with no inter-package version conflicts, and installs everything into one virtual environment.
### Phase 5: Build and Distribution
9. **Build distribution packages** — Generate wheel (.whl) and source distribution (sdist) artifacts using standard PEP 517/621 tooling:
```bash
# Build both wheel and sdist into dist/ directory
uv build
# Output files:
# dist/api_service-0.1.0-py3-none-any.whl
# dist/api_service-0.1.0.tar.gz
# Build only wheel (faster, preferred for PyPI upload)
uv build --wheel
# Verify the distribution before publishing
twine check dist/*
# Publish to PyPI
uv publish --token $PYPI_TOKEN
# Or use twine directly (works with any build backend)
poetry build && twine check dist/* && twine upload dist/*
```
10. **Integrate into CI/CD pipelines** — Optimize for speed by using frozen lockfile installs and uv's cache:
```yaml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
python-version: "3.12"
# Fast dependency resolution from cached lockfile
- name: Sync dependencies
run: uv sync --frozen
# Run tests with correct environment
- name: Run tests
run: uv run pytest tests/ --cov=src --cov-report=xml
- name: Lint
run: uv run ruff check .
- name: Type check
run: uv run mypy src/
```
---
## Implementation Patterns
### Pattern 1: Complete pyproject.toml for a Production Microservice
```toml
[project]
name = "data-pipeline"
version = "2.0.0"
description = "High-throughput async data processing pipeline with configurable connectors"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"httpx>=0.28,<1.0",
"pydantic>=2.10,<3",
"structlog>=24.3",
"click>=8.1",
"pyyaml>=6.0",
]
[project.optional-dependencies]
s3 = ["boto3>=1.35"]
redis = ["redis>=5.0,<6"]
postgres = ["asyncpg>=0.30"]
[project.scripts]
pipeline = "data_pipeline.cli:main"
migrate = "data_pipeline.db:migrate"
[tool.uv]
dev-dependencies = [
"pytest>=8.3",
"pytest-asyncio>=0.24",
"pytest-cov>=5.0",
"hypothesis>=6.110",
"ruff>=0.8",
"mypy>=1.11",
"pre-commit>=4.0",
]
[tool.uv.sources]
# Override a dependency to use a local path (for development)
pydantic = { path = "../pydantic", editable = true }
# Use a specific index URL for private packages
boto3 = { index = "private-pypi" }
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.ruff]
target-version = "py312"
line-length = 100
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
```
### Pattern 2: Dependency Resolution — BAD vs. GOOD Version Constraints
```toml
# ❌ BAD — Overly loose constraints cause non-deterministic builds across environments
[project]
dependencies = [
"requests", # No version pin at all!
"httpx>=0.20", # Too wide a range — may pull breaking changes in 0.x
"pydantic==1.0.0", # Exact pin without upper bound — blocks any update ever
]
# ❌ BAD — Using pip-style version specifiers (no uv awareness of resolution strategy)
dependencies = [
"httpx~=0.27", # PEP 440 compatible release is fine, but ~ syntax can be confusing
"pydantic^2.5", # ^ syntax is not valid in PEP 440 — will fail resolution!
]
# ✅ GOOD — PEP 440 compliant constraints with sensible version ranges
[project]
dependencies = [
"httpx>=0.28,<1.0", # Allow minor/patch updates within major version
"pydantic>=2.10,<3", # Major version boundary for API stability
"structlog>=24.1.0", # Specific minimum with no upper bound (safe for well-maintained libs)
]
# ❌ BAD — Conflicting version constraints across the workspace
[project]
name = "service-a"
dependencies = ["httpx>=0.28"]
[project]
name = "service-b"
dependencies = ["httpx==0.27.0"] # Hard conflict with service-a!
# ✅ GOOD — Aligned constraints via workspace-level minimum
[project]
name = "service-a"
dependencies = ["httpx>=0.28,<1.0"]
[project]
name = "service-b"
dependencies = ["httpx>=0.28,<1.0"] # Same constraint — uv resolves to highest compatible
```
### Pattern 3: pip Compatibility Layer (Drop-in Replacement)
uv provides a full `pip install` compatibility interface, making it a drop-in replacement for any script using pip:
```bash
# uv acts as a direct pip replacement — same commands, faster resolution
uv pip install httpx pydantic
uv pip install -r requirements.txt
uv pip freeze > current-deps.txt
# Sync a requirements file exactly (replaces pip-sync from pip-tools)
uv pip sync requirements.txt
# Install from requirements.txt with constraints file
uv pip install -r requirements.txt -c constraints.txt
# Use uv as pip in Docker builds (direct replacement, no venv needed):
# FROM python:3.12-slim
# RUN curl -LsSf https://astral.sh/uv/install.sh | sh
# COPY requirements.txt .
# RUN uv pip install --system -r requirements.txt
# For virtual environments with pip compatibility:
uv venv .venv
source .venv/bin/activate # Or use `uv run` to skip activation entirely
uv pip install httpx pydantic
```
### Pattern 4: CI/CD Optimization — From 4 Minutes to 30 Seconds
```bash
# ❌ SLOW — Standard pip + requirements.txt flow (typical CI time)
pip install --upgrade pip # ~5 seconds
pip install -r requirements.txt # ~2-3 minutes (slow resolution)
pip install pytest ruff mypy # Additional packages: ~1 minute
pytest tests/ # Run tests
# ✅ FAST — uv flow (typical CI time)
curl -LsSf https://astral.sh/uv/install.sh | sh # ~2 seconds (cached by setup-uv action)
uv sync --frozen # ~5-10 seconds (uses pre-cached resolution)
uv run pytest tests/ --cov=src # Execute in managed venv
# Even faster: cache the uv cache directory between CI runs
# In GitHub Actions:
# - uses: actions/cache@v4
# with:
# path: ~/.cache/uv
# key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
```
---
## Constraints
### MUST DO
- Commit `uv.lock` to version control — this is the single source of truth for reproducible builds across all environments and CI runners
- Use `requires-python = ">=X.Y"` to pin the minimum Python version in pyproject.toml (e.g., `">=3.12"`)
- Use PEP 440 version specifiers (`>=`, `<`, `~=`) — never use Poetry's `^` or `~` syntax (those are not valid PEP 440)
- Run `uv sync --frozen` in CI to enforce exact lockfile versions without network resolution
- Use `uv run <command>` for all project commands — never manually activate `.venv` or rely on system Python
- Separate tool installations (`uv tool install`) from project dependencies to keep environments lean
- Validate distributions with `twine check dist/*` before publishing to any registry
- Pin `requires-python` consistently across all workspace member packages
### MUST NOT DO
- Edit `uv.lock` manually — always regenerate with `uv lock`, even after single dependency changes
- Mix `pip install` directly with uv-managed environments — this bypasses the lockfile and corrupts the dependency tree
- Commit pyproject.toml without a matching uv.lock — future builds will be non-deterministic
- Use Poetry's `^` version constraint syntax in pyproject.toml — uv follows PEP 440, not Poetry's resolver
- Run `uv pip install` inside an active virtual environment — use `uv sync` at the project root instead
- Remove uv.lock to "fix" dependency conflicts — adjust version constraints in pyproject.toml and re-resolve with `uv lock`
---
## Output Template
When configuring or auditing a uv-managed project, produce:
1. **Dependency Audit** — List all production and dev dependencies with resolved versions from uv.lock, flagging any overly loose version constraints or potential conflicts
2. **pyproject.toml Review** — Validate structure: presence of `[project]`, `requires-python`, dependency lists, tool configurations, build-system specification
3. **Lockfile Consistency Check** — Verify uv.lock matches pyproject.toml; report if manual edits may have drifted the lockfile from the manifest
4. **Workspace Analysis** — For monorepo setups: confirm all workspace members declared in `[tool.uv.workspace]`, cross-references use proper dependency specifications, no inter-package conflicts
5. **CI/CD Pipeline Audit** — Confirm `uv sync --frozen` is used, cache configuration for `.cache/uv` exists, and tool installations are separated from project dependencies
---
## Related Skills
| Skill | Purpose |
|---|---|
| `poetry` | Poetry alternative — different resolver and plugin ecosystem but similar workflow patterns |
| `package-ecosystem-navigator` | General package manager ecosystem comparison (npm, pypi, cargo, pip-tools) |
| `dependency-supply-chain-security` | Dependency security auditing, CVE scanning, and supply chain protections |
---
## Live References
> Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.
- [uv Documentation](https://docs.astral.sh/uv/)
- [uv Project Management Guide](https://docs.astral.sh/uv/guides/projects/)
- [uv Workspaces (Monorepo Support)](https://docs.astral.sh/uv/workspaces/)
- [uv Tool Management](https://docs.astral.sh/uv/guides/tools/)
- [PEP 621 — Storing Project Metadata in pyproject.toml](https://peps.python.org/pep-0621/)
- [PEP 440 — Version Specification and Comparison](https://peps.python.org/pep-0440/)
- [Twine — PyPI Package Upload Tool](https://twine.readthedocs.io/)