Skip to content

How to Create and Distribute a Python CLI Tool

pyproject.toml lets you attach any Python function to an executable command name via [project.scripts]. When someone installs the package, their package manager creates a wrapper script that calls that function. With uvx, users can run the tool without even installing it first.

Tip

New to Python packaging? Start with the Create your first Python project with uv tutorial before following this guide.

Define the entry point

Add a [project.scripts] table to your pyproject.toml. If you don’t have a package project yet, uv init --package my-tool scaffolds one with a build backend pre-configured:

pyproject.toml
[project.scripts]
my-tool = "my_tool:main"

The value my_tool:main means “call the main function from the my_tool package.” The key on the left (my-tool) becomes the executable command name on the user’s PATH. This is the PEP 621 equivalent of the console_scripts entry point in older setuptools-based projects.

The function can use argparse, click, or plain sys.argv. The packaging mechanism is the same regardless of what the function does internally.

Test locally

uv run my-tool --help

uv run installs the project into the local virtual environment and invokes the entry point. No manual pip install -e . step is needed.

Build the package

$ uv build
Successfully built dist/my_tool-0.1.0.tar.gz
Successfully built dist/my_tool-0.1.0-py3-none-any.whl

Both a source distribution and a wheel land in the dist/ directory.

Publish to PyPI

The recommended publishing workflow is trusted publishing from GitHub Actions, which requires no stored secrets. For quick one-off uploads, generate an API token at pypi.org/manage/account/ and pass it with --token.

Before publishing to the live index, verify the package looks correct on TestPyPI:

uv publish --publish-url https://test.pypi.org/legacy/ --token YOUR_TEST_TOKEN

Then publish to PyPI:

uv publish

Run the published tool with uvx

After publishing, anyone with uv installed can run the tool without a prior install step:

$ uvx my-tool Alice
Hello, Alice!

uvx resolves and caches the tool environment on first run and reuses the cache on subsequent calls. The tool never touches the user’s project dependencies.

For a permanent installation that puts the command on PATH:

uv tool install my-tool
my-tool Alice

The executable lands in ~/.local/bin/.

Run uv tool upgrade my-tool to pull a newer version later.

Learn More

Last updated on

Please submit corrections and feedback...