CLI Basics
10 examples to get you started with CLI Tools - 7 basic and 3 intermediate.
Search across all documentation pages
10 examples to get you started with CLI Tools - 7 basic and 3 intermediate.
uv add click typer rich for intermediate examplesThe simplest CLI reads arguments from sys.argv.
import sys
if len(sys.argv) < 2:
print("Usage: greet.py NAME")
sys.exit(1)
print(f"Hello, {sys.argv[1]}!")sys.argv[0] is the script nameRelated: argparse - proper argument parsing
stdlib argument parsing with auto-generated help.
import argparse
parser = argparse.ArgumentParser(description="Greet users")
parser.add_argument("name", help="Name to greet")
parser.add_argument("--loud", action="store_true", help="Uppercase output")
args = parser.parse_args()
msg = f"Hello, {args.name}!"
print(msg.upper() if args.loud else msg)--help generated automaticallyaction="store_true" for boolean flagsRelated: argparse - full guide
Return meaningful exit codes for shell integration.
import sys
def main() -> int:
try:
run()
return 0
except FileNotFoundError:
print("File not found", file=sys.stderr)
return 2
except PermissionError:
return 13
sys.exit(main())--help$?CLIs read from stdin and write to stdout; errors go to stderr.
import sys
for line in sys.stdin:
print(line.strip().upper())
# Usage: cat file.txt | python upper.py > out.txtcmd1 | cmd2--verbose logs should go to stderrOrganize CLI into verbs: git commit, docker run.
import argparse
parser = argparse.ArgumentParser()
sub = parser.add_subparsers(dest="command", required=True)
add = sub.add_parser("add", help="Add item")
add.add_argument("name")
remove = sub.add_parser("remove", help="Remove item")
remove.add_argument("id", type=int)
args = parser.parse_args()add_subparsers creates command groupsdest="command" identifies which subcommand ranRelated: Click - decorator-based subcommands
argparse converts string args to typed values.
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--ratio", type=float, default=0.5)
parser.add_argument("--tags", nargs="+") # one or more stringstype=int validates and convertsnargs="+" collects multiple valueschoices=[...] restricts valid valuesRead config from env vars as fallback.
import os
api_key = os.environ.get("API_KEY")
if not api_key:
raise SystemExit("Set API_KEY environment variable")--helpRelated: Config & Environment - layering config
Click uses decorators for cleaner CLI code.
import click
@click.command()
@click.option("--count", default=1, help="Number of greetings")
@click.argument("name")
def greet(name, count):
for _ in range(count):
click.echo(f"Hello, {name}!")
if __name__ == "__main__":
greet()click.echo handles encoding correctly@click.group() for subcommandsRelated: Click - full Click guide
Formatted tables, progress bars, and syntax highlighting.
from rich.console import Console
from rich.table import Table
console = Console()
table = Table(title="Users")
table.add_column("ID", style="cyan")
table.add_column("Email")
table.add_row("1", "ada@example.com")
console.print(table)Related: Rich Output - formatting guide
Ship CLI via entry points and pipx.
[project.scripts]
mytool = "mytool.cli:main"pipx install mytool
mytool --help[project.scripts] registers command on installRelated: Packaging & Distributing CLIs
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026