Skip to content
vast-cow's blog
Go back

Make a CLI command from your Python package

Edit page

In short: declare a console_scripts entry point in your package metadata, activate the target virtual environment, then run pip install (during development use pip install -e .). That will place an executable wrapper in ./venv/bin (Unix/macOS) or venv\Scripts (Windows). Below are concrete examples and step-by-step instructions.

1) Example project layout

myproject/
├─ pyproject.toml   ← (or setup.cfg / setup.py)
└─ src/
   └─ cli.py

src/cli.py (example):

def main():
    print("Hello from mycmd!")

if __name__ == "__main__":
    main()

The function referenced by the entry point (here mypackage.cli:main) will be called when the installed command runs.

When using setuptools as the build backend, add a pyproject.toml like:

[build-system]
requires = ["setuptools>=61", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "0.0.1"
description = "example package"

[project.scripts]
mycmd = "cli:main"

This makes mycmd an installed command that calls cli:main.

3) Another common way: setup.cfg

If your project uses setup.cfg:

[metadata]
name = mypackage
version = 0.0.1

[options]
packages = find:

[options.entry_points]
console_scripts =
    mycmd = cli:main

(Older projects may still use setup.py with entry_points={...}.)

4) Install into a virtual environment (activate first!)

Always create and activate a venv before installing, so the wrapper lands in the venv and not in system Python.

Unix / macOS:

python -m venv venv
source venv/bin/activate
pip install -e .

Windows (PowerShell):

python -m venv venv
venv\Scripts\Activate.ps1
pip install -e .

-e (editable) is convenient during development because code edits are immediately reflected when you run the command. Using pip install . (non-editable) also creates the script/binary but installs a fixed build.

5) Verify the installed command

Unix/macOS:

which mycmd         # shows venv/bin/mycmd if venv is active
mycmd               # run it and check output

Expected locations:

Run mycmd and you should see Hello from mycmd! (or whatever your main() prints).

6) Notes & best practices


Edit page
Share this post:

Comments


Previous Post
Workaround for using UAS USB3 storage on Linux
Next Post
Create a macOS Installer USB Without a Mac