Python Typer Tutorial: Build CLIs with Python in Minutes

Learn how to build CLIs with Python using Typer in a few simple steps.



Python Typer Tutorial: Build CLIs with Python in Minutes
Image by Author | Created on Canva

 

In this tutorial, we'll build a Command Line Interface (CLI) using Typer, a Python library that makes building CLIs fast and simple. Typer also leverages Python's type hints.

This tutorial will walk you through how to build a CLI for a schedule tracker. Specifically, we’ll learn how to:

  • Set up Typer
  • Add commands
  • Handle task, time, and priority—input and data types correctly

Let’s get started!

 

Step 1: Install Typer

 

First, let's install Typer:

$ pip3 install typer

 

Installing Typer automatically installs all the required dependencies, which facilitates the command-line interface functionality. Please install Typer in a virtual environment for the project.

Here’s the GitHub repository for this simple project.

 

Step 2: Create the Basic CLI

 

Let’s start by creating a simple CLI that can add a task to a schedule with the correct time format.

Create a Python file named schedule_tracker.py.

Import the required libraries and modules. The typer.Typer() instance (app) manages the CLI commands.

import typer
from datetime import datetime
import json
from typing import List

app = typer.Typer()

 

We define a few helper functions to load the schedule from and save it to a JSON file:

SCHEDULE_FILE = "schedule.json"

def load_schedule() -> List[dict]:
    try:
        with open(SCHEDULE_FILE, "r") as f:
            return json.load(f)
    except (FileNotFoundError, json.JSONDecodeError):
        return []

def save_schedule(schedule: List[dict]):
    with open(SCHEDULE_FILE, "w") as f:
        json.dump(schedule, f, default=str, indent=4)

 

Because we have a time associated with each task, let’s create a helper function that parses the string to a valid time object:

def parse_time(t: str) -> datetime.time:
    try:
        return datetime.strptime(t, "%H:%M").time()
    except ValueError:
        typer.echo("Invalid time format. Please use HH:MM.")
        raise typer.Exit()

 

Create the basic add_task command. The task (a description of the task), the time, and priority define each task item:

@app.command()
def add_task(
	task: str,
	time: str = typer.Option(..., help="Time in HH:MM format"),
	priority: int = typer.Option(1, help="Priority of the task")
):
    schedule = load_schedule()
    task_time = parse_time(time)
    schedule.append({"task": task, "time": task_time.strftime("%H:%M"), "priority": priority})
    save_schedule(schedule)
    typer.echo(f"Task '{task}' added at {task_time.strftime('%H:%M')} with priority {priority}")

if __name__ == "__main__":
	app()

 

Step 3: Run the CLI

 

Now run schedule_tracker.py to add tasks like so:

$ python3 schedule_tracker.py add-task "Team meeting" --time "14:00" --priority 2

 

Which outputs:

Task 'Team meeting' added at 14:00 with priority 2

 

Now you have a working CLI that accepts tasks with associated time and priority!

 

Step 4: Add More Commands

 

Let’s add more functionality to our schedule tracker, such as viewing and removing tasks.

First, add a command to view tasks sorted by time:

@app.command()
def list_tasks():
    """List all scheduled tasks."""
    schedule = load_schedule()
    if not schedule:
        typer.echo("No tasks found.")
        return
    for task in sorted(schedule, key=lambda x: x["time"]):
        @app.command()
        print(f"Task {i}: {task['task']}")
        print(f"  Time: {task['time']}")
        print(f"  Priority: {task['priority']}")
        print("-" * 40)  # Add a separator line for better readability

 

You can modify this function as needed to sort tasks by priority as well.

Let’s also add a command to remove tasks by their index number:

@appcommand()
def remove_task(task_number: int):
    """Remove a task by its number."""
    schedule = load_schedule()
    if 0 < task_number <= len(schedule):
        removed_task = schedule.pop(task_number - 1)
        save_schedule(schedule)  # Save the updated schedule
        typer.echo(f"Removed task '{removed_task['task']}' scheduled at {removed_task['time']}") 
    else: 
        typer.echo(f"Invalid task number. Choose a number between 1 and {len(schedule)}.")

 

Step 5: Test the Improved CLI

 

Now, test the following commands.

Add multiple tasks:

$ python3 schedule_tracker.py add-task "Code review" --time "10:30" --priority 1
$ python3 schedule_tracker.py add-task "Client meeting" --time "12:00" --priority 3

 

Doing so, you'll see:

Task 'Code review' added at 10:30 with priority 1
Task 'Client meeting' added at 12:00 with priority 3

 

View all tasks:

$ python3 schedule_tracker.py list-tasks

 

Running this command outputs:

Task 0: Code review
  Time: 10:30
  Priority: 1
----------------------------------------
Task 1: Client meeting
  Time: 12:00
  Priority: 3
----------------------------------------
Task 2: Team meeting
  Time: 14:00
  Priority: 2
----------------------------------------

 

Remove a task:

$ python3 schedule_tracker.py remove-task 1

 

This outputs:

Removed task 'Team meeting' scheduled at 14:00

 

View the updated task list:

$ python3 schedule_tracker.py list-tasks

 

We should now see the following output:

Task 0: Code review
  Time: 10:30
  Priority: 1
----------------------------------------
Task 1: Client meeting
  Time: 12:00
  Priority: 3
----------------------------------------

 

Wrapping Up

 

That’s all for this tutorial. As seen, with Typer, you can create simple yet powerful CLIs in just minutes. In this tutorial, we built a schedule tracker that handles tasks and time input validation efficiently.

You can now improve the version we’ve built. You can extend this project by adding more features like recurring tasks, reminders, or exporting the schedule. Or you can try building a similar app for tracking expenses.

Happy coding!

 

 

Bala Priya is a developer, educator, and technical writer based in India. She writes about programming, data science, machine learning, and AI, with a focus on making complex technical ideas practical and approachable. She creates tutorials, how-to guides, and deep dives that help developers build, solve problems, and understand complex technical concepts. Her technical interests include LLM applications, agentic AI, graph algorithms, computer vision, explainable AI, and ML systems. When she’s not writing or coding, Bala is usually reading classic literature, epic fantasy, or speculative fiction... with a cup of coffee close by. She also enjoys talking about books, learning new things, and sharing what she learns with the developer community.


Get the FREE ebook 'KDnuggets Artificial Intelligence Pocket Dictionary' along with the leading newsletter on Data Science, Machine Learning, AI & Analytics straight to your inbox.

By subscribing you accept KDnuggets Privacy Policy


Get the FREE ebook 'KDnuggets Artificial Intelligence Pocket Dictionary' along with the leading newsletter on Data Science, Machine Learning, AI & Analytics straight to your inbox.

By subscribing you accept KDnuggets Privacy Policy

Get the FREE ebook 'KDnuggets Artificial Intelligence Pocket Dictionary' along with the leading newsletter on Data Science, Machine Learning, AI & Analytics straight to your inbox.

By subscribing you accept KDnuggets Privacy Policy

No, thanks!