from typing import List, Optional

import typer


def main(device: Optional[List[str]] = typer.Option(None)):
    if not device:
        print("No provided devices")
        raise typer.Abort()
    for d in device:
        print(f"Processing device: {d}")


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

And then it can be used like in:

$ ./my_cli --device 1 --device 2

Take a look at the documentation.

If the only input for the CLI is a list of devices, you can simplify it to using arguments instead. Then it could be used like:

$ ./my_cli 1 2
Answer from ericbn on Stack Overflow
🌐
Typer
typer.tiangolo.com › tutorial › multiple-values › multiple-options
Multiple CLI Options - Typer
For this, use the standard Python list to declare it as a list of str: ... from typing import Annotated import typer app = typer.Typer() @app.command() def main(user: Annotated[list[str] | None, typer.Option()] = None): if not user: print(f"No provided users (raw input = {user})") raise typer.Abort() for u in user: print(f"Processing user: {u}") if __name__ == "__main__": app()
🌐
Typer
typer.tiangolo.com › tutorial › multiple-values › arguments-with-multiple-values
CLI Arguments with Multiple Values - Typer
You can define the type of a CLI argument using list. ... from pathlib import Path import typer app = typer.Typer() @app.command() def main(files: list[Path], celebration: str): for path in files: if path.is_file(): print(f"This file exists: {path.name}") print(celebration) if __name__ == "__main__": app()
🌐
Readthedocs
cyclopts.readthedocs.io › en › latest › vs_typer › optional_list › README.html
Optional Lists - Cyclopts - Read the Docs
This approach can also help differentiate between the intention of using a default list and explicitly requesting an empty list. ... import typer typer_app = typer.Typer() @typer_app.command() def foo(favorite_numbers: Optional[list[int]] = None): if favorite_numbers is None: favorite_numbers = [1, 2, 3] print(f"My favorite numbers are: {favorite_numbers}") typer_app(["--favorite-numbers", "100", "--favorite-numbers", "200"], standalone_mode=False) # My favorite numbers are: [100, 200] typer_app([], standalone_mode=False) # My favorite numbers are: []
🌐
GitHub
github.com › fastapi › typer › issues › 387
Does Typer support Tuples as Multiple Multi Value Options - List[Tuple[str, str]] - like Click does? · Issue #387 · fastapi/typer
April 20, 2022 - import typer from typing import List, Tuple app = typer.Typer() @app.command() def test(opts: List[Tuple[str, str]]): ...
Author: fastapi
🌐
Typer
typer.tiangolo.com › tutorial › multiple-values › options-with-multiple-values
CLI Options with Multiple Values - Typer
import typer app = typer.Typer() @app.command() def main(user: tuple[str, int, bool] = typer.Option((None, None, None))): username, coins, is_wizard = user if not username: print("No user provided") raise typer.Abort() print(f"The username {username} has {coins} coins") if is_wizard: print("And this user is a wizard!") if __name__ == "__main__": app()
🌐
Typer
typer.tiangolo.com › tutorial › parameter-types
CLI Parameter Types - Typer
import typer app = typer.Typer() @app.command() def main(name: str, age: int = 20, height_meters: float = 1.89, female: bool = True): print(f"NAME is {name}, of type: {type(name)}") print(f"--age is {age}, of type: {type(age)}") print(f"--height-meters is {height_meters}, of type: {type(height_meters)}") print(f"--female is {female}, of type: {type(female)}") if __name__ == "__main__": app()
Find elsewhere
🌐
Calmcode
calmcode.io › course › typer › options
Calmcode - typer: Options
import typer from typing import List from pathlib import Path app = typer.Typer(name="demo", add_completion=False, help="This is a demo app.") @app.command() def talk(text: str = typer.Argument(..., help="The text to type."), repeat: int = typer.Option(1, help="Number of times to repeat."), loud: bool = typer.Option(False, is_flag=True)): """Talks some text below""" if loud: text = text.upper() for _ in range(repeat): print(text) if __name__ == "__main__": app() The talk command can be run in multiple ways now.
🌐
Real Python
realpython.com › python-typer-cli
Build a Command-Line To-Do App With Python and Typer – Real Python
July 3, 2026 - Now you have a way to retrieve the database file path from the application’s configuration file. You also have a way to initialize the database with an empty to-do list in JSON format. It’s time to implement the init command with Typer so that your users can initialize their to-do database from the CLI.
🌐
Calmcode
calmcode.io › course › typer › subcommands
Calmcode - typer: Subcommands
import typer from typing import List from pathlib import Path from .db import app as db_app app = typer.Typer(name="demo", add_completion=False, help="This is a demo app.") # Here is where we attach subcommands as a group app.add_typer(db_app, name="db") @app.command() def hello_world(name): """Say hello""" print(f"hello {name}!") @app.command() def goodbye_world(name): """Say goodbye""" print(f"goodbye {name}!") @app.command() def add(n1: int = typer.Argument(..., help="An integer"), n2: int = typer.Argument(1, help="An integer")): """Add two numbers""" print(n1 + n2) def check_file_exists(pa
🌐
Blue Book
lyz-code.github.io › blue-book › typer
Typer - The Blue Book
import typer app = typer.Typer() items_app = typer.Typer() app.add_typer(items_app, name="items") users_app = typer.Typer() app.add_typer(users_app, name="users") @items_app.command("create") def items_create(item: str): print(f"Creating item: {item}") @items_app.command("delete") def items_delete(item: str): print(f"Deleting item: {item}") @items_app.command("sell") def items_sell(item: str): print(f"Selling item: {item}") @users_app.command("create") def users_create(user_name: str): print(f"Creating user: {user_name}") @users_app.command("delete") def users_delete(user_name: str): print(f"Deleting user: {user_name}") if __name__ == "__main__": app()
🌐
Typer
typer.tiangolo.com › reference › typer
Typer class - Typer
Here's the reference information for the Typer class, with all its parameters, attributes and methods.
🌐
Open-typer
open-typer.github.io › docs › annotated.html
Open-Typer: Class List
Loading · Searching · No Matches · Class List · Here are the classes, structs, unions and interfaces with brief descriptions: · [detail level 12] · Generated by 1.9.8
🌐
Aph
tech.aph.org › tt_info.htm
Talking Typer - APH Tech - American Printing House
What's New | Instructions | Download | Purchase | Contents · Notice: Accessibility of APH Websites
🌐
Typer
typer.tiangolo.com
Typer - Typer
Run scripts: Typer includes a typer command/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally.
🌐
Splunk
help.splunk.com › en › splunk-enterprise › spl-search-reference › 9.1 › search-commands › typer
typer | Splunk Enterprise (last updated 2025-07-04T02:28:40.544Z)
July 4, 2025 - Under the [typer] stanza, specify the default for the maxlen setting. Returns a field called eventtype which lists the names of the event types associated with the search results.