CLI wrapperยถ

Click Extraโ€™s wrap subcommand runs any installed Click CLI through Click Extra, without modifying the targetโ€™s source code. By default it applies help colorization, useful for previewing how a third-party CLI would look with Click Extraโ€™s keyword highlighting and themed styling. With --show-params or --man, it instead loads the target and describes it without running it.

Usageยถ

The wrap subcommand is the default when no known subcommand is given, so both forms work:

$ click-extra wrap -- flask --help
$ click-extra -- flask --help
$ wrap --help
Usage: wrap [OPTIONS] SCRIPT [ARGS]...
Aliases: run

  Run, or introspect, any Click CLI through Click Extra.

  By default, runs SCRIPT with keyword highlighting and themed styling for its
  help screens. The target CLI is not modified.

  With --show-params, --man or --carapace, SCRIPT is loaded and described
  without being run. Extra arguments after SCRIPT navigate into nested
  subcommands; for --show-params, any trailing options are replayed against the
  resolved command so the parameter table reports their value and source.

  Resolution order for SCRIPT: installed console_scripts entry point, a local
  project directory (its entry point is read from pyproject.toml or setup.cfg),
  Python file path, module:function notation, or Python module name.

Options:
  --show-params           Show the parameters of the target CLI and exit,
                          without running it.
  --man                   Show the man page (roff) of the target CLI and exit,
                          without running it.
  --carapace              Show the Carapace completion spec (YAML) of the target
                          CLI and exit, without running it.
  --output-dir DIRECTORY  With --man, write one .1 file per (sub)command into
                          this directory instead of printing a single page to
                          stdout. Created if missing.
  --install               With --carapace, write the spec into Carapace's user
                          spec directory instead of printing it, and echo the
                          written path.
  --table-format [aligned|asciidoc|colon-grid|csv|csv-excel|csv-excel-tab|csv-unix|double-grid|double-outline|fancy-grid|fancy-outline|github|grid|heavy-grid|heavy-outline|hjson|html|jira|json|json5|jsonc|latex|latex-booktabs|latex-longtable|latex-raw|mediawiki|mixed-grid|mixed-outline|moinmoin|orgtbl|outline|pipe|plain|presto|pretty|psql|rounded-grid|rounded-outline|rst|simple|simple-grid|simple-outline|textile|toml|tsv|unsafehtml|vertical|xml|yaml|youtrack]
                          With --show-params, the rendering style of the
                          parameter table. Falls back to the click-extra group's
                          --table-format when not set here.
  --columns [id,spec,class,param_type,python_type,hidden,exposed,allowed_in_conf,envvars,default,is_flag,flag_value,is_bool_flag,multiple,nargs,prompt,confirmation_prompt,value,source]
                          Restrict and reorder table columns, SQL SELECT-style.
                          Comma-separated list of column IDs. Default: all
                          columns in canonical order.
  -h, --help              Show this message and exit.

Tip

run is an alias for wrap, so you can also use:

$ click-extra run -- flask --help

Wrapping a Click CLIยถ

Pass the target CLI name (or path) as the first argument. Everything after it is forwarded to the target:

$ click-extra -- flask --help
$ click-extra -- black --help
$ click-extra -- ./my_script.py --help
$ click-extra -- ../my-project --help
$ click-extra -- my_package.cli:main --help

Tip

Every example on this page uses the -- separator to visually split Click Extraโ€™s own options from the target CLI and its arguments. It is optional (Click Extra stops parsing its own options at the first token it does not recognize), but using it consistently keeps the two sides of the invocation unambiguous:

$ click-extra --no-color -- flask --help

Execution timingยถ

The group-level --time flag measures the total execution time of the wrapped CLI, including import and patching overhead:

$ click-extra --time -- flask routes
Execution time: 0.342 seconds.

Color controlยถ

--color / --no-color controls whether ANSI codes are emitted. The flag also respects environment variables like NO_COLOR, CLICOLOR, and FORCE_COLOR:

$ click-extra --no-color -- flask --help
$ NO_COLOR=1 click-extra -- flask --help

The group-level --theme option selects a color preset for help screens. The flag is part of click-extraโ€™s default options, so it works on every click-extra command:

$ click-extra --theme light -- flask --help

Custom themes can be registered with register_theme() before the CLI is parsed or declared inside the --config file (see Custom themes via config below). Either way the new name becomes a valid value for --theme for the duration of the invocation.

