uv Tool Management
Purpose
This skill teaches you how to efficiently manage Python command-line tools using uv, including running tools on-demand without installation, installing persistent tools globally, managing versions, and understanding when to use tools versus project dependencies.
Quick Start
Run any CLI tool without installing it:
# Run ruff (Python linter) once without installation
uvx ruff check .
# Equivalent longer form
uv tool run ruff check .
# Install a tool permanently for repeated use
uv tool install ruff
# Then run the installed tool
ruff check .
Instructions
Step 1: Understand the Tool Management Landscape
uv replaces pipx for tool management. There are three main approaches:
uvx (temporary execution): Run a tool once without installation
- Tool is fetched, cached, and executed in an isolated environment
- No modification to your system
- Ideal for: occasional use, trying tools, CI/CD where tools aren't needed repeatedly
uv tool install (persistent installation): Install a tool for repeated use
- Tool is installed globally in a dedicated environment
- Available in PATH after installation
- Ideal for: tools you use regularly (linters, formatters, test runners)
uv run (project environment): Run tools that need access to your project
- Tools run within your project's virtual environment
- Can access your project's installed packages
- Ideal for: testing, linting, formatting your project code
Step 2: Choose Between uvx and uv tool install
Use uvx (ephemeral) when:
- Running a tool for the first time to test it
- Tool is used rarely or on-demand
- You want no installation footprint
- Running in CI/CD pipelines (cleaner, no persistent state)
- Tool has conflicting dependencies with other tools
# Try a new tool without committing to it
uvx httpie https://api.github.com/users/github
# Run a tool on-demand in CI
uvx mypy src/
# Run tool from different package
uvx --from httpie http https://example.com
Use uv tool install (persistent) when:
- Tool is part of your regular workflow
- Team uses it consistently (document in README)
- Tool provides utility functions beyond single invocation
- You want faster execution (no download overhead each time)
- Tool is referenced in project docs or scripts
# Install tools you use daily
uv tool install ruff
uv tool install black
uv tool install mypy
# Then run directly without prefix
ruff check .
black --check src/
mypy src/
Use uv run (project environment) when:
- Running tests, linters, or formatters on your project
- Tool needs access to project dependencies
- Running from within project directory
- Tool is listed in project's dev dependencies
# Test runner needs access to project (test libraries, modules)
uv run pytest tests/
# Linter running on project code
uv run mypy src/
# Format project code
uv run black src/
Step 3: Run Tools with uvx
Basic execution without arguments:
uvx ruff check .
uvx black --check src/
Specify exact version:
# Run specific version of a tool
uvx ruff@0.3.0 check .
# Use version constraint
uvx --from 'ruff>=0.3.0,<0.4.0' ruff check .
Run tools from different packages:
# httpie is in package 'httpie', command is 'http'
uvx --from httpie http https://api.github.com
# mkdocs is in 'mkdocs', command is 'mkdocs'
uvx mkdocs serve
Include optional dependencies (extras):
# mypy with optional faster caching
uvx --from 'mypy[faster-cache]' mypy src/
# mkdocs with material theme
uvx --with mkdocs-material mkdocs serve
Run with specific Python version:
# Run tool with Python 3.10 (useful for compatibility testing)
uvx --python 3.10 ruff check .
# Ensure tool runs on minimum supported version
uvx --python 3.9 pytest tests/
Run from git repository:
# Install directly from GitHub
uvx --from git+https://github.com/httpie/cli httpie
Step 4: Install and Manage Persistent Tools
Install tools:
# Install latest version
uv tool install ruff
# Install specific version
uv tool install ruff@0.3.0
# Install with extras
uv tool install 'mypy[faster-cache]'
# Install from git
uv tool install git+https://github.com/user/tool
List installed tools:
uv tool list
# Example output:
# black 0.23.11 /Users/user/.local/bin/black
# mypy 1.7.0 /Users/user/.local/bin/mypy
# ruff 0.3.0 /Users/user/.local/bin/ruff
Upgrade tools:
# Upgrade specific tool to latest
uv tool upgrade ruff
# Upgrade all tools
uv tool upgrade --all
# Upgrade to specific version
uv tool upgrade ruff@0.4.0
Uninstall tools:
# Remove installed tool
uv tool uninstall ruff
# Remove multiple tools
uv tool uninstall ruff black mypy
Step 5: Understand Tool vs Project Dependencies
Critical distinction for your workflow:
# pyproject.toml
[project]
# Main project dependencies - needed to run your application
dependencies = [
"fastapi>=0.104.0",
"httpx>=0.27.0",
]
[project.optional-dependencies]
# Optional features for your application (not development tools)
aws = ["boto3>=1.34.0"]
database = ["sqlalchemy>=2.0.0"]
[dependency-groups]
# Development tools - only needed while developing
test = [
"pytest>=8.0.0",
"pytest-cov>=4.1.0",
]
lint = [
"ruff>=0.1.0",
"mypy>=1.7.0",
]
format = [
"black>=23.11.0",
]
Decision matrix:
| Use Case | Tool | Command | Where |
|---|---|---|---|
| Try a new linter | uvx | uvx flake8 . | Any directory |
| Lint project code regularly | uv run | uv run ruff check . | Project directory |
| Lint tool used across projects | uv tool install | ruff check . | Any directory |
| Test code | uv run | uv run pytest | Project directory |
| Build documentation | uv tool install | uv tool install mkdocs | Global install |
| One-time script execution | uvx | uvx httpie | Any directory |
| Format code | uv run | uv run black src/ | Project directory |
Step 6: Manage Tool Versions and Upgrades
Check installed version:
# Show version of installed tool
ruff --version
# Or via uv
uv tool list | grep ruff
Upgrade specific tool:
# Upgrade to latest
uv tool upgrade ruff
# Keep all tools up to date
uv tool upgrade --all
Pin tool version:
# Use specific version (best practice for team consistency)
uv tool install ruff@0.3.0
# Override installed version
uv tool install ruff@0.4.0
Clean up old tools:
# Uninstall unused tools
uv tool uninstall old-tool
# Check what's installed
uv tool list
# Free up disk space
uv cache prune
Step 7: Handle Tool Dependencies and Conflicts
Tools with conflicting dependencies:
# These tools both depend on different versions of a library
# uvx creates isolated environments, avoiding conflicts
uvx tool-a
uvx tool-b
# Both run in separate, isolated environments
# No dependency conflicts
Tools requiring additional packages:
# Add extra packages to tool execution
uvx --with mkdocs-material mkdocs serve
# Tool runs with mkdocs + mkdocs-material installed
Specific Python version for tool:
# Some tools require specific Python versions
# Ensure compatibility
uvx --python 3.9 older-tool
# Run with minimum supported Python
uvx --python 3.10 modern-tool
Examples
Example 1: One-Time Tool Usage (uvx)
You need to check code quality but don't use ruff regularly:
# Run ruff once to check your code
uvx ruff check .
# Output analysis but don't install anything
# After execution, no system changes
# Next time you run it, it's fetched again (but cached locally)
Example 2: Regular Linting in Project (uv run)
Your project uses ruff as a dev dependency:
# In your project directory
cd my-project
# Edit pyproject.toml to add ruff to dev dependencies
# [dependency-groups]
# lint = ["ruff>=0.1.0"]
# Sync environment
uv sync --group lint
# Run linter from project environment
uv run ruff check .
# Everyone on team uses same ruff version (from uv.lock)
Example 3: Global Tool Installation (uv tool install)
You use ruff across multiple projects:
# Install once globally
uv tool install ruff
# Use in any directory
cd project-a && ruff check .
cd ../project-b && ruff check .
# No project setup needed
# Tool always available in PATH
Example 4: Test Different Python Versions
You need to verify code works on Python 3.10 and 3.12:
# Run with Python 3.10
uvx --python 3.10 pytest tests/
# Run with Python 3.12
uvx --python 3.12 pytest tests/
# Each uses different Python version
# No installation overhead
Example 5: Tool with Extras
mypy runs faster with optional faster-cache feature:
# Via uvx (temporary)
uvx --from 'mypy[faster-cache]' mypy src/
# Via uv tool install (persistent)
uv tool install 'mypy[faster-cache]'
mypy src/
Example 6: CI/CD Pipeline
Your CI uses different tools without installation:
# .github/workflows/ci.yml
- name: Lint code
run: uvx ruff check .
- name: Type check
run: uvx mypy src/
- name: Format check
run: uvx black --check .
- name: Test
run: |
uv sync --group test
uv run pytest tests/
Each step is clean, isolated, no tool installation overhead.
Example 7: Cleanup and Maintenance
Remove old tools and free disk space:
# See what's installed
uv tool list
# Remove tool you no longer use
uv tool uninstall old-formatter
# Prune cache of unused packages
uv cache prune
# Check cache location and size
uv cache dir
Requirements
- uv installed (install via:
curl -LsSf https://astral.sh/uv/install.sh | sh) - Python 3.8+ available (for running tools)
- Understanding of your project's dependency structure
See Also
- references/tool-comparison.md - Detailed comparison of uvx vs uv tool vs uv run
- references/common-workflows.md - Copy-paste ready tool usage patterns
- examples/tool-scenarios.md - Real-world tool management examples
- uv Documentation - Official tool management guide