Accessing the Execution Context
To access internal state and metadata about the current CLI execution, you can use the typer.Context and typer.CallbackParam classes. These classes provide access to the underlying Click context and parameter objects.
Accessing the Execution Context
You can access the execution context by adding a parameter type-hinted with typer.Context to your command or callback function. Typer will automatically inject the current context object.
import typer
app = typer.Typer()
@app.command()
def main(ctx: typer.Context):
print(f"Executing command: {ctx.info_name}")
# Access parsed parameters
print(f"Parameters: {ctx.params}")
if __name__ == "__main__":
app()
Identifying Invoked Subcommands
In a global callback (using @app.callback()), you can use typer.Context to determine which subcommand is about to be executed via the invoked_subcommand property.
import typer
app = typer.Typer()
@app.command()
def create(username: str):
print(f"Creating user: {username}")
@app.callback()
def main(ctx: typer.Context):
"""
Manage users in the awesome CLI app.
"""
if ctx.invoked_subcommand:
print(f"About to execute command: {ctx.invoked_subcommand}")
if __name__ == "__main__":
app()
Using CallbackParam in Parameter Callbacks
When writing a callback for a specific Option or Argument, you can use typer.CallbackParam to access metadata about the parameter that triggered the callback, such as its name.
from typing import Annotated
import typer
def name_callback(ctx: typer.Context, param: typer.CallbackParam, value: str):
# Check if we are just parsing for completion/help
if ctx.resilient_parsing:
return
print(f"Validating parameter: {param.name}")
if value != "Camila":
raise typer.BadParameter("Only Camila is allowed")
return value
app = typer.Typer()
@app.command()
def main(name: Annotated[str, typer.Option(callback=name_callback)] = "John"):
print(f"Hello {name}")
if __name__ == "__main__":
app()
Handling Extra Arguments
If you need to capture arbitrary arguments that aren't defined in your function signature, configure context_settings to allow extra arguments and then access them via ctx.args.
import typer
app = typer.Typer()
@app.command(
context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
)
def main(ctx: typer.Context):
for extra_arg in ctx.args:
print(f"Got extra arg: {extra_arg}")
if __name__ == "__main__":
app()
Troubleshooting: Resilient Parsing
When using typer.Context inside a callback, you may encounter situations where the callback is executed during shell completion or help generation rather than actual command execution.
To prevent side effects (like database writes or network calls) during these phases, always check ctx.resilient_parsing:
def my_callback(ctx: typer.Context, value: str):
if ctx.resilient_parsing:
# The context is in "resilient" mode (e.g. for autocompletion)
# Return early to avoid side effects
return value
# Perform logic that should only happen during execution
...
return value
This is particularly important for typer.CallbackParam usage, as parameter validation logic often needs to be bypassed when the CLI is just trying to provide help or suggestions.