Create Python CLI Tools with uv

Posted: | Tags: Python, 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!")
source: __init__.py

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()}')
source: cli.py

utils.py:

import numpy as np


def numpy_version():
    return np.__version__
source: utils.py

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:

Related Categories

Related Articles