Cli Tools
Build real command-line tools the same way professionals build developer utilities, automated scripts, data pipelines, AI model runners, and deployment tools. Master both argparse (standard, built-in) and Typer (modern, FastAPI-style) for creating production-grade CLI applications.
Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
This lesson teaches how to build real command-line tools, the same way professionals build:
1. argparse (standard, low-level, built into Python) — Perfect for: small scripts, simple tools, full control.
2. Typer (modern, high-level, super-fast development) — Perfect for: professional apps, developer tools, banners, sub-commands, autocomplete.
🔥 1. Why Command-Line Tools Matter
Before GUIs, everything ran in the terminal. But even today:
Having CLI-building skills makes you 10× more valuable as a developer.
⚙️ 2. argparse Basics — The Standard Python CLI Option
argparse ships with Python. No installation needed.
🧠 3. Positional vs Optional Arguments
Optional flags improve usability and mirror real CLI tools like pip, git, and docker.
📝 4. Typed Arguments: int, float, file paths
🧩 5. Sub-Commands (Like Git)
Many tools behave like: git add, git push, git commit. You can create the same pattern:
This transforms your script into a multi-command CLI application.
⚡ 6. Real Project Example — File Organizer
🚀 7. Introduction to Typer (The Modern CLI Framework)
Typer is built by the creator of FastAPI. It offers:
🧠 8. Basic Typer Example
🎛 9. Optional Arguments in Typer
Usage: python tool.py download https://example.com --retries 5 --verbose
🧩 10. Typed Options & Defaults
This makes code cleaner and more maintainable.
🏗 11. Subcommands (Typer's strongest feature)
You now have a full CLI program with modules.
🧠 12. Real Project Example — AI Assistant CLI
In this part, we go deeper into real engineering patterns, advanced argument features, error handling, output design, color/UI improvements, and structuring multi-file CLI apps the same way professionals build tools like pip, docker, aws-cli, git, uv, and fastapi-cli.
⚡ 1. Advanced argparse Features You MUST Know
Sometimes a user should only choose one option:
Now the user cannot do: python tool.py --verbose --quiet
This is used for logging mode, compression types, environment switches, etc.
Stops invalid inputs before they crash your program.
🧠 2. Using Config Files + CLI Arguments Together
Professional CLI tools combine: environment variables, config files, command-line arguments.
Example: python deploy.py --config config.yaml --env production
argparse supports this pattern through: FileType, custom loaders, layered parsing logic
🧰 3. Advanced Typer Patterns (Modern CLI Engineering)
⚙️ 4. Handling Errors Gracefully
🧩 5. Building Multi-Command Apps (Professional Structure)
Real CLIs use folder architectures. For Typer:
🧠 6. Environment-Aware Commands
📦 7. Creating "Plugins" for CLI Tools
🔍 8. Auto-generated Help Screens
This UI alone saves hours of documentation. argparse also generates help automatically, but Typer's formatting is noticeably cleaner.
🧱 9. Testing CLI Tools
You can test argparse & Typer apps with pytest using CliRunner. Example for Typer:
🌐 10. Packaging Your CLI as a PIP Installable Tool
You can turn a Typer/argparse script into a real installable command:
This final section focuses on enterprise-grade CLI engineering, including structured logging, configuration layers, packaging/distribution, versioning, interactive shell modes, autocomplete, performance optimisation, security best practices, and production deployment patterns.
⚡ 1. Enterprise-Style Configuration Layers
Professional CLI apps often support configuration from multiple layers:
This allows flexible behaviour: users can override defaults, automation pipelines can use environment variables, developers can test using temporary config files. Typer-based tools commonly use pydantic or dynaconf to manage all layers cleanly.
🧠 2. CLI Autocompletion (Bash, Zsh, Fish)
Modern CLI tools include autocomplete for: commands, options, file paths, arguments.
Under the hood, it generates shell-compatible scripts. This dramatically improves user experience and is a key part of professional developer tools.
📦 3. Packaging as a Standalone Executable (Windows, Mac, Linux)
Not every user has Python installed. You can turn your CLI into one executable file using:
Briefcase — Creates full OS-native installers.
This is how tools become "real" apps that run anywhere.
🧩 4. Versioning & Release Flows
⚙️ 5. Creating Subcommands Like Professional Tools (docker, git, aws-cli)
Practice quiz
Which CLI library ships with Python and needs no installation?
- Typer
- Click
- argparse
- Rich
Answer: argparse. argparse is part of the standard library, so it is built into Python with no extra install.
In argparse, what is the difference between a positional and an optional argument?
- Positionals are required by name; optionals start with - or -- and are not required
- Positionals start with --, optionals do not
- They are identical
- Optionals must come first
Answer: Positionals are required by name; optionals start with - or -- and are not required. Positional arguments (like a filename) are required; optional flags such as --verbose start with - or -- and are not required.
How do you make an argparse flag like --verbose a simple on/off switch?
- type=bool
- nargs=0
action='store_true' makes the flag store True when present and False otherwise.
Which add_argument option restricts a value to a fixed set like low/medium/high?
- nargs
- choices
- default
- metavar
Answer: choices. choices=['low','medium','high'] makes argparse reject any value outside that list automatically.
What does nargs="+" do for an argument?
- Accepts one or more values into a list
- Makes it optional
- Adds a default of 1
- Allows only one value
Answer: Accepts one or more values into a list. nargs='+' collects one or more values, useful for batch operations like --files a.txt b.txt c.txt.
How does argparse let a tool behave like git with add/commit/push subcommands?
- parser.add_argument('sub')
- parser.subcommand()
- parser.add_subparsers() with sub.add_parser('add')
- It cannot do subcommands
Answer: parser.add_subparsers() with sub.add_parser('add'). add_subparsers() creates a subcommand dispatcher, and sub.add_parser('add') defines each subcommand.
Who created Typer, and what framework is it modeled after?
- Guido van Rossum, modeled on Django
- The creator of FastAPI, sharing its type-hint style
- The Flask team
- The pytest team
Answer: The creator of FastAPI, sharing its type-hint style. Typer is built by the creator of FastAPI and uses the same type-hint-driven, modern style.
How does Typer know an argument's type and validate it?
- You write manual isinstance checks
- It guesses from the value
- You pass a type= argument like argparse
- From the function's type hints (e.g. name: str, count: int)
Answer: From the function's type hints (e.g. name: str, count: int). Typer reads the command function's type hints to validate and convert arguments automatically.
Which is the recommended way to keep secrets like API keys out of a CLI tool?
- Hard-code them in the script
- Read them from environment variables (e.g. os.getenv)
- Store them in the --help text
- Commit them to Git
Answer: Read them from environment variables (e.g. os.getenv). The lesson stresses using environment variables / .env loaders and never hard-coding secrets in code.
In pyproject.toml, what makes a Typer/argparse script installable as a real command?
A [project.scripts] entry like learnfast = 'app.main:app' exposes the app as an installable console command.