On this page
article
Building CLI Applications
Create command-line tools with argparse and Click — arguments, subcommands, options, and packaging CLI apps.
Command-line interfaces (CLIs) are how developers interact with tools daily. Python’s argparse (stdlib) and click (third-party) make building CLIs straightforward.
argparse — Standard Library
# greet.py
import argparse
def main():
parser = argparse.ArgumentParser(
description="Greet people from the command line.",
)
parser.add_argument("name", help="Name to greet")
parser.add_argument(
"--count", "-c", type=int, default=1,
help="Number of times to greet",
)
parser.add_argument(
"--loud", action="store_true",
help="Greet loudly (uppercase)",
)
args = parser.parse_args()
greeting = f"Hello, {args.name}!"
if args.loud:
greeting = greeting.upper()
for _ in range(args.count):
print(greeting)
if __name__ == "__main__":
main()
Usage:
python greet.py Alice
python greet.py Bob --count 3 --loud
python greet.py --help
Subcommands
def main():
parser = argparse.ArgumentParser(prog="tool")
subparsers = parser.add_subparsers(dest="command", required=True)
# create command
create_parser = subparsers.add_parser("create", help="Create a resource")
create_parser.add_argument("name")
# delete command
delete_parser = subparsers.add_parser("delete", help="Delete a resource")
delete_parser.add_argument("id", type=int)
args = parser.parse_args()
if args.command == "create":
print(f"Creating {args.name}")
elif args.command == "delete":
print(f"Deleting ID {args.id}")
python tool.py create myproject
python tool.py delete 42
Click — Elegant CLI Framework
pip install click
import click
@click.group()
def cli():
"""My CLI tool."""
pass
@cli.command()
@click.argument("name")
@click.option("--count", "-c", default=1, help="Number of greetings")
@click.option("--loud", is_flag=True, help="Greet loudly")
def greet(name, count, loud):
"""Greet someone."""
greeting = f"Hello, {name}!"
if loud:
greeting = greeting.upper()
for _ in range(count):
click.echo(greeting)
@cli.command()
@click.argument("filename", type=click.Path(exists=True))
@click.option("--format", type=click.Choice(["json", "csv"]), default="json")
def convert(filename, format):
"""Convert a file to another format."""
click.echo(f"Converting {filename} to {format}")
if __name__ == "__main__":
cli()
python cli.py greet Alice --count 3 --loud
python cli.py convert data.csv --format json
python cli.py --help
Interactive Prompts
import click
@click.command()
def setup():
name = click.prompt("Project name")
use_docker = click.confirm("Use Docker?")
env = click.prompt(
"Environment",
type=click.Choice(["dev", "staging", "prod"]),
default="dev",
)
click.echo(f"Setting up {name} ({env}), Docker: {use_docker}")
Progress Bars
import click
import time
@click.command()
def process():
items = range(100)
with click.progressbar(items, label="Processing") as bar:
for item in bar:
time.sleep(0.01)
Packaging as an Installable CLI
In pyproject.toml:
[project.scripts]
mytool = "myapp.cli:main"
After pip install -e ., run from anywhere:
mytool greet Alice
argparse vs Click
| Feature | argparse | Click |
|---|---|---|
| Dependency | stdlib | third-party |
| Syntax | verbose | decorator-based |
| Subcommands | manual setup | built-in groups |
| Colors/prompts | manual | built-in |
| Testing | parse_args() |
CliRunner |
# Testing Click apps
from click.testing import CliRunner
def test_greet():
runner = CliRunner()
result = runner.invoke(greet, ["Alice", "--loud"])
assert result.exit_code == 0
assert "HELLO, ALICE!" in result.output
CLIs are the fastest way to automate workflows and share tools with your team.