Configurationยถ

Click Extraโ€™s configuration file support works alongside the wrapper. Group-level options like verbosity can be set in pyproject.toml:

[tool.click-extra]
verbosity = "DEBUG"
$ click-extra -- flask --help
debug: Set <Logger click_extra (DEBUG)> to DEBUG.
...

Defaults for the wrapped CLIยถ

The [tool.click-extra.wrap.<script>] section sets persistent defaults for a specific target CLI. All keys are converted to CLI arguments and prepended to the targetโ€™s invocation:

[tool.click-extra.wrap.flask]
app = "myapp:create_app"
debug = true
$ click-extra -- flask routes
# Equivalent to: flask --app myapp:create_app --debug routes

The section name must match the script name you pass on the command line. Multiple targets can each have their own section:

[tool.click-extra.wrap.flask]
app = "myapp:create_app"

[tool.click-extra.wrap.quart]
app = "otherapp:create_app"

Explicit CLI arguments always override config values:

$ click-extra -- flask --app otherapp routes
# CLI --app wins over config

Invalid option names are caught by the target CLI itself with standard Click error messages, so typos are surfaced immediately.

Custom themes via configยถ

The --config flag also accepts theme overrides and brand-new theme definitions. Drop a [tool.click-extra.themes.<name>] table into the same pyproject.toml and the new palette is loaded before --theme is validated, so it can be selected on the command line or pinned via theme = "...":

[tool.click-extra]
theme = "midnight"

# Override one slot of the built-in `dark` theme:
[tool.click-extra.themes.dark]
option = { fg = "bright_cyan" }

# Define a fresh palette named "midnight":
[tool.click-extra.themes.midnight]
option = { fg = "blue", bold = true }
heading = { fg = "magenta" }
choice = { fg = "yellow" }
$ click-extra --help
# --theme [dark|dracula|light|manpage|midnight|monokai|nord|solarized_dark]
$ click-extra -- flask --help     # rendered with the "midnight" palette

Themes loaded this way live on ctx.meta for the current invocation only. The module-level theme_registry is never mutated, so back-to-back wraps in the same process donโ€™t cross-contaminate. See Themes from your --config file for the full schema and the validation behavior.

Script resolutionยถ

SCRIPT is accepted in five forms, tried in this order:

  1. A console_scripts entry point exposed by an installed package, the most common case:

    $ click-extra wrap -- flask --help
    
  2. A local project directory. Its console-script entry point is read from pyproject.toml ([project.scripts]) or setup.cfg (console_scripts), and the directory holding its top-level package is added to sys.path so it imports without an install step. This is handy for a checked-out project sitting next to your own:

    $ click-extra wrap -- ../my-project --help
    

    Both the flat layout (the package at the project root) and the src layout (under src/) are detected. When several scripts point at different targets, pass the right one with module:function notation; the error lists the candidates. Adding the directory to sys.path makes its package importable, but it does not install the projectโ€™s dependencies, so see Dependencies of the wrapped CLI below.

  3. A .py file path. The file is imported in place, with no install step required:

    $ click-extra wrap -- path/to/my_cli.py --help
    
  4. module:function notation pointing straight at a Click command object. Useful when the entry point is a wrapper rather than the command itself, or when the command isnโ€™t exposed as a console script at all:

    $ click-extra wrap -- flask.cli:cli --help
    
  5. A bare Python module name invocable via python -m. The resolver imports the module and picks up the Click command from its top-level attributes:

    $ click-extra wrap -- my_package.cli --help
    

The same resolver backs every wrap mode, including --show-params and --man.

Dependencies of the wrapped CLIยถ

wrap runs the target inside Click Extraโ€™s own interpreter: it imports the resolved module and calls it in-process (see How it works). The target is never installed into a separate environment, so every third-party package the target imports must already be importable where wrap runs, exactly as if you had launched the target directly.

This bites hardest when wrapping a project directory. Pointing wrap at a checked-out project makes its package importable by putting it on sys.path, but it does not install that projectโ€™s declared dependencies. If the targetโ€™s CLI imports a package that is absent, the failure surfaces from the targetโ€™s own code:

$ click-extra wrap -- ../weather-cli --help
...
ModuleNotFoundError: No module named 'httpx'

A traceback like this means resolution already succeeded and the target started running: the missing module is a dependency of the target, not of Click Extra. It is the same error a direct python -m weather_cli would raise.

