cli.run

otto.cli.run.list_instructions_callback(value)
Return type:

None

otto.cli.run.main(ctx, list_instructions=False)
otto.cli.run.instruction(*args, options=None, **kwargs)

Register an async function as an otto run subcommand.

When options is a dataclass, the decorator expands its fields (including inherited ones) into individual CLI flags — exactly like @register_suite() does for suite options. The original function must declare a parameter annotated with the options class; the decorator replaces it with the expanded fields and, at call time, constructs the populated dataclass instance before forwarding it to the function.

If the function declares a parameter annotated as OttoContext, that parameter is stripped from the CLI signature and injected at call time from the active context (DI-friendly, additive — existing handlers are unaffected).

Usage without options (unchanged from before):

@instruction()
async def deploy(debug: Annotated[bool, typer.Option()] = False):
    ...

Usage with an options dataclass:

@dataclass
class _Opts(RepoOptions):
    debug: Annotated[bool, typer.Option()] = False

@instruction(options=_Opts)
async def deploy(opts: _Opts):
    print(opts.debug)

Usage with OttoContext injection:

@instruction()
async def status(ctx: OttoContext) -> CommandStatus:
    host = ctx.get_host("router")
    ...

The same dataclass may be inherited by a suite’s inner Options class, giving both otto test and otto run subcommands a uniform set of repo-wide flags.