How to Design Great CLI Apps with Python

How to Design Great CLI Apps with Python

2025-12-15
PythonCLIOpen Source

Command Line Interfaces (CLIs) are the bread and butter of developer efficiency. While Graphical User Interfaces (GUIs) are great for end-users, CLIs are often faster and more scriptable for developers. However, writing a CLI isn't just about parsing arguments; it's about creating a tool that is intuitive, helpful, and pleasant to use.

As a junior developer, moving beyond simple scripts to robust CLI applications is a major step up. Here is how to design great CLI apps using Python.

1. Prioritize Developer Experience (DX)

Just because a tool runs in a terminal doesn't mean it should be ugly or confusing. A great CLI adheres to the Principle of Least Astonishment.

  • Help Flags: Always ensure your app responds to --help with clear instructions.
  • Sensible Defaults: Don't force the user to type 10 arguments if 9 of them usually have the same value.
  • Standard Output: Send data to stdout and errors to stderr. This allows users to pipe your output into other tools safely.

2. Choosing the Right Library: Typer

Python comes with a built-in library called argparse. While powerful, it requires a lot of boilerplate code.

For modern Python development, Typer is the gold standard. It is built on top of the popular library Click but leverages Python type hints to define arguments automatically.

Here is how simple a CLI is with Typer:

import typer

def main(name: str, formal: bool = False):
    if formal:
        typer.echo(f"Good day to you, {name}.")
    else:
        typer.echo(f"Hey {name}!")

if __name__ == "__main__":
    typer.run(main)

With just that code, Typer automatically generates help text, handles boolean flags (--formal), and validates input types.

3. Making it Interactive and Beautiful with 'Rich'

The terminal used to be monochrome, but it doesn't have to be. To make your CLI "great" rather than just "functional," you need Rich.

Rich is a Python library for rich text and beautiful formatting in the terminal. It creates progress bars, markdown rendering, syntax highlighting, and tables with almost zero effort.

Here is an example of printing a table of data:

from rich.console import Console
from rich.table import Table

console = Console()

table = Table(title="Server Status")

table.add_column("ID", style="cyan", no_wrap=True)
table.add_column("Status", style="magenta")
table.add_column("IP Address", justify="right", style="green")

table.add_row("101", "Active", "192.168.1.1")
table.add_row("102", "Offline", "192.168.1.2")

console.print(table)

4. Interactive Prompts

Sometimes you need to ask the user for input dynamically (like a confirmation Are you sure? [y/N]).

While you can use the built-in input(), it is brittle. Libraries like Questionary or rich prompts allow you to create select lists, checkboxes, and password inputs easily.

import questionary

flavor = questionary.select(
    "What is your favorite flavor?",
    choices=[
        "Chocolate",
        "Vanilla",
        "Strawberry",
    ]
).ask()

print(f"You chose {flavor}")

Summary

To build a CLI that other developers will love:

  1. Use Typer for argument parsing to save time and reduce bugs.
  2. Use Rich to provide visual feedback (colors, tables, progress bars).
  3. Respect the user by providing help text and standard exit codes.

Great tools are a joy to use. With Python's ecosystem, you can build professional-grade CLIs in minutes.