The lightest fix is to layer the missing packages onto an ephemeral run with uv, one --with per dependency:

$ uv run --with httpx click-extra wrap -- ../weather-cli --help

Alternatively, run wrap from an environment that already has the target and its dependencies installed (the targetโ€™s own virtualenv, for example).

Ephemeral wrapping with uvxยถ

The wrapper pairs well with uvx for one-shot colorization of any Click CLI without permanently installing Click Extra. The ephemeral environment holds only Click Extra, so the target and anything it imports have to be pulled in with --with (see Dependencies of the wrapped CLI above):

$ uvx --with flask click-extra -- flask --help
$ uvx --with black click-extra -- black --help

How it worksยถ

The wrapper monkey-patches Click at two levels before importing the target module:

  1. Decorator defaults: @click.command() and @click.group() produce colorized commands when no explicit cls= is given.

  2. Method patching: click.Command.get_help and click.Command.format_help are patched to inject the colorized formatter and keyword collection on all commands, including those with custom classes (like Flaskโ€™s FlaskGroup).

CLIs already built with Click Extra or Cloup are unaffected by the patching (they already have their own help formatting) but still run correctly through the wrapper.

Introspecting external CLIsยถ

The --show-params flag turns wrap into a read-only inspector: it loads any Click CLI without running it and prints a table of every parameter, with its ID, spec, class, type, hidden status, environment variables, and default value. This is the same table the --show-params option produces for a Click Extra CLI, pointed at a foreign target instead.

$ wrap --help
Usage: wrap [OPTIONS] SCRIPT [ARGS]...
Aliases: run

  Run, or introspect, any Click CLI through Click Extra.

  By default, runs SCRIPT with keyword highlighting and themed styling for its
  help screens. The target CLI is not modified.

  With --show-params, --man or --carapace, SCRIPT is loaded and described
  without being run. Extra arguments after SCRIPT navigate into nested
  subcommands; for --show-params, any trailing options are replayed against the
  resolved command so the parameter table reports their value and source.

  Resolution order for SCRIPT: installed console_scripts entry point, a local
  project directory (its entry point is read from pyproject.toml or setup.cfg),
  Python file path, module:function notation, or Python module name.

Options:
  --show-params           Show the parameters of the target CLI and exit,
                          without running it.
  --man                   Show the man page (roff) of the target CLI and exit,
                          without running it.
  --carapace              Show the Carapace completion spec (YAML) of the target
                          CLI and exit, without running it.
  --output-dir DIRECTORY  With --man, write one .1 file per (sub)command into
                          this directory instead of printing a single page to
                          stdout. Created if missing.
  --install               With --carapace, write the spec into Carapace's user
                          spec directory instead of printing it, and echo the
                          written path.
  --table-format [aligned|asciidoc|colon-grid|csv|csv-excel|csv-excel-tab|csv-unix|double-grid|double-outline|fancy-grid|fancy-outline|github|grid|heavy-grid|heavy-outline|hjson|html|jira|json|json5|jsonc|latex|latex-booktabs|latex-longtable|latex-raw|mediawiki|mixed-grid|mixed-outline|moinmoin|orgtbl|outline|pipe|plain|presto|pretty|psql|rounded-grid|rounded-outline|rst|simple|simple-grid|simple-outline|textile|toml|tsv|unsafehtml|vertical|xml|yaml|youtrack]
                          With --show-params, the rendering style of the
                          parameter table. Falls back to the click-extra group's
                          --table-format when not set here.
  --columns [id,spec,class,param_type,python_type,hidden,exposed,allowed_in_conf,envvars,default,is_flag,flag_value,is_bool_flag,multiple,nargs,prompt,confirmation_prompt,value,source]
                          Restrict and reorder table columns, SQL SELECT-style.
                          Comma-separated list of column IDs. Default: all
                          columns in canonical order.
  -h, --help              Show this message and exit.

Here is Flaskโ€™s run subcommand rendered with the vertical table format:

