Skip to main content

Creating Basic Commands

In this tutorial, you will learn how to build a command-line interface (CLI) with multiple subcommands using the Typer class and the @app.command() decorator. You will create a user management tool that can create and delete users, while exploring how to configure command metadata and help output.

Prerequisites​

To follow this tutorial, you need the typer package installed. If you want to see the enhanced help formatting, ensure rich is also installed.

Step 1: Initialize the Typer Application​

The main entry point for any Typer application is the typer.main.Typer class. This object acts as a registry for your commands.

import typer

app = typer.Typer()

By creating an instance of Typer, you gain access to the @app.command() decorator, which you will use to register functions as CLI commands.

Step 2: Define a Basic Command​

To turn a Python function into a CLI command, decorate it with @app.command(). Typer automatically inspects the function signature to determine the command's arguments.

@app.command()
def create(username: str):
"""
Create a new user with the given USERNAME.
"""
print(f"Creating user: {username}")

When you define a command:

  • Function Name: The function name create becomes the command name in the CLI. If the function name has underscores (e.g., create_user), Typer converts them to hyphens (create-user) by default.
  • Docstrings: The docstring of the function is automatically used as the help text for the command.
  • Arguments: The username: str parameter tells Typer that this command requires a string argument.

Step 3: Add Multiple Commands and Metadata​

You can add as many commands as you need to the same app instance. You can also pass configuration parameters to the @app.command() decorator to control how the command appears in the help output.

@app.command(deprecated=True, help="Remove a user from the system.")
def delete(username: str):
"""
This docstring is ignored because the 'help' parameter is provided.
"""
print(f"Deleting user: {username}")

In this example:

  • deprecated=True: This marks the command as deprecated in the help output, warning users that it may be removed in the future.
  • help="...": This explicitly sets the help text, overriding the function's docstring.

Step 4: Organize Commands with Rich Help Panels​

If you have many commands, you can group them into logical sections in the help output using the rich_help_panel parameter. This requires the rich library to be installed.

@app.command(rich_help_panel="Maintenance")
def sync():
"""
Synchronize user data with the remote server.
"""
print("Syncing...")

When a user runs --help, the sync command will be displayed under a specific "Maintenance" header rather than the default "Commands" list.

Step 5: Execute the Application​

To make your script executable from the command line, call the app instance as a function. This triggers the Typer.__call__ method, which handles argument parsing and command execution.

if __name__ == "__main__":
app()

Complete Working Example​

Combining all the steps, here is a complete script based on the docs_src/commands/help/tutorial003_py310.py and tutorial006_py310.py examples:

import typer

# Initialize the app with Rich markup enabled for help text
app = typer.Typer(rich_markup_mode="rich")

@app.command()
def create(username: str):
"""
[green]Create[/green] a new user. :sparkles:
"""
print(f"Creating user: {username}")

@app.command(deprecated=True)
def delete(username: str):
"""
[red]Delete[/red] a user. :x:
"""
print(f"Deleting user: {username}")

@app.command(rich_help_panel="Maintenance")
def sync():
"""
[blue]Synchronize[/blue] the system. :recycle:
"""
print("Syncing the system")

if __name__ == "__main__":
app()

Verifying the Result​

You can now run your application from the terminal:

  1. View Help: Run python main.py --help. You will see the commands listed, with delete marked as deprecated and sync grouped under "Maintenance".
  2. Run a Command: Run python main.py create hiro.
    • Output: Creating user: hiro
  3. Missing Arguments: Run python main.py create. Typer will automatically show an error message indicating that the username argument is missing.

Next Steps​

Now that you can create basic commands, you can explore Command Contexts to access the underlying click.Context or learn about Sub-Typer instances to nest groups of commands into a hierarchical structure.