This is a template for a command-line interface (CLI) application written in Python. This will mostly be used as a starting point for creating new CLI applications.
The key aspect of this template is that there is no external dependencies.
It is designed to be simple and easy to understand.
I also tend to use this template to create CLI for other on-going projects as a replacement of bash scripts and Makefile (or any alternatives).
For example, I have used this template to create a CLI for my Django application to interact with the other tools like docker, python manage.py, etc.
The cli folder contains the following files:
__main__.py: This is the entry point for the CLI application.commands: This folder contains all the command packages.commands/cmd1: A command package to give a glimpse of how you can use folder structure to create a command with subcommands and arguments.commands/cmd2: Another example package to explain how to create a dynamic subcommands.commands/cmd3: Bare minimum package. The main purpose is to demonstrate how to create a command for this documentation.
-
You can download the
clifolder and put it in your project directory (I suggest you put it in the root of your project). Since it contains some examples, you can use it as a starting point for your own CLI application. -
You also need to add the following to your
pyproject.tomlfile:
# if the build system is not set, you need to add the following lines:
[build-system]
requires = ["setuptools>=80.9.0", "wheel"]
build-backend = "setuptools.build_meta"
# Add the following lines to be able to run the CLI application in this format: `cli cmd1 subcmd2 --arg1 value1` without using python executable.
[project.scripts]
cli = "cli.__main__:main"- After adding the previous lines, you can run
uv synccommand install the cli in your virtual environment in editable mode. - If you completed the previous steps, you can run
cli --helpcommand to see the help message.
usage: cli [-h] {cmd1,cmd2} ...
positional arguments:
{cmd1,cmd2}
cmd1 cmd1 related commands
cmd2 cmd2 related commands. Example of dynamic command generation
options:
-h, --help show this help message and exitTo be able to add a new command follow these steps;
- Create a package folder1 in the
commandsfolder. (e.g.cmd3) - Add a doc string for the
__init__file. This doc string will be used in help message. - Create
init_commandfunction inside the__init__file. With this function you can define arguments, subcommands, etc. The signature for the init_command function:
def init_command(parser: argparse.ArgumentParser) -> None:- Create "handle" function inside the
__init__file. In this function you need to handle the logic for the command. The signature for thehandlefunction:
def handle(parser: argparse.ArgumentParser) -> None:- Import the new package into the
cli/__main__.pyfile. The import statement needs to follow the following format:
from .commands import <newpackage> # e.g. from .commands import cmd3Please change the
<newpackage>to the name of the package folder that you created in the step #1.
- Add
<newpackage>to theCOMMAND_PACKAGESlist.
from .commands import cmd3 # ----> new line
# ...
COMMAND_PACKAGES = [
# ...,
cmd3, # ----> new line
]- After adding the new package to the
COMMAND_PACKAGESlist, you can now use the new command. Here is the expected output for thecli --helpcommand:
$ cli --help
usage: cli [-h] {cmd1,cmd2,cmd3} ...
positional arguments:
{cmd1,cmd2,cmd3}
cmd1 cmd1 related commands
cmd2 cmd2 related commands. Example of dynamic command generation
cmd3 Command 3 docs
options:
-h, --help show this help message and exitTo add a subcommand, please check the
__init__file of the example implementations.
Footnotes
-
package folder means a folder that contains
__init__.pyfile. ↩