Create Python CLI Tools with uv
With uv, a Python package and project manager, you can easily create, install, and run command-line interface (CLI) tools.
Even when you're just prototyping, letting uv manage the environment means you don’t need to worry about virtual environments or dependencies.
For instructions on installing uv, see the official documentation. Package managers like Homebrew or WinGet are also supported:
This article uses the following version of uv:
$ uv --version
uv 0.7.7 (Homebrew 2025-05-22)
You can find the sample repository for this article here:
Create a Project with uv init --package
To create a new project, use uv init --package
:
$ uv init --package my-uv-tool
Initialized project `my-uv-tool` at `/Users/xxxxx/Documents/my-uv-tool`
The --package
flag creates a packaged application, which allows the tool to be installed using uv tool
.
This command generates the following structure:
$ tree my-uv-tool
my-uv-tool
├── pyproject.toml
├── README.md
└── src
└── my_uv_tool
└── __init__.py
Change into the directory and run the tool by its project name (my-uv-tool
):
$ cd my-uv-tool
$ uv run my-uv-tool
Hello from my-uv-tool!
In the examples that follow, assume the current working directory is the project root—the one containing pyproject.toml
and README.md
.
Add Dependencies with uv add
If your tool needs third-party libraries, add them with uv add
:
$ uv add numpy
You can also add CLI frameworks like click or fire this way.
To remove dependencies, use uv remove
.
Edit Your Code
By default, main()
is defined in __init__.py
:
def main() -> None:
print("Hello from my-uv-tool!")
You can remove this main()
function if it's not needed, but keep the __init__.py
file itself, even if empty.
For example, let’s add cli.py
and utils.py
to src/my_uv_tool
.
cli.py
:
from my_uv_tool import utils
def main():
print('Hello from cli.py!')
print(f'NumPy version: {utils.numpy_version()}')
utils.py
:
import numpy as np
def numpy_version():
return np.__version__
Define Entry Points in pyproject.toml
To use functions from these new files as commands, set up entry points under [project.scripts]
in pyproject.toml
.
By default, the project name (my-uv-tool
) is mapped to "my_uv_tool:main"
, which refers to the main()
function defined in my_uv_tool/__init__.py
:
[project.scripts]
my-uv-tool = "my_uv_tool:main"
For example, modify the default entry point and add a new one like this:
[project.scripts]
my-uv-tool = "my_uv_tool.cli:main"
my-np-version = "my_uv_tool.utils:numpy_version"
The left side defines the command name, and the right side specifies the function to execute.
For example, "my_uv_tool.cli:main"
refers to the main()
function in my_uv_tool/cli.py
, and "my_uv_tool.utils:numpy_version"
points to the numpy_version()
function in my_uv_tool/utils.py
.
You can now run them with uv run
:
$ uv run my-uv-tool
Hello from cli.py!
NumPy version: 2.2.6
$ uv run my-np-version
2.2.6
Install the Tool with uv tool install
To install your tool, run uv tool install
with the path to the project.
In this example, we’re already in the project root, so you can simply use .
as the path:
$ uv tool install -e .
Installed 2 executables: my-np-version, my-uv-tool
Use the -e
(--editable
) flag for editable installs—any code changes are reflected immediately, which is especially useful during development.
Note: changes to pyproject.toml
(such as adding new entry points) won’t take effect until you uninstall and reinstall the tool.
If the bin
directory used by uv tool
isn’t in your PATH
, you’ll see a warning during installation. See the next section for how to set it up.
Once your PATH
is set correctly, you can run the installed commands from anywhere, with no need to activate a virtual environment.
$ my-uv-tool
Hello from cli.py!
NumPy version: 2.2.6
$ my-np-version
2.2.6
To list installed tools, use uv tool list
:
$ uv tool list
my-uv-tool v0.1.0
- my-np-version
- my-uv-tool
To uninstall the tool, use uv tool uninstall
:
$ uv tool uninstall my-uv-tool
Uninstalled 2 executables: my-np-version, my-uv-tool
You can check where tools are installed using uv tool dir
, but this directory is managed by uv and should not be modified manually.
$ uv tool dir
/Users/xxxxx/.local/share/uv/tools
Add the bin
Directory Used by uv tool
to Your PATH
To run tools installed with uv tool
from anywhere, the bin
directory must be included in your environment’s PATH
.
If it’s not, a warning will be shown when you run uv tool install
.
Here’s an example warning on Windows:
warning: `C:\Users\xxxxx\.local\bin` is not on your PATH. To use installed tools,
run `$env:PATH = "C:\Users\xxxxx\.local\bin;$env:PATH"` or `uv tool update-shell`.
As the message suggests, you can automatically configure your PATH
using uv tool update-shell
:
$ uv tool update-shell
Afterward, restart your terminal for the changes to take effect. On Windows, you may need to sign out and sign back in.
For more information on the location of the bin
directory, see the official documentation:
Publish Your Tool
To publish your tool on PyPI, follow the steps in the official guide:
If you don’t plan to release it on PyPI, you can still make it installable via a public Git repository:
$ uv tool install git+https://github.com/nkmk/my-uv-tool
For details on specifying tags, branches, and other options, see: