Parameters and Inputs
In Typer, CLI parameters are defined as function arguments in your command functions. The library distinguishes between Options (prefixed with -- or -) and Arguments (positional inputs). The modern and recommended way to configure these is using typing.Annotated, which allows you to attach metadata to your types without breaking standard Python type hinting.
Core Parameter Types
Typer provides two primary functions in typer/params.py to define CLI inputs:
typer.Option: Used for optional parameters, flags, and configurations.typer.Argument: Used for required positional data.
Internally, these functions return instances of OptionInfo and ArgumentInfo (defined in typer/models.py), which store metadata until the command is invoked and converted into Click objects.
The Annotated Pattern
The preferred way to define parameters is by wrapping the type in Annotated. This keeps the default value of the function parameter as the actual default value of the CLI input.
from typing import Annotated
import typer
app = typer.Typer()
@app.command()
def main(
name: Annotated[str, typer.Argument(help="The name of the user")] = "World",
lastname: Annotated[str, typer.Option(help="The last name of the user")] = "",
):
print(f"Hello {name} {lastname}")
In this example, name is a positional argument with a default of "World", and lastname is a CLI option (--lastname).
Configuring Options
typer.Option supports a wide range of metadata to control how the CLI behaves.
Custom Names and Aliases
You can provide multiple names for an option. If no name is provided, Typer automatically uses the function parameter name (converting underscores to hyphens).
@app.command()
def main(user_name: Annotated[str, typer.Option("--user", "-u", "-x")]):
print(f"Hello {user_name}")
Found in typer/params.py
Counters
For options like verbosity levels (e.g., -vvv), use the count=True parameter. The type should be int.
@app.command()
def main(verbose: Annotated[int, typer.Option("--verbose", "-v", count=True)] = 0):
print(f"Verbose level is {verbose}")
Found in typer/params.py
Interactive Prompts
Options can be configured to prompt the user if they are not provided on the command line. This is particularly useful for sensitive information like passwords.
@app.command()
def login(
name: str,
password: Annotated[str, typer.Option(prompt=True, hide_input=True)],
):
print(f"Hello {name}. Doing something very secure with password.")
Found in typer/params.py
Configuring Arguments
typer.Argument is used for positional inputs. By default, arguments are required unless a default value is provided.
Required vs. Optional
To explicitly mark an argument as required while still using Annotated, use ... (Ellipsis) as the default value.
@app.command()
def main(name: Annotated[str, typer.Argument()] = ...):
print(f"Hello {name}")
Custom Metavars
The metavar parameter in ArgumentInfo (and OptionInfo) allows you to change how the parameter is represented in the help text.
@app.command()
def main(name: Annotated[str, typer.Argument(metavar="✨username✨")]):
print(f"Hello {name}")
Found in typer/params.py
Environment Variable Mapping
Both Option and Argument can be mapped to environment variables using the envvar parameter. If the CLI parameter is not provided, Typer will look for the specified environment variable.
@app.command()
def main(name: Annotated[str, typer.Argument(envvar="ME")]):
print(f"Hello Mr. {name}")
Found in typer/params.py
You can also hide the environment variable from the help text using show_envvar=False.
Validation and Constraints
Typer leverages Click's underlying validation logic while providing a cleaner interface through ParameterInfo.
Numeric Constraints
For int or float types, you can use min and max to enforce ranges. The clamp parameter can be used to force values into the range instead of raising an error.
@app.command()
def main(
user_id: Annotated[int, typer.Option(min=1, max=1000, clamp=True)],
):
print(f"ID is {user_id}")
Found in typer/params.py
Custom Parsers
If you need to handle complex types, you can provide a custom parser function. This function takes a str and returns the parsed object.
def my_parser(value: str):
return f"Parsed: {value}"
@app.command()
def main(opt: Annotated[str, typer.Option(parser=my_parser)] = "Foo"):
print(opt)
Found in typer/params.py
Internal Implementation Details
The metadata for parameters is managed by classes in typer/models.py:
ParameterInfo: The base class for all parameter metadata, containing shared fields likedefault,callback,envvar, andhelp.OptionInfo: ExtendsParameterInfowith option-specific fields likeprompt,confirmation_prompt, andcount.ArgumentInfo: ExtendsParameterInfospecifically for positional arguments.
When a command is registered, Typer inspects the function signature, extracts these Info objects from the Annotated types, and uses them to construct TyperOption or TyperArgument objects (found in typer/core.py), which are specialized subclasses of click.Option and click.Argument.
Deprecation Warnings
Note that the following patterns are deprecated in this codebase:
- Using
typer.Option()ortyper.Argument()as the default value of a function parameter (e.g.,def main(name=typer.Option("World"))). UseAnnotatedinstead. - The
is_flagandflag_valueparameters intyper.Option. Typer handles flags automatically based on the type hint (e.g.,bool). - The
shell_completeparameter is being phased out in favor ofautocompletion.