$ wrap --show-params --table-format vertical -- flask run
***************************[ 1. row ]***************************
ID                  | run.cert
Spec.               | --cert PATH
Class               | click.core.Option
Param type          | flask.cli.CertParamType
Python type         | str
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_CERT
Default             | None
Is flag             | โœ˜
Flag value          | 
Is bool flag        | โœ˜
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 2. row ]***************************
ID                  | run.debug
Spec.               | --debug / --no-debug
Class               | click.core.Option
Param type          | click.types.BoolParamType
Python type         | bool
Hidden              | โœ˜
Exposed             | โœ˜
Env. vars.          | FLASK_RUN_DEBUG
Default             | False
Is flag             | โœ“
Flag value          | True
Is bool flag        | โœ“
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 3. row ]***************************
ID                  | run.debugger
Spec.               | --debugger / --no-debugger
Class               | click.core.Option
Param type          | click.types.BoolParamType
Python type         | bool
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_DEBUGGER
Default             | None
Is flag             | โœ“
Flag value          | True
Is bool flag        | โœ“
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 4. row ]***************************
ID                  | run.exclude_patterns
Spec.               | --exclude-patterns PATH
Class               | click.core.Option
Param type          | flask.cli.SeparatedPathType
Python type         | str
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_EXCLUDE_PATTERNS
Default             | None
Is flag             | โœ˜
Flag value          | 
Is bool flag        | โœ˜
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 5. row ]***************************
ID                  | run.extra_files
Spec.               | --extra-files PATH
Class               | click.core.Option
Param type          | flask.cli.SeparatedPathType
Python type         | str
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_EXTRA_FILES
Default             | None
Is flag             | โœ˜
Flag value          | 
Is bool flag        | โœ˜
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 6. row ]***************************
ID                  | run.help
Spec.               | --help
Class               | click.core.Option
Param type          | click.types.BoolParamType
Python type         | bool
Hidden              | โœ˜
Exposed             | โœ˜
Env. vars.          | FLASK_RUN_HELP
Default             | False
Is flag             | โœ“
Flag value          | True
Is bool flag        | โœ“
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 7. row ]***************************
ID                  | run.host
Spec.               | -h, --host TEXT
Class               | click.core.Option
Param type          | click.types.StringParamType
Python type         | str
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_HOST
Default             | '127.0.0.1'
Is flag             | โœ˜
Flag value          | 
Is bool flag        | โœ˜
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 8. row ]***************************
ID                  | run.key
Spec.               | --key FILE
Class               | click.core.Option
Param type          | click.types.Path
Python type         | str
Hidden              | โœ˜
Exposed             | โœ˜
Env. vars.          | FLASK_RUN_KEY
Default             | None
Is flag             | โœ˜
Flag value          | 
Is bool flag        | โœ˜
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 9. row ]***************************
ID                  | run.port
Spec.               | -p, --port INTEGER
Class               | click.core.Option
Param type          | click.types.IntParamType
Python type         | int
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_PORT
Default             | 5000
Is flag             | โœ˜
Flag value          | 
Is bool flag        | โœ˜
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 10. row ]***************************
ID                  | run.reload
Spec.               | --reload / --no-reload
Class               | click.core.Option
Param type          | click.types.BoolParamType
Python type         | bool
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_RELOAD
Default             | None
Is flag             | โœ“
Flag value          | True
Is bool flag        | โœ“
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 
***************************[ 11. row ]***************************
ID                  | run.with_threads
Spec.               | --with-threads / --without-threads
Class               | click.core.Option
Param type          | click.types.BoolParamType
Python type         | bool
Hidden              | โœ˜
Exposed             | โœ“
Env. vars.          | FLASK_RUN_WITH_THREADS
Default             | True
Is flag             | โœ“
Flag value          | True
Is bool flag        | โœ“
Multiple            | โœ˜
Nargs               | 1
Prompt              | 
Confirmation prompt | โœ˜
Value               | None
Source              | 

Because wrap resolves the targetโ€™s own context, the auto-generated environment variables resolve too (Flask sets the FLASK_ prefix, so --port reads FLASK_RUN_PORT):

