Make a CLI command from your Python package (quick guide)

Published: (January 19, 2026 at 09:16 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

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 .). This places an executable wrapper in ./venv/bin (Unix/macOS) or venv\Scripts (Windows).

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 (e.g., 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!)

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

  • Unix/macOS: ./venv/bin/mycmd (executable wrapper)
  • Windows: venv\Scripts\mycmd.exe (or mycmd-script.py)

Running mycmd should display Hello from mycmd! (or whatever your main() prints).

6) Notes & best practices

  • Always activate the virtual environment before pip install unless you explicitly want a system/global install.
  • console_scripts (entry points) are the recommended approach — they produce OS‑appropriate wrapper scripts and integrate with package metadata.
  • The legacy scripts= option in setup.py copies scripts directly; entry points are generally better for dependency resolution and cross‑platform behavior.
  • Libraries like Click or Typer make building richer CLI apps simple; the entry point syntax remains the same (point to the function that invokes the CLI).
Back to Blog

Related posts

Read more »