stdlib's built-in CLI parser. For real projects, also see Typer — the modern, type-hint-driven CLI framework.
// Raw
process.argv // ["node", "script.js", "arg1"]
// Libraries
// Commander.js — full-featured
// yargs — flexible
// minimist — minimal
# Raw
import sys
sys.argv # ["script.py", "arg1", "arg2"]
# stdlib
import argparse # batteries-included, no install
# Third-party — better APIs
# Click — decorator-based, widely used
# Typer — type-hint-driven (Click under the hood)
# rich — beautiful terminal output
# greet.py
import argparse
def main():
parser = argparse.ArgumentParser(
description="A friendly greeting tool"
)
# Positional argument (required)
parser.add_argument("name", help="Name to greet")
# Optional argument with flag
parser.add_argument(
"--count", "-c",
type=int,
default=1,
help="Number of times to greet (default: 1)"
)
# Boolean flag
parser.add_argument(
"--shout",
action="store_true", # True if flag present, False otherwise
help="Output in uppercase"
)
# Choice from a set
parser.add_argument(
"--language",
choices=["en", "es", "fr"],
default="en"
)
args = parser.parse_args()
msg = f"Hello, {args.name}!"
if args.shout:
msg = msg.upper()
for _ in range(args.count):
print(msg)
if __name__ == "__main__":
main()
# Usage:
# python greet.py Alice
# python greet.py Alice --count 3 --shout
# python greet.py --help ← auto-generated help!
# git-clone.py — multi-command CLI
import argparse
def cmd_add(args):
print(f"Adding {args.files}")
def cmd_commit(args):
print(f"Committing: {args.message}")
def main():
parser = argparse.ArgumentParser(description="Mini VCS")
subparsers = parser.add_subparsers(dest="command", required=True)
# 'add' subcommand
add_parser = subparsers.add_parser("add", help="Stage files")
add_parser.add_argument("files", nargs="+") # one or more
# 'commit' subcommand
commit_parser = subparsers.add_parser("commit", help="Commit changes")
commit_parser.add_argument("-m", "--message", required=True)
args = parser.parse_args()
match args.command:
case "add": cmd_add(args)
case "commit": cmd_commit(args)
# python git-clone.py add file1.txt file2.txt
# python git-clone.py commit -m "Initial commit"
Typer generates the entire CLI from your function's type hints. No parser setup — just annotate your function.
# pip install typer[all]
import typer
from typing import Annotated
app = typer.Typer()
@app.command()
def greet(
name: str,
count: Annotated[int, typer.Option(help="Times to greet")] = 1,
shout: bool = False,
):
"""A friendly greeting tool."""
msg = f"Hello, {name}!"
if shout:
msg = msg.upper()
for _ in range(count):
typer.echo(msg)
@app.command()
def goodbye(name: str):
"""Say goodbye."""
typer.echo(f"Goodbye, {name}!")
if __name__ == "__main__":
app()
# python greet.py greet Alice --count 3 --shout
# python greet.py goodbye Bob
# python greet.py --help ← auto-generated, beautiful help
Use argparse when you can't add dependencies. Use Typer for new projects — it's the most ergonomic. Click is the battle-tested foundation that Typer builds on — worth knowing if you read others' code.
rich adds colors, tables, progress bars, and syntax highlighting to your CLI — like chalk + ora + cli-table in JS.
# pip install rich
from rich import print
from rich.console import Console
from rich.table import Table
from rich.progress import track
console = Console()
# Styled print (works with [markup])
print("[bold green]✅ Success![/bold green]")
print("[red]Error:[/red] File not found")
console.log("Debug info", log_locals=True)
# Table
table = Table(title="Users")
table.add_column("Name", style="cyan")
table.add_column("Role", style="magenta")
table.add_row("Alice", "admin")
table.add_row("Bob", "editor")
console.print(table)
# Progress bar
for item in track(large_list, description="Processing..."):
process(item)
# Syntax highlighting
from rich.syntax import Syntax
code = Syntax('print("hello")', "python", theme="monokai")
console.print(code)
# Make directly executable on Unix
#!/usr/bin/env python3
# (add this as the first line of your script)
# In terminal:
chmod +x my_script.py
./my_script.py
# Install as a CLI tool via pyproject.toml
[project.scripts]
my-tool = "mypackage.cli:app" # module:function
# After pip install -e .
my-tool --help # works from anywhere in the terminal
1. In argparse, what does action="store_true" do?
2. What is the main advantage of Typer over argparse?
3. To make a script installable as a CLI command via pip, you define it in:
Questions answered correctly.