Context state

Click Extra’s option callbacks publish their resolved values on Click’s Context.meta dict. That dict is shared across the parent/child context hierarchy and lives for the duration of a single CLI invocation, so it doubles as a per-request shared bus between Click Extra’s eager callbacks and your own command body.

If you are writing a @command- or @group-decorated function, you can read any of the entries below at any point: in the function body, in a parameter callback, in a @pass_context consumer, or in a subcommand of a group that declared one of the options. Click Extra’s default options (--verbosity, --theme, --config, --time, etc.) are wired in automatically by @command / @group, so the corresponding entries are populated without you having to opt in.

Picking values up from your own callbacks

Every key Click Extra owns lives under the click_extra. namespace and is exposed as a constant in the click_extra.context module:

from click_extra import command, context, echo, pass_context

@command
@pass_context
def status(ctx):
    """Print a status line tagged with the current verbosity."""
    level = ctx.meta[context.VERBOSITY_LEVEL]
    echo(f"[{level}] all systems nominal.")
$ status --verbosity INFO
[INFO] all systems nominal.

You may also reach the same entry through the literal string (ctx.meta["click_extra.verbosity_level"]): the constants only fix the spelling in one place and document who owns each entry.

Available keys

The table below lists every entry Click Extra writes, the option that triggers it, and the value’s shape. Entries marked write-only are not read back internally: they exist so your code can inspect what the user picked.

Constant

String key

Set by

Value

context.RAW_ARGS

click_extra.raw_args

ExtraCommand.make_context (always, on @command group)

list[str] — pre-parsed argv slice fed to the current command

context.CONF_SOURCE

click_extra.conf_source

ConfigOption.load_conf (@config_option)

pathlib.Path | URL | None — file the configuration was loaded from

context.CONF_FULL

click_extra.conf_full

ConfigOption.load_conf (@config_option)

dict | None — full parsed configuration document

context.TOOL_CONFIG

click_extra.tool_config

ConfigOption._apply_config_schema (with config_schema)

The deserialised app section (also reachable via get_tool_config())

context.VERBOSITY_LEVEL

click_extra.verbosity_level

--verbosity / --verbose callbacks (reconciled)

LogLevel — the highest level any verbosity option picked

context.VERBOSITY

click_extra.verbosity

--verbosity callback

LogLevel — raw value of --verbosity LEVEL (write-only)

context.VERBOSE

click_extra.verbose

--verbose / -v callback

int — repetition count (write-only)

context.START_TIME

click_extra.start_time

--time callback (@timer_option)

floattime.perf_counter() snapshot

context.JOBS

click_extra.jobs

--jobs callback (@jobs_option)

int — effective parallel job count (clamped to >= 1)

context.TABLE_FORMAT

click_extra.table_format

--table-format callback (@table_format_option)

TableFormat

context.SORT_BY

click_extra.sort_by

--sort-by callback (@sort_by_option)

tuple[str, ...] — column IDs in priority order

context.THEME

click_extra.theme.active

--theme callback (always present on @command)

HelpExtraTheme — palette picked for this invocation

Worked examples

Switching behaviour on the active theme

from click_extra import command, context, echo, pass_context

@command
@pass_context
def report(ctx):
    """Render a status line in the active theme's success colour."""
    theme = ctx.meta[context.THEME]
    echo(theme.success("OK"))
$ report --theme dark
OK

Driving parallelism off --jobs

--jobs is not part of the default options, so it has to be added explicitly via @jobs_option:

from click_extra import command, context, echo, jobs_option, pass_context

@command
@jobs_option
@pass_context
def crunch(ctx):
    """Demonstrate reading the resolved `--jobs` value."""
    echo(f"Working with {ctx.meta[context.JOBS]} workers.")
$ crunch --jobs 4
warning: Requested 4 jobs exceeds available CPU cores (1).
Working with 4 workers.

Inspecting the loaded configuration

--config is part of the default options. The block below uses --no-config to skip discovery, then reads CONF_SOURCE to confirm no file was loaded:

from click_extra import command, context, echo, pass_context

@command
@pass_context
def show_conf(ctx):
    """Print which configuration file (if any) was loaded."""
    source = ctx.meta.get(context.CONF_SOURCE)
    echo(f"config: {source or 'none'}")
$ show-conf --no-config
Skip configuration file loading altogether.
config: none

Reaching the context outside the command body

Inside a @command-decorated function, you can either accept ctx via @pass_context or call click.get_current_context() from any helper that runs while the CLI is being invoked. Both give you the same context, and both expose the same .meta dict.

Caution

Outside an active CLI invocation (e.g. at import time, in unit tests that build options directly without invoking a CLI, or in a REPL) there is no context, and these keys are not available. Helpers that need to work in both modes should fall through to a sane default. The theming layer does this with get_current_theme(), which returns the module-level default_theme when no context is in flight.

click_extra.context API

Click context plumbing: the ExtraContext subclass plus the central registry of every ctx.meta key Click Extra writes or reads.

Click’s click.Context.meta is a per-invocation dict that Click shares across the parent/child context hierarchy. Click Extra uses it to pass per-invocation state (the picked theme, the resolved table format, the loaded configuration, etc.) between eager callbacks and the rest of the CLI without mutating module-level globals. Per-invocation context storage is what keeps back-to-back invocations of the same CLI (Sphinx builds, test runners, REPLs) from leaking state into each other.