$ wrap --show-params --table-format vertical --columns id,envvars -- flask run
***************************[ 1. row ]***************************
ID         | run.cert
Env. vars. | FLASK_RUN_CERT
***************************[ 2. row ]***************************
ID         | run.debug
Env. vars. | FLASK_RUN_DEBUG
***************************[ 3. row ]***************************
ID         | run.debugger
Env. vars. | FLASK_RUN_DEBUGGER
***************************[ 4. row ]***************************
ID         | run.exclude_patterns
Env. vars. | FLASK_RUN_EXCLUDE_PATTERNS
***************************[ 5. row ]***************************
ID         | run.extra_files
Env. vars. | FLASK_RUN_EXTRA_FILES
***************************[ 6. row ]***************************
ID         | run.help
Env. vars. | FLASK_RUN_HELP
***************************[ 7. row ]***************************
ID         | run.host
Env. vars. | FLASK_RUN_HOST
***************************[ 8. row ]***************************
ID         | run.key
Env. vars. | FLASK_RUN_KEY
***************************[ 9. row ]***************************
ID         | run.port
Env. vars. | FLASK_RUN_PORT
***************************[ 10. row ]***************************
ID         | run.reload
Env. vars. | FLASK_RUN_RELOAD
***************************[ 11. row ]***************************
ID         | run.with_threads
Env. vars. | FLASK_RUN_WITH_THREADS

Restricting columnsยถ

Pass --columns a comma-separated list of column IDs to restrict and reorder the table, SQL SELECT-style:

$ wrap --show-params --columns id,spec,default -- flask run
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ ID                   โ”‚ Spec.                              โ”‚ Default     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ run.cert             โ”‚ --cert PATH                        โ”‚ None        โ”‚
โ”‚ run.debug            โ”‚ --debug / --no-debug               โ”‚ False       โ”‚
โ”‚ run.debugger         โ”‚ --debugger / --no-debugger         โ”‚ None        โ”‚
โ”‚ run.exclude_patterns โ”‚ --exclude-patterns PATH            โ”‚ None        โ”‚
โ”‚ run.extra_files      โ”‚ --extra-files PATH                 โ”‚ None        โ”‚
โ”‚ run.help             โ”‚ --help                             โ”‚ False       โ”‚
โ”‚ run.host             โ”‚ -h, --host TEXT                    โ”‚ '127.0.0.1' โ”‚
โ”‚ run.key              โ”‚ --key FILE                         โ”‚ None        โ”‚
โ”‚ run.port             โ”‚ -p, --port INTEGER                 โ”‚ 5000        โ”‚
โ”‚ run.reload           โ”‚ --reload / --no-reload             โ”‚ None        โ”‚
โ”‚ run.with_threads     โ”‚ --with-threads / --without-threads โ”‚ True        โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Reading values and their sourceยถ

Any options after SCRIPT (and its subcommand path) are replayed against the resolved command, so the value and source columns report what each parameter would resolve to under those arguments:

$ wrap --show-params --columns id,value,source -- flask run --port 8080
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ ID                   โ”‚ Value       โ”‚ Source      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ run.cert             โ”‚ None        โ”‚ DEFAULT     โ”‚
โ”‚ run.debug            โ”‚ False       โ”‚ DEFAULT     โ”‚
โ”‚ run.debugger         โ”‚ None        โ”‚ DEFAULT     โ”‚
โ”‚ run.exclude_patterns โ”‚ None        โ”‚ DEFAULT     โ”‚
โ”‚ run.extra_files      โ”‚ None        โ”‚ DEFAULT     โ”‚
โ”‚ run.help             โ”‚ False       โ”‚ DEFAULT     โ”‚
โ”‚ run.host             โ”‚ '127.0.0.1' โ”‚ DEFAULT     โ”‚
โ”‚ run.key              โ”‚ None        โ”‚ DEFAULT     โ”‚
โ”‚ run.port             โ”‚ '8080'      โ”‚ COMMANDLINE โ”‚
โ”‚ run.reload           โ”‚ None        โ”‚ DEFAULT     โ”‚
โ”‚ run.with_threads     โ”‚ True        โ”‚ DEFAULT     โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Machine-readable outputยถ

All --table-format renderings are supported. JSON is handy for programmatic consumption:

