uvx vs uv: When to Use Each Tool in Python Development
I kept typing uv run ruff check . when I should have used uvx ruff check .. Then I’d wonder why my project’s virtual environment got cluttered with tools I only needed once. The confusion between uv and uvx slowed me down for weeks.
If you’re scratching your head about when to use which command, you’re not alone. Both tools come from the same ecosystem, but they solve different problems. Let me clear this up.
What is uv?
uv is the main package and project manager from Astral. Think of it as pip, poetry, pyenv, and pipx rolled into one fast tool.
When I use uv, I’m working with my project:
- Managing dependencies with
uv addanduv remove - Creating and syncing virtual environments with
uv sync - Running commands that need my project installed with
uv run - Installing Python versions with
uv python install - Creating new projects with
uv init
The key insight: uv operates within your project context. It knows about your pyproject.toml, your virtual environment, and your installed packages.
# Initialize a new projectuv init myproject
# Add a dependencyuv add requests
# Run a script that uses your project's packagesuv run python main.pyWhat is uvx?
uvx is a convenience alias for uv tool run. It runs Python tools in isolated, temporary environments.
When I use uvx, I’m saying: “Run this tool once, don’t mess with my project.”
The tool runs in its own clean environment, does its job, and leaves no trace in my project. This is perfect for:
- Tools I don’t want installed permanently
- Testing different versions of tools
- Quick one-off commands
# Run ruff without installing it anywhereuvx ruff check .
# Try a specific version of black
# Run Python itself in isolationuvx python -c "print('hello')"Key Differences at a Glance
| Aspect | uv | uvx |
|---|---|---|
| Purpose | Project management | One-off tool runs |
| Environment | Uses project venv | Creates temporary venv |
| Persistence | Changes persist | Ephemeral, cleaned up |
| Use case | Dependencies, scripts | Tools you don’t need installed |
| Speed | Fast (uses existing venv) | Fast (creates temp venv on demand) |
Decision Framework
When I reach for a command, I ask myself these questions:
1. Does the tool need access to my project’s installed packages?
If yes, use uv run. For example, pytest needs to import my project’s code. mypy needs to check my project’s types.
# pytest needs your project installeduv run pytest tests/
# mypy needs access to your source code typesuv run mypy src/
# Your project's CLI tooluv run myproject-cli --helpIf no, consider uvx. For example, ruff just needs to read files. It doesn’t need my project’s packages.
# ruff only needs to read filesuvx ruff check .
# black only needs to format filesuvx black .
# Run any tool without project contextuvx cowsay "Hello, isolated world"2. Is this a one-off command I won’t repeat?
If I’m testing a tool or running it once, uvx is the answer. No need to pollute my project or global tools.
# Test a linter I'm consideringuvx ruff check .
# Run a tool for a quick checkuvx mypy --version
# Try a different version3. Will I use this tool frequently across projects?
If yes, install it as a tool with uv tool install. This installs it globally (but in its own environment).
# Install ruff globally for frequent useuv tool install ruff
# Now run it directlyruff check .
# Install specific version4. Am I managing dependencies?
For adding, removing, or syncing packages, use uv commands directly:
# Add a dependencyuv add requests
# Add a dev dependencyuv add --dev pytest
# Remove a dependencyuv remove requests
# Sync environment with lock fileuv syncReal-World Scenarios
Scenario 1: Running Linters
I want to check my code with ruff. Does ruff need my project installed? No. It just reads files and checks them.
# Good: uvx for isolated runuvx ruff check .
# Also fine if I use ruff a lot:uv tool install ruffruff check .
# Overkill: uv run (creates unnecessary project context)uv run ruff check . # Works but unnecessaryScenario 2: Running Tests
I want to run my test suite. Does pytest need my project installed? Yes. It imports my code to test it.
# Correct: uv run for project contextuv run pytest tests/
# Wrong: uvx won't have your project installeduvx pytest tests/ # Fails - can't find your codeScenario 3: Testing a New Tool
I heard about a new formatter and want to try it on my project.
# Perfect: uvx for one-off testinguvx ruff format . # Try it without committing
# If I like it, install for frequent useuv tool install ruffruff format .Scenario 4: CI/CD Pipeline
In CI, I want clean, reproducible runs.
# Use uvx for tools that don't need project contextuvx ruff check .uvx ruff format --check .
# Use uv run for testsuv run pytestuv run mypy src/Common Mistakes
Mistake 1: Using uv run for everything
I used to run uv run ruff check . constantly. This created unnecessary project context. Now I use uvx ruff check . for tools that don’t need my project.
Mistake 2: Installing tools I use once
I installed tools globally with uv tool install just to try them. My global tool list became a mess. Now I use uvx for testing.
Mistake 3: Using uvx for project tools
I tried uvx pytest and wondered why my tests couldn’t import my code. The isolated environment didn’t have my project installed. uv run pytest was the answer.
Quick Reference
# Project managementuv init [name] # Create new projectuv add [package] # Add dependencyuv remove [package] # Remove dependencyuv sync # Sync with lock file
# Running in project contextuv run [command] # Run with project installeduv run pytest # Tests need your code
# Isolated tool runsuvx [tool] # Run once, clean environmentuvx ruff check . # Linter doesn't need projectuvx python -c "..." # Isolated Python
# Frequent tool useuv tool install [tool] # Install globallyruff check . # Then run directlySummary
In this post, I explained when to use uvx versus uv in Python development. The core principle is simple: uvx for isolated tool runs that don’t need your project, uv run for commands that need your project installed. Think of uvx as “run this tool somewhere clean” and uv run as “run this command in my project.”
The decision comes down to one question: does the tool need to import my project’s code? If yes, uv run. If no, uvx. For tools you use daily across projects, install them with uv tool install.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments