uv tool install and pipx install solve the same core problem: they put a Python command-line tool on your PATH without letting its dependencies collide with anything else on your machine. Each tool gets its own isolated virtual environment, and you type its name like any other program. The differences show up in speed, upgrade ergonomics, and how you run something just once. This guide puts the two side by side for the specific job of installing and living with globally available CLIs.
TL;DR
- Both give isolated global installs. Each installed CLI lands in a dedicated virtual environment, so
httpieandawsclinever fight overrequestsversions. uv tool installis faster thanks to uv's Rust resolver and a shared global cache — repeat installs reuse already-downloaded wheels.uvxandpipx runare the one-off runners. Use them to execute a tool once without leaving anything installed.- Upgrades differ:
uv tool upgradere-resolves against your constraints;pipx upgradedoes the same for pipx-managed venvs. Both let you pin. - Pick uv if you already use it for project work (one tool, one cache); pick pipx if you want a small, single-purpose installer that does nothing else.
Both give you isolated global installs
The shared idea is worth stating plainly because it is the whole reason these tools exist. If you pip install httpie into your system Python, its pinned requests and pygments become global, and the next tool that wants a different pygments breaks. Isolated installers avoid this by creating one virtual environment per tool and exposing only that tool's entry-point scripts on your PATH.
# pipx: one venv for black, another for httpie
$ pipx install black
$ pipx install httpie
# uv: same model, different front door
$ uv tool install black
$ uv tool install httpie
After either pair of commands, black and http are on your PATH, backed by separate environments that can hold conflicting dependency trees without noticing each other. This is the same isolation principle covered in managing virtual environments for cross-platform CLIs — an installed tool is just a managed, named venv you never have to activate.
uv tool install / uvx vs pipx install / pipx run
Both tools split the world into two verbs: install and keep versus run once.
# Keep it around (adds a command to your PATH)
$ pipx install cowsay
$ uv tool install cowsay
# Run it once, throw the environment away afterwards
$ pipx run cowsay "hello"
$ uvx cowsay "hello"
uvx is simply an alias for uv tool run. It resolves the requested package, builds (or reuses a cached) ephemeral environment, runs the command, and leaves nothing on your PATH. pipx run behaves the same way and caches the temporary environment for a few days so a second pipx run of the same tool is quick.
The one-off runners are the right call for tools you touch rarely: a project scaffolder, a linter you only run in CI, a cookiecutter template. There is no reason to permanently install something you invoke twice a year — reach for uvx or pipx run and skip the cleanup. The scaffolding workflow in CLI project scaffolding with Cookiecutter is a textbook case: uvx cookiecutter gh:org/template runs the generator without adding a command you will never use again.
Speed and the shared cache
This is where uv pulls ahead. uv keeps a single global cache of downloaded and built wheels and resolves dependencies with a parallel Rust resolver. When you install a second tool that shares a dependency with the first, uv links the already-cached wheel instead of re-downloading it. Cold installs are fast; warm installs are close to instant.
# First install populates the cache
$ uv tool install rich-cli
# A later install that shares 'rich' reuses cached wheels
$ uv tool install textual
pipx is a thin, pure-Python layer over venv and pip. It is perfectly fast enough for interactive use, but it does not share a wheel cache across tool environments the way uv does, so each install does more independent work. If you install and reinstall many tools — for example, rebuilding a toolbox in a fresh container — the difference is noticeable.
Upgrades and pinning
Both tools let you upgrade one CLI, upgrade everything, or pin to an exact version.
# Upgrade a single tool
$ pipx upgrade httpie
$ uv tool upgrade httpie
# Upgrade every installed tool
$ pipx upgrade-all
$ uv tool upgrade --all
# Pin at install time
$ pipx install 'httpie==3.2.2'
$ uv tool install 'httpie==3.2.2'
An upgrade re-resolves the tool's dependencies against its version constraints and rebuilds the environment. Pinning matters for reproducibility: if a CLI is part of your team's workflow, pin the version in your setup docs so everyone runs the same one. You can also inject extra packages into a tool's environment — useful when a CLI needs an optional plugin:
# Add a plugin into an existing tool environment
$ pipx inject mkdocs mkdocs-material
$ uv tool install mkdocs --with mkdocs-material
Note the small ergonomic difference: pipx injects into an already-installed tool as a separate step, while uv declares extras with --with at install time (re-running the install updates the set). Both end with the plugin importable inside the tool's isolated environment.
uv tool list and managing what's installed
Listing and removing work the same way in both, which makes auditing your global toolbox easy.
# What is installed, and which commands does each expose?
$ uv tool list
black v24.10.0
- black
- blackd
httpie v3.2.4
- http
- https
$ pipx list
# Remove a tool and its environment
$ uv tool uninstall black
$ pipx uninstall black
uv tool list shows both the package version and every console script that package puts on your PATH, which is handy when a single distribution installs several commands (like black and blackd). One more uv-specific nicety: uv tool update-shell ensures the tool bin directory is on your PATH, the equivalent of pipx's pipx ensurepath.
Comparison table
| Dimension | uv tool | pipx |
|---|---|---|
| Isolation model | One venv per tool | One venv per tool |
| Install a tool | uv tool install X | pipx install X |
| Run once, no install | uvx X / uv tool run X | pipx run X |
| Upgrade one / all | uv tool upgrade X / --all | pipx upgrade X / upgrade-all |
| Add a plugin | --with pkg at install | pipx inject tool pkg |
| List installed | uv tool list | pipx list |
| Shared wheel cache | Yes (global) | No |
| Resolver | Rust, parallel | pip (pure Python) |
| Scope of the tool | Full project + package manager | Install/run CLIs only |
| Runtime dependency | Single static uv binary | Python + pip |
When each wins
Reach for uv tool when you already use uv for project dependency management. Keeping one binary, one cache, and one mental model for both your projects and your global tools is a real simplification — the same uv you use in uv for Python CLI dependency management also installs finished CLIs. It is also the fastest option for cold environments like CI runners and Docker images.
Reach for pipx when you want a small, focused, well-established tool that does exactly one thing. pipx has been the community standard for global CLI installs for years, it is packaged in most distributions, and it carries no expectation that you adopt a whole project workflow. If uv is not already in your stack, pipx is the lower-commitment choice. The end-to-end distribution story — building the tool and telling users to install it with pipx — lives in installing and distributing CLIs with pipx.
For most teams the honest answer is "whichever you already have." Both deliver the same isolation guarantee; the deciding factor is how much other tooling you want to standardize on.
Production notes
- Publishing advice should name a runnable installer. When you document install steps for your CLI, offer both
pipx install yourclianduv tool install yourcli— users have one or the other, rarely both. - CI: prefer the one-off runner. In CI you usually want
uvx ruff checkorpipx run ruff checkrather than a persistent install; the ephemeral environment is cached and there is no global state to clean up. PATHsetup is a first-run gotcha. Both tools install scripts into a bin directory that may not be on a fresh machine'sPATH. Runuv tool update-shellorpipx ensurepathonce and restart the shell.- Pin tools your team depends on. An unpinned
uv tool install/pipx installfloats to the latest release; pin the version in onboarding docs to avoid "works on my laptop" drift. - Python version.
uv tool install --python 3.12 Xlets uv fetch and use a specific interpreter for the tool's environment; pipx relies on a Python already present on the system.
Related
- uv for Python CLI dependency management — the parent guide covering uv end to end for CLI projects.
- Installing and distributing CLIs with pipx — how to package a CLI so users can install it with pipx or uv.
- Managing virtual environments for cross-platform CLIs — the isolation model that global tool installs are built on.
- uv init vs poetry init for CLI tools — choosing a project bootstrapper before you ship the tool.