This module is part of Click Extra’s public API. Inside any @command- or @group-decorated function, request the active context with click.pass_context() (or call click.get_current_context()) and read the entries you need:

from click_extra import command, context, echo, pass_context

@command
@pass_context
def cli(ctx):
    echo(f"Theme: {ctx.meta[context.THEME]}")
    echo(f"Jobs:  {ctx.meta[context.JOBS]}")

Each constant below documents who writes the entry, when, and what shape the value takes. The raw string values are stable and downstream code may also read ctx.meta["click_extra.<field>"] directly: the constants exist so internal call sites and downstream code can converge on a single spelling.

class click_extra.context.ExtraContext(*args, meta=None, **kwargs)[source]

Bases: Context

Like cloup._context.Context, but with the ability to populate the context’s meta property at instantiation.

Also defaults color to True for root contexts (i.e. without a parent), so help screens are always colorized — even when piped. Click’s own default is None (auto-detect via TTY), which strips colors in non-interactive contexts.

Parent-to-child color inheritance is handled by Click itself at Context.__init__ time, so no property override is needed.

Todo

Propose addition of meta keyword upstream to Click.

Like parent’s context but with an extra meta keyword-argument.

Also force color default to True if not provided by user and this context has no parent.

formatter_class

Use our own formatter to colorize the help screen.

alias of HelpExtraFormatter

click_extra.context.META_NAMESPACE: Final[str] = 'click_extra.'

Prefix shared by every ctx.meta key Click Extra writes.

Reserved for entries the framework owns. Downstream consumers picking their own ctx.meta keys are encouraged to use a different prefix to avoid colliding with current or future Click Extra entries.

click_extra.context.RAW_ARGS: Final[str] = 'click_extra.raw_args'

The pre-parsed argv slice fed to the current command.

Written by click_extra.commands.ExtraCommand.make_context so that click_extra.parameters.ShowParamsOption can re-parse the original arguments for the --show-params table without re-running the callbacks.

click_extra.context.CONF_SOURCE: Final[str] = 'click_extra.conf_source'

Resolved path or URL of the configuration file that was loaded.

Written by click_extra.config.ConfigOption.load_conf after a configuration file is found and parsed. None if no file matched.

click_extra.context.CONF_FULL: Final[str] = 'click_extra.conf_full'

Full parsed configuration document (the whole file, every section).

Written by click_extra.config.ConfigOption.load_conf. Read by click_extra.commands.ExtraGroup (for subcommand inheritance) and by click_extra.wrap.run() (to forward the loaded config to wrapped CLIs).

click_extra.context.TOOL_CONFIG: Final[str] = 'click_extra.tool_config'

The app-specific config section, deserialised through config_schema.

Written by click_extra.config.ConfigOption._apply_config_schema only when a schema callable is configured. Read via click_extra.config.get_tool_config().

click_extra.context.VERBOSITY_LEVEL: Final[str] = 'click_extra.verbosity_level'

The reconciled LogLevel chosen for the run.

Written by click_extra.logging.ExtraVerbosity.set_level(), which arbitrates between every verbosity-related option (--verbosity, --verbose/-v) and keeps the highest pick. Read by the same callback to detect prior writes from sibling options.

click_extra.context.VERBOSITY: Final[str] = 'click_extra.verbosity'

Raw value of --verbosity LEVEL as the user passed it.

Written by click_extra.logging.VerbosityOption.set_level(). Stored alongside VERBOSITY_LEVEL so downstream code can tell whether the final level came from --verbosity or from -v repetitions.

click_extra.context.VERBOSE: Final[str] = 'click_extra.verbose'

Raw repetition count of --verbose/-v.

Written by click_extra.logging.VerboseOption.set_level(). Same role as VERBOSITY for the -v family of flags.

click_extra.context.START_TIME: Final[str] = 'click_extra.start_time'

time.perf_counter() snapshot taken when --time is enabled.

Written by click_extra.timer.TimerOption.register_timer_on_close.

click_extra.context.JOBS: Final[str] = 'click_extra.jobs'

Effective parallel job count after clamping (always >= 1).

Written by click_extra.jobs.JobsOption.validate_jobs. Click Extra itself does not act on this value: it is a contract for downstream commands that drive their own concurrency.

click_extra.context.TABLE_FORMAT: Final[str] = 'click_extra.table_format'

The TableFormat chosen via --table-format.

Written by click_extra.table.TableFormatOption.init_formatter. Read by click_extra.table.SortByOption to thread the same format through ctx.print_table.

click_extra.context.SORT_BY: Final[str] = 'click_extra.sort_by'

Tuple of column IDs picked via --sort-by (in priority order).

Written by click_extra.table.SortByOption.init_sort.

click_extra.context.THEME: Final[str] = 'click_extra.theme.active'

The HelpExtraTheme active for this invocation.

Written by click_extra.theme.ThemeOption.set_theme. Read via click_extra.theme.get_current_theme(), which falls back to click_extra.theme.default_theme when no key is set.

click_extra.context.get(ctx, key, default=None)[source]

Read key from the current context’s shared meta dict.

Equivalent to ctx.meta.get(key, default). Click’s meta is shared across the parent/child hierarchy, so reading from the local context is sufficient: there is no need to walk up to the root manually.

Return type:

Any

click_extra.context.set(ctx, key, value)[source]

Write value under key in the current context’s shared meta dict.

Equivalent to ctx.meta[key] = value. Provided as the symmetric writer for get() so that callers can route both sides of a meta access through this module.

Return type:

None