Skip to main content

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.