$ wrap --show-params --table-format json -- flask run
[
  {
    "ID": "run.cert",
    "Spec.": "--cert PATH",
    "Class": "click.core.Option",
    "Param type": "flask.cli.CertParamType",
    "Python type": "str",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_CERT"
    ],
    "Default": null,
    "Is flag": false,
    "Flag value": null,
    "Is bool flag": false,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.debug",
    "Spec.": "--debug / --no-debug",
    "Class": "click.core.Option",
    "Param type": "click.types.BoolParamType",
    "Python type": "bool",
    "Hidden": false,
    "Exposed": false,
    "Env. vars.": [
      "FLASK_RUN_DEBUG"
    ],
    "Default": false,
    "Is flag": true,
    "Flag value": true,
    "Is bool flag": true,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.debugger",
    "Spec.": "--debugger / --no-debugger",
    "Class": "click.core.Option",
    "Param type": "click.types.BoolParamType",
    "Python type": "bool",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_DEBUGGER"
    ],
    "Default": null,
    "Is flag": true,
    "Flag value": true,
    "Is bool flag": true,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.exclude_patterns",
    "Spec.": "--exclude-patterns PATH",
    "Class": "click.core.Option",
    "Param type": "flask.cli.SeparatedPathType",
    "Python type": "str",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_EXCLUDE_PATTERNS"
    ],
    "Default": null,
    "Is flag": false,
    "Flag value": null,
    "Is bool flag": false,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.extra_files",
    "Spec.": "--extra-files PATH",
    "Class": "click.core.Option",
    "Param type": "flask.cli.SeparatedPathType",
    "Python type": "str",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_EXTRA_FILES"
    ],
    "Default": null,
    "Is flag": false,
    "Flag value": null,
    "Is bool flag": false,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.help",
    "Spec.": "--help",
    "Class": "click.core.Option",
    "Param type": "click.types.BoolParamType",
    "Python type": "bool",
    "Hidden": false,
    "Exposed": false,
    "Env. vars.": [
      "FLASK_RUN_HELP"
    ],
    "Default": false,
    "Is flag": true,
    "Flag value": true,
    "Is bool flag": true,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.host",
    "Spec.": "-h, --host TEXT",
    "Class": "click.core.Option",
    "Param type": "click.types.StringParamType",
    "Python type": "str",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_HOST"
    ],
    "Default": "127.0.0.1",
    "Is flag": false,
    "Flag value": null,
    "Is bool flag": false,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.key",
    "Spec.": "--key FILE",
    "Class": "click.core.Option",
    "Param type": "click.types.Path",
    "Python type": "str",
    "Hidden": false,
    "Exposed": false,
    "Env. vars.": [
      "FLASK_RUN_KEY"
    ],
    "Default": null,
    "Is flag": false,
    "Flag value": null,
    "Is bool flag": false,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.port",
    "Spec.": "-p, --port INTEGER",
    "Class": "click.core.Option",
    "Param type": "click.types.IntParamType",
    "Python type": "int",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_PORT"
    ],
    "Default": 5000,
    "Is flag": false,
    "Flag value": null,
    "Is bool flag": false,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.reload",
    "Spec.": "--reload / --no-reload",
    "Class": "click.core.Option",
    "Param type": "click.types.BoolParamType",
    "Python type": "bool",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_RELOAD"
    ],
    "Default": null,
    "Is flag": true,
    "Flag value": true,
    "Is bool flag": true,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  },
  {
    "ID": "run.with_threads",
    "Spec.": "--with-threads / --without-threads",
    "Class": "click.core.Option",
    "Param type": "click.types.BoolParamType",
    "Python type": "bool",
    "Hidden": false,
    "Exposed": true,
    "Env. vars.": [
      "FLASK_RUN_WITH_THREADS"
    ],
    "Default": true,
    "Is flag": true,
    "Flag value": true,
    "Is bool flag": true,
    "Multiple": false,
    "Nargs": 1,
    "Prompt": null,
    "Confirmation prompt": false,
    "Value": null,
    "Source": null
  }
]

Subcommand drillingยถ

Extra arguments after SCRIPT navigate into nested command groups; the table then scopes to the resolved node:

$ click-extra wrap --show-params -- flask run
$ click-extra wrap --show-params -- flask routes

Target resolutionยถ

Target resolution follows the same order as the default mode: a console_scripts entry point, a local project directory, a .py file path, module:function notation, or a bare Python module name.

When the resolved entry point is a wrapper function (not a Click command), the module is scanned for Click command instances. If a single command group is found, it is used automatically. If multiple candidates exist, the error message lists them so you can use explicit module:name notation:

$ click-extra wrap --show-params -- flask.cli:cli

Some CLIs import their Click command lazily: a __main__:main wrapper that runs from my_package.cli import cli only when called, for instance. The module scan then finds nothing at the top level and wrap reports No Click command found in my_package.__main__. Introspection cannot recover the command from such an entry point, nor from the project directory that resolves to it, because running the wrapper is the only thing that would import the command. Point it instead at the module that defines the command with module:function notation, making the package importable if it is not installed:

$ PYTHONPATH=../my-project click-extra wrap --man -- my_package.cli:cli

click_extra.cli_wrapper APIยถ

        classDiagram
  Command <|-- _WrapCommand
  Group <|-- WrapperGroup
  _HelpColorsMixin <|-- _WrapCommand
    

The click-extra wrap command and the machinery to wrap a foreign Click CLI.

Monkey-patches Clickโ€™s decorator functions before importing (or running) a target module so its @click.command() / @click.group() produce colorized, keyword-highlighted, themed variants. Also resolves and invokes the target, and introspects it for --show-params and --man without firing its callbacks.

Not to be confused with text wrapping: that is click.wrap_text(), exposed at the package root as click_extra.wrap_text.

class click_extra.cli_wrapper.WrapperGroup(*args, help_command=True, **kwargs)[source]

Bases: Group

Group that falls back to the wrap subcommand for unknown names.

Known subcommands and their aliases are dispatched normally. Anything else is treated as a target script and forwarded to wrap.

Like Command.__init__, but auto-injects a help subcommand.

Parameters:

help_command (bool) โ€“ when True (the default), a help subcommand is automatically registered. Set to False to suppress it, or register your own help subcommand to override it.

resolve_command(ctx, args)[source]
Return type:

tuple[str | None, Command | None, list[str]]

click_extra.cli_wrapper.patch_click(theme=None, color=True)[source]

Replace Clickโ€™s decorator functions with colorized variants.

Must be called before importing the target CLI module so that @click.command() and @click.group() decorators produce colorized commands.

Note

Only the decorator functions are replaced, not the class names (click.Command, click.Group). Replacing class names would break isinstance and issubclass checks in Click internals (_param_memo) and Cloupโ€™s decorator validators.

Parameters:
  • theme (HelpTheme | None) โ€“ Color theme to use. None keeps the current default.

  • color (bool | None) โ€“ Tri-state ANSI control mirroring ctx.color: True forces colors on, False strips them, and None (the GNU auto default) defers to the output streamโ€™s TTY status.

Return type:

None

click_extra.cli_wrapper.unpatch_click()[source]

Restore Clickโ€™s original decorator functions and methods.

Reverses the changes made by patch_click(). Useful in tests to avoid leaking global state between test cases.

Return type:

None

click_extra.cli_wrapper.resolve_target(script)[source]

Resolve a script name to a module path and function name.

Resolution order:

  1. console_scripts entry points from installed packages.

  2. A local project directory: its console_scripts entry point is read from pyproject.toml / setup.cfg and its package is added to sys.path.

  3. .py file path.

  4. Explicit module:function notation.

  5. Bare Python module or package name.

Return type:

tuple[str, str]

Returns:

(module_path, function_name) tuple. function_name is empty when the target should be invoked as a module or script file.

Raises:

click.ClickException โ€“ If the script cannot be resolved.

Note

Resolving a local project directory has a side effect: the directory holding its top-level package is prepended to sys.path so the subsequent import succeeds. The targetโ€™s own dependencies must still be importable in the current environment.

click_extra.cli_wrapper.invoke_target(script, module_path, function_name, args)[source]

Import and call the target CLI.

Reconstructs sys.argv so Clickโ€™s argument parsing sees the targetโ€™s program name and arguments.

Parameters:
  • script (str) โ€“ Original script name (used as sys.argv[0]).

  • module_path (str) โ€“ Dotted module path or .py file path.

  • function_name (str) โ€“ Function to call, or empty for module execution.

  • args (tuple[str, ...]) โ€“ Arguments to pass to the target CLI.

Return type:

None

click_extra.cli_wrapper.resolve_target_command(script, subcommands=())[source]

Import SCRIPT and return its Click command object and a matching context.

Resolves SCRIPT through resolve_target(), imports the module, then obtains the command object without running the CLI: the entry-point attribute when it is itself a command, otherwise by scanning the moduleโ€™s namespace for Click command instances (preferring groups). Optional subcommands navigate into nested groups, mirroring the path a user would type.

Shared by the wrap commandโ€™s --show-params and --man modes so both introspect the exact same resolved command.

Raises:

click.ClickException โ€“ when no unambiguous Click command can be found, or a requested subcommand does not exist.

Return type:

tuple[Command, Context]