Themes

Click Extra exposes a small theming system that controls every color used in help screens: options, choices, metavars, arguments, CLI names, defaults, environment variables, log levels, and more. Two themes ship by default (dark and light), and downstream projects can register their own.

The --theme option

Every command and group built with @click_extra.command / @click_extra.group automatically gets a --theme flag, alongside the other default options.

from click_extra import command, echo

@command
def weather():
    """Show the local weather forecast."""
    echo("Sunny, 22°C.")
$ weather --theme light --help
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.

The flag is eager, so it is processed before any other option and before help is rendered. The picked theme is stored on the active Click context’s meta dict under click_extra.context.THEME and inherits down to subcommands, so a parent group’s --theme applies to every child. See the available keys table for the full inventory you can read from your own callbacks.

Configuration file

Like every other default option, --theme reads its value from pyproject.toml:

[tool.weather]
theme = "light"

Now invocations of the weather CLI pick up the light theme without passing --theme on the command line.

Built-in themes

Name

Color model

Notes

dark

16 named ANSI colors

Process-wide default. Follows the user’s terminal palette.

light

16 named ANSI colors

Tuned for white backgrounds: no bright variants, blue replaces cyan.

solarized_dark

24-bit RGB

Warm-toned dark theme with selective accent contrast.

dracula

24-bit RGB

High-contrast dark theme with vivid neon accents.

nord

24-bit RGB

Cool-toned dark theme built around frost-blue and aurora accents.

monokai

24-bit RGB

Classic dark theme with high-saturation magenta and lime accents.

Each row is keyed by the --theme choice value; access the instance via BUILTIN_THEMES["<name>"] (e.g. BUILTIN_THEMES["dark"]). Click any name to jump to that theme’s palette listing below.

Click each tab below for a live render of the theme applied to the same weather CLI’s --help output. Colors are produced at Sphinx build time, not screenshots.

$ weather --theme dark --help
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.
$ weather --theme light --help
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.
$ weather --theme solarized_dark --help
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.
$ weather --theme dracula --help
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.
$ weather --theme nord --help
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.
$ weather --theme monokai --help
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.

Two flavors ship in click_extra/themes.toml:

  • ANSI themes (dark, light) use the 16 named ANSI colors via cloup.styling.Color, so the rendered colors track whatever palette the user’s terminal is configured with. Pick these when you want to blend in with the user’s terminal theme.

  • Branded themes (solarized_dark, dracula, nord, monokai) emit 24-bit RGB triplets from each theme’s canonical palette. Pick these when the theme name implies specific colors (solarized_dark should look like Solarized, not “whatever the terminal calls cyan”). Terminals without 24-bit support fall back to the nearest 256-color cell automatically. Each theme’s slot mapping is hand-curated: there’s no automated translation from generic colour-scheme formats, because none of them expose the same semantic roles we care about (option, metavar, choice, deprecated, envvar, …).

click_extra.theme.BUILTIN_THEMES is a dict[str, HelpExtraTheme] mapping the names above to their instances; it is built by parsing click_extra/themes.toml at import time and is seeded into theme_registry immediately afterwards. Read the TOML file directly for the exact palette mapping, or call theme.to_dict() at runtime to get a TOML/JSON-friendly dict.

Palettes

Every styled slot of each built-in theme, with the swatch and attribute decorations rendered live from the shipped themes.toml at Sphinx build time. The block below iterates BUILTIN_THEMES and calls palette_html() for each: downstream projects with their own custom themes can drop the same loop into their own docs to get matching swatch listings.

dark

invoked_command
bright_white
Usage: my-cli [OPTIONS] COMMAND [ARGS]...
heading
bright_blue bold underline
Options:
constraint
magenta
(mutually exclusive)
alias
cyan
  show, ls     Show the current state.
alias_secondary
cyan dim
  show (ls)     Show the current state.
critical
red bold
CRITICAL: Database connection lost.
error
red
ERROR: Configuration file not found.
warning
yellow
WARNING: Requested 16 jobs exceeds available CPU cores (8).
debug
blue
DEBUG: Resolved /etc/myapp/config.toml.
option
cyan
--config CONFIG_PATH    Location of the configuration file.
-v, --verbose           Increase verbosity.
subcommand
cyan
Commands:
  backup        Snapshot the data store.
  restore       Restore from a snapshot.
choice
magenta
--format [json|csv|xml]   Output format. Defaults to json.
metavar
cyan dim
--output TEXT       Destination file.
--workers INTEGER   Worker count.
bracket
dim
--port INTEGER    [env var: PORT; default: 8080; required]
envvar
yellow dim
--threshold INTEGER   Acceptable error rate.
                      [env var: THRESHOLD, TEST_THRESHOLD]
default
green dim italic
--output FILENAME    Destination file.  [default: out.csv]
--retries INTEGER    Retry budget.  [default: 5]
range_label
cyan dim
--level INTEGER RANGE    Verbosity level.  [0<=x<=9]
--port INTEGER RANGE     Bind port.        [x>=1024]
required
red dim
--token TEXT    Authentication token.  [required]
argument
cyan
Usage: cp [OPTIONS] SRC DST
Usage: pack [OPTIONS] [FILES]... [OUTPUT]
deprecated
bright_yellow bold
--old-api    Legacy endpoint. (DEPRECATED: use --new-api instead)
--legacy     Kept for compatibility. (deprecated: removed in v9)
search
green bold
--retry-budget INTEGER    The retry budget.
success
green
 database migration completed
 1,245 records imported
subheading
blue
◼ 3 mails sharing hash a1b2c3d4
◼ 7 mails sharing hash e5f6a7b8

dracula

invoked_command
#f8f8f2 bold
Usage: my-cli [OPTIONS] COMMAND [ARGS]...
heading
#ff79c6 bold underline
Options:
constraint
#ff79c6
(mutually exclusive)
alias
#8be9fd
  show, ls     Show the current state.
alias_secondary
#8be9fd dim
  show (ls)     Show the current state.
critical
#ff5555 bold
CRITICAL: Database connection lost.
error
#ff5555
ERROR: Configuration file not found.
warning
#ffb86c
WARNING: Requested 16 jobs exceeds available CPU cores (8).
debug
#6272a4
DEBUG: Resolved /etc/myapp/config.toml.
option
#bd93f9
--config CONFIG_PATH    Location of the configuration file.
-v, --verbose           Increase verbosity.
subcommand
#bd93f9
Commands:
  backup        Snapshot the data store.
  restore       Restore from a snapshot.
choice
#ff79c6
--format [json|csv|xml]   Output format. Defaults to json.
metavar
#bd93f9 dim
--output TEXT       Destination file.
--workers INTEGER   Worker count.
bracket
#6272a4
--port INTEGER    [env var: PORT; default: 8080; required]
envvar
#ffb86c dim
--threshold INTEGER   Acceptable error rate.
                      [env var: THRESHOLD, TEST_THRESHOLD]
default
#50fa7b dim italic
--output FILENAME    Destination file.  [default: out.csv]
--retries INTEGER    Retry budget.  [default: 5]
range_label
#bd93f9 dim
--level INTEGER RANGE    Verbosity level.  [0<=x<=9]
--port INTEGER RANGE     Bind port.        [x>=1024]
required
#ff5555 dim
--token TEXT    Authentication token.  [required]
argument
#bd93f9
Usage: cp [OPTIONS] SRC DST
Usage: pack [OPTIONS] [FILES]... [OUTPUT]
deprecated
#ffb86c bold
--old-api    Legacy endpoint. (DEPRECATED: use --new-api instead)
--legacy     Kept for compatibility. (deprecated: removed in v9)
search
#f1fa8c bold
--retry-budget INTEGER    The retry budget.
success
#50fa7b
 database migration completed
 1,245 records imported
subheading
#8be9fd
◼ 3 mails sharing hash a1b2c3d4
◼ 7 mails sharing hash e5f6a7b8

light

invoked_command
black bold
Usage: my-cli [OPTIONS] COMMAND [ARGS]...
heading
blue bold underline
Options:
constraint
magenta
(mutually exclusive)
alias
blue
  show, ls     Show the current state.
alias_secondary
blue dim
  show (ls)     Show the current state.
critical
red bold
CRITICAL: Database connection lost.
error
red
ERROR: Configuration file not found.
warning
magenta
WARNING: Requested 16 jobs exceeds available CPU cores (8).
debug
blue dim
DEBUG: Resolved /etc/myapp/config.toml.
option
blue
--config CONFIG_PATH    Location of the configuration file.
-v, --verbose           Increase verbosity.
subcommand
blue
Commands:
  backup        Snapshot the data store.
  restore       Restore from a snapshot.
choice
magenta
--format [json|csv|xml]   Output format. Defaults to json.
metavar
blue dim
--output TEXT       Destination file.
--workers INTEGER   Worker count.
bracket
dim
--port INTEGER    [env var: PORT; default: 8080; required]
envvar
magenta dim
--threshold INTEGER   Acceptable error rate.
                      [env var: THRESHOLD, TEST_THRESHOLD]
default
green dim italic
--output FILENAME    Destination file.  [default: out.csv]
--retries INTEGER    Retry budget.  [default: 5]
range_label
blue dim
--level INTEGER RANGE    Verbosity level.  [0<=x<=9]
--port INTEGER RANGE     Bind port.        [x>=1024]
required
red dim
--token TEXT    Authentication token.  [required]
argument
blue
Usage: cp [OPTIONS] SRC DST
Usage: pack [OPTIONS] [FILES]... [OUTPUT]
deprecated
red bold
--old-api    Legacy endpoint. (DEPRECATED: use --new-api instead)
--legacy     Kept for compatibility. (deprecated: removed in v9)
search
green bold
--retry-budget INTEGER    The retry budget.
success
green
 database migration completed
 1,245 records imported
subheading
blue dim
◼ 3 mails sharing hash a1b2c3d4
◼ 7 mails sharing hash e5f6a7b8

monokai

invoked_command
#f8f8f2 bold
Usage: my-cli [OPTIONS] COMMAND [ARGS]...
heading
#a6e22e bold underline
Options:
constraint
#ae81ff
(mutually exclusive)
alias
#a6e22e
  show, ls     Show the current state.
alias_secondary
#a6e22e dim
  show (ls)     Show the current state.
critical
#f92672 bold
CRITICAL: Database connection lost.
error
#f92672
ERROR: Configuration file not found.
warning
#fd971f
WARNING: Requested 16 jobs exceeds available CPU cores (8).
debug
#75715e
DEBUG: Resolved /etc/myapp/config.toml.
option
#66d9ef
--config CONFIG_PATH    Location of the configuration file.
-v, --verbose           Increase verbosity.
subcommand
#66d9ef
Commands:
  backup        Snapshot the data store.
  restore       Restore from a snapshot.
choice
#ae81ff
--format [json|csv|xml]   Output format. Defaults to json.
metavar
#66d9ef dim
--output TEXT       Destination file.
--workers INTEGER   Worker count.
bracket
#75715e
--port INTEGER    [env var: PORT; default: 8080; required]
envvar
#fd971f dim
--threshold INTEGER   Acceptable error rate.
                      [env var: THRESHOLD, TEST_THRESHOLD]
default
#e6db74 dim italic
--output FILENAME    Destination file.  [default: out.csv]
--retries INTEGER    Retry budget.  [default: 5]
range_label
#66d9ef dim
--level INTEGER RANGE    Verbosity level.  [0<=x<=9]
--port INTEGER RANGE     Bind port.        [x>=1024]
required
#f92672 dim
--token TEXT    Authentication token.  [required]
argument
#66d9ef
Usage: cp [OPTIONS] SRC DST
Usage: pack [OPTIONS] [FILES]... [OUTPUT]
deprecated
#fd971f bold
--old-api    Legacy endpoint. (DEPRECATED: use --new-api instead)
--legacy     Kept for compatibility. (deprecated: removed in v9)
search
#e6db74 bold
--retry-budget INTEGER    The retry budget.
success
#a6e22e
 database migration completed
 1,245 records imported
subheading
#a6e22e
◼ 3 mails sharing hash a1b2c3d4
◼ 7 mails sharing hash e5f6a7b8

nord

invoked_command
#eceff4 bold
Usage: my-cli [OPTIONS] COMMAND [ARGS]...
heading
#5e81ac bold underline
Options:
constraint
#b48ead
(mutually exclusive)
alias
#8fbcbb
  show, ls     Show the current state.
alias_secondary
#8fbcbb dim
  show (ls)     Show the current state.
critical
#bf616a bold
CRITICAL: Database connection lost.
error
#bf616a
ERROR: Configuration file not found.
warning
#d08770
WARNING: Requested 16 jobs exceeds available CPU cores (8).
debug
#4c566a
DEBUG: Resolved /etc/myapp/config.toml.
option
#81a1c1
--config CONFIG_PATH    Location of the configuration file.
-v, --verbose           Increase verbosity.
subcommand
#81a1c1
Commands:
  backup        Snapshot the data store.
  restore       Restore from a snapshot.
choice
#b48ead
--format [json|csv|xml]   Output format. Defaults to json.
metavar
#81a1c1 dim
--output TEXT       Destination file.
--workers INTEGER   Worker count.
bracket
#4c566a
--port INTEGER    [env var: PORT; default: 8080; required]
envvar
#d08770 dim
--threshold INTEGER   Acceptable error rate.
                      [env var: THRESHOLD, TEST_THRESHOLD]
default
#a3be8c dim italic
--output FILENAME    Destination file.  [default: out.csv]
--retries INTEGER    Retry budget.  [default: 5]
range_label
#81a1c1 dim
--level INTEGER RANGE    Verbosity level.  [0<=x<=9]
--port INTEGER RANGE     Bind port.        [x>=1024]
required
#bf616a dim
--token TEXT    Authentication token.  [required]
argument
#81a1c1
Usage: cp [OPTIONS] SRC DST
Usage: pack [OPTIONS] [FILES]... [OUTPUT]
deprecated
#d08770 bold
--old-api    Legacy endpoint. (DEPRECATED: use --new-api instead)
--legacy     Kept for compatibility. (deprecated: removed in v9)
search
#ebcb8b bold
--retry-budget INTEGER    The retry budget.
success
#a3be8c
 database migration completed
 1,245 records imported
subheading
#88c0d0
◼ 3 mails sharing hash a1b2c3d4
◼ 7 mails sharing hash e5f6a7b8

solarized_dark

invoked_command
#eee8d5 bold
Usage: my-cli [OPTIONS] COMMAND [ARGS]...
heading
#268bd2 bold underline
Options:
constraint
#6c71c4
(mutually exclusive)
alias
#2aa198
  show, ls     Show the current state.
alias_secondary
#2aa198 dim
  show (ls)     Show the current state.
critical
#dc322f bold
CRITICAL: Database connection lost.
error
#dc322f
ERROR: Configuration file not found.
warning
#b58900
WARNING: Requested 16 jobs exceeds available CPU cores (8).
debug
#586e75
DEBUG: Resolved /etc/myapp/config.toml.
option
#268bd2
--config CONFIG_PATH    Location of the configuration file.
-v, --verbose           Increase verbosity.
subcommand
#268bd2
Commands:
  backup        Snapshot the data store.
  restore       Restore from a snapshot.
choice
#6c71c4
--format [json|csv|xml]   Output format. Defaults to json.
metavar
#268bd2 dim
--output TEXT       Destination file.
--workers INTEGER   Worker count.
bracket
#586e75
--port INTEGER    [env var: PORT; default: 8080; required]
envvar
#cb4b16 dim
--threshold INTEGER   Acceptable error rate.
                      [env var: THRESHOLD, TEST_THRESHOLD]
default
#859900 dim italic
--output FILENAME    Destination file.  [default: out.csv]
--retries INTEGER    Retry budget.  [default: 5]
range_label
#268bd2 dim
--level INTEGER RANGE    Verbosity level.  [0<=x<=9]
--port INTEGER RANGE     Bind port.        [x>=1024]
required
#dc322f dim
--token TEXT    Authentication token.  [required]
argument
#268bd2
Usage: cp [OPTIONS] SRC DST
Usage: pack [OPTIONS] [FILES]... [OUTPUT]
deprecated
#d33682 bold
--old-api    Legacy endpoint. (DEPRECATED: use --new-api instead)
--legacy     Kept for compatibility. (deprecated: removed in v9)
search
#b58900 bold
--retry-budget INTEGER    The retry budget.
success
#859900
 database migration completed
 1,245 records imported
subheading
#2aa198
◼ 3 mails sharing hash a1b2c3d4
◼ 7 mails sharing hash e5f6a7b8

Module exports

click_extra.theme exposes two themes and a pair of accessor helpers:

  • nocolor_theme: an all-identity theme used when ANSI rendering is suppressed.

  • get_default_theme() / set_default_theme(theme): read or override the process-wide fallback. The default is the built-in dark palette. ThemeOption does not call set_default_theme: per-invocation choices live on ctx.meta instead. click_extra.wrap.patch_click() calls set_default_theme() to override the fallback for the entire patched session.

Use click_extra.theme.get_current_theme() to read the theme that applies to the current invocation: it consults the active Click context first and falls back to get_default_theme().

Adding a new built-in theme

A built-in theme is a single TOML table in click_extra/themes.toml: declare a [<name>] table with one inline-table per styled slot. The file is parsed at import time via HelpExtraTheme.from_dict, so adding a theme requires no Python — only the data:

# click_extra/themes.toml

[zenburn]
# Zenburn by Jani Nurminen.
# Palette: https://kippura.org/zenburnpage/
invoked_command = { fg = "#dcdccc", bold = true }
heading = { fg = "#8cd0d3", bold = true, underline = true }
option = { fg = "#8cd0d3" }
# ... fill in the rest of the slots

Tables are kept in alphabetical order; tests/test_themes.py enforces this. The slot mapping is the work: generic colour-scheme catalogs (base16, pygments, iTerm palettes) don’t expose the semantic roles Click Extra needs (option, metavar, choice, deprecated, envvar, …), so each theme is hand-curated. Use the existing solarized_dark, dracula, nord, and monokai tables as templates.

Registering a custom theme

The list of valid --theme choices is pulled from click_extra.theme.theme_registry (plus per-invocation overrides from --config) at parse time. To add your own theme from a downstream package, call register_theme() before declaring your commands:

from click_extra import (
    BUILTIN_THEMES,
    Color,
    Style,
    command,
    echo,
    register_theme,
)

NEON = BUILTIN_THEMES["dark"].with_(
    heading=Style(fg=Color.bright_magenta, bold=True, underline=True),
    option=Style(fg=Color.bright_cyan),
    choice=Style(fg=Color.bright_yellow),
)
register_theme("neon", NEON)


@command
def cocktail():
    """Mix a cocktail."""
    echo("Cheers!")

After this runs, cocktail --theme neon becomes a valid invocation, and cocktail --help lists neon alongside the built-in choices.

Tip

For themes that depend on runtime state (terminal-background detection, environment variables, user settings), compute the HelpExtraTheme once at startup and pass it to register_theme. The registry holds plain instances only — if you need lazy or per-invocation resolution, load the theme from [tool.<cli>.themes.<name>] (see Themes from your --config file below) so it lands on ctx.meta rather than the process-wide dict.

Anatomy of a theme

HelpExtraTheme is a frozen dataclass that extends cloup.HelpTheme with extra styling slots for log levels and Click Extra’s own categories.

Use with_() to derive a new theme that only overrides a few styles:

from click_extra import BUILTIN_THEMES, Style, Color

minimal = BUILTIN_THEMES["dark"].with_(
    option=Style(fg=Color.white),
    choice=Style(fg=Color.white, dim=True),
)

with_() returns the same instance when no styles change and validates that all keyword arguments match a known field, so typos like optoin=... raise immediately.

Cross-reference highlighting

The cross_ref_highlight flag (default True) controls whether option names, choices, arguments, metavars, and CLI names are highlighted wherever they appear in free-form prose. Disable it for a calmer help screen:

calm = BUILTIN_THEMES["dark"].with_(cross_ref_highlight=False)

See Cross-reference highlighting for the details on what stays styled when the flag is off.

Manual loading from a mapping

HelpExtraTheme.to_dict() and HelpExtraTheme.from_dict() round-trip a theme through plain mappings, so a theme can live in a TOML, JSON, or YAML file alongside the rest of an application’s configuration:

[my_theme]
option = { fg = "cyan" }
heading = { fg = "bright_blue", bold = true, underline = true }
choice = { fg = "magenta" }
import tomllib
from pathlib import Path

from click_extra import HelpExtraTheme, register_theme

raw = tomllib.loads(Path("config.toml").read_text())
register_theme("my_theme", HelpExtraTheme.from_dict(raw["my_theme"]))

to_dict() only emits slots that diverge from the default (identity / None), and from_dict() raises TypeError on unknown keys, so configuration typos surface at load time rather than silently producing a half-styled theme.

For the much more common case where the theme should live in the same --config file the CLI already reads, see the next section — click-extra wires the loader for you.

Themes from your --config file

ConfigOption recognizes a themes sub-table inside the app’s section. Every [<cli>.themes.<name>] entry is parsed via HelpExtraTheme.from_dict and made available to --theme for the duration of the invocation, with two distinct behaviors depending on whether <name> matches a built-in:

  • Override an existing palette. Re-declare a built-in name (dark, dracula, light, …) and the slots you set are overlaid on top of the built-in palette via HelpExtraTheme.cascade. Unset slots inherit from the built-in, so a one-line override like option = { fg = "bright_cyan" } is enough.

  • Define a new palette. Use any other name and --theme <name> becomes a valid choice for that invocation. Unset slots default to no styling (identity), so you typically declare a slot for every category you care about.

In both cases the theme registry mutation is per-invocation: it lives on ctx.meta under click_extra.context.THEME_OVERRIDES and never touches the module-level theme_registry. Sphinx builds, test runners, and any other host process running multiple CLI invocations back-to-back never leak themes between them.

Override an existing built-in

from click_extra import command, echo

@command
def weather():
    """Show the local weather forecast."""
    echo("Sunny, 22°C.")

Drop the override under [<cli>.themes.dark] in your weather.toml:

[weather.themes.dark]
option = { fg = "bright_cyan" }
choice = { fg = "yellow", bold = true }

Then ask for --help with the override applied (the rest of the dark palette stays put):

$ weather --config /tmp/tmpcfb0zq43/weather.toml --help
Load configuration matching /tmp/tmpcfb0zq43/weather.toml
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default: dark]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.

Define a brand-new theme

[weather.themes.midnight]
option = { fg = "blue", bold = true }
heading = { fg = "magenta" }
choice = { fg = "yellow" }
default = { fg = "green", italic = true }

The new name immediately shows up in --help’s --theme metavar and is selectable on the command line:

$ weather --config /tmp/tmps6vy4hgu/weather.toml --help
Load configuration matching /tmp/tmps6vy4hgu/weather.toml
Usage: weather [OPTIONS]

  Show the local weather forecast.

Options:
  --time / --no-time      Measure and print elapsed execution time.  [default:
                          no-time]
  --config CONFIG_PATH    Location of the configuration file. Supports local
                          path with glob patterns or remote URL.  [default: ~/.c
                          onfig/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.js
                          onc,*.hjson,*.ini,*.xml,pyproject.toml}]
  --no-config             Ignore all configuration files and only use command
                          line parameters and environment variables.
  --validate-config FILE  Validate the configuration file and exit.
  --color, --ansi / --no-color, --no-ansi
                          Strip out all colors and all ANSI codes from output.
                          [default: color]
  --theme [dark|dracula|light|midnight|monokai|nord|solarized_dark]
                          Color theme used for help screens.  [default:
                          midnight]
  --show-params           Show all CLI parameters, their provenance, defaults
                          and value, then exit.
  --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]
                          Rendering style of tables.  [default: rounded-outline]
  --verbosity LEVEL       Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                          [default: WARNING]
  -v, --verbose           Increase the default WARNING verbosity by one level
                          for each additional repetition of the option.
                          [default: 0]
  --version               Show the version and exit.
  -h, --help              Show this message and exit.

The same [weather] theme = "midnight" selector you’d use for a built-in works here: pre-pick the new theme as the default for invocations of this CLI.

Validation

Malformed entries surface as ValidationError with a path rooted at the configuration file root, both during --validate-config and at normal load time:

[weather.themes.midnight]
optoin = { fg = "blue" } # typo
$ weather --validate-config /tmp/tmp2q8gwarf/weather.toml
Configuration validation error: weather.themes.midnight: Unknown HelpExtraTheme field(s): optoin

The built-in ConfigValidator for the themes sub-tree is auto-registered on every ConfigOption, so app authors don’t have to opt in. Apps that ship their own ConfigValidator continue to work alongside it.

Interaction with --color / --no-color

--theme controls which colors are used. --color / --no-color controls whether colors are emitted at all. The two are independent:

  • --theme light with --no-color emits no ANSI codes.

  • --theme dark with --color (the default) emits the dark theme’s ANSI codes.

  • NO_COLOR=1 in the environment overrides any --theme choice by silencing all ANSI output.

The --color callback inspects the standard set of color environment variables (NO_COLOR, CLICOLOR, FORCE_COLOR, LLM, etc.) before the theme is applied: see color_envvars for the full list.

click_extra.theme API

        classDiagram
  ExtraOption <|-- ThemeOption
  HelpTheme <|-- HelpExtraTheme
  ParamType <|-- ThemeChoice
    

Help-screen color themes for Click Extra.

Holds the HelpExtraTheme dataclass (pure data, no factory methods), the nocolor_theme constant, the process-wide fallback accessed via get_default_theme() / set_default_theme(), the named-theme theme_registry plus register_theme() helper, and the ThemeOption that exposes --theme on every Click Extra command.

The built-in themes (dark, dracula, light, monokai, nord, solarized_dark) live in the package data file click_extra/themes.toml and are loaded at module import time via HelpExtraTheme.from_dict(). Adding a new built-in theme is a one-file edit in that TOML file — no Python needed. The same TOML schema is used for user-defined themes loaded from configuration: see Themes for the user guide.

Note

The active theme for a CLI invocation is stored on the Click context’s meta dict under click_extra.context.THEME by ThemeOption. Use get_current_theme() to retrieve it: that helper consults the active Click context first and falls back to get_default_theme() when no context is in flight (e.g. at import time, in wrap patching, or in bare REPL usage). Per-invocation context storage means concurrent invocations of the same CLI in one process (Sphinx builds, test runners, REPLs) do not leak --theme choices into each other.

class click_extra.theme.HelpExtraTheme(invoked_command=<function identity>, command_help=<function identity>, heading=<function identity>, constraint=<function identity>, section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=<function identity>, alias_secondary=None, epilog=<function identity>, critical=<function identity>, error=<function identity>, warning=<function identity>, info=<function identity>, debug=<function identity>, option=<function identity>, subcommand=<function identity>, choice=<function identity>, metavar=<function identity>, bracket=<function identity>, envvar=<function identity>, default=<function identity>, range_label=<function identity>, required=<function identity>, argument=<function identity>, deprecated=<function identity>, search=<function identity>, success=<function identity>, cross_ref_highlight=True, subheading=<function identity>)[source]

Bases: HelpTheme

Extends cloup.HelpTheme with slots for log levels and the structural elements Click Extra highlights in help screens.

Each slot below documents what it colors. The built-in themes shipped in BUILTIN_THEMES provide the visual styling by setting the relevant slots; user-defined themes can be authored as plain mappings and loaded via from_dict().

critical()

Style applied to the CRITICAL level name in log records.

Example: CRITICAL: Database connection lost.

Return type:

TypeVar(T)

Rendered with the default dark theme:

CRITICAL: Database connection lost.
error()

Style applied to the ERROR level name in log records.

Example: ERROR: Configuration file not found.

Return type:

TypeVar(T)

Rendered with the default dark theme:

ERROR: Configuration file not found.
warning()

Style applied to the WARNING level name in log records.

Example: WARNING: Requested 16 jobs exceeds available CPU cores (8).

Return type:

TypeVar(T)

Rendered with the default dark theme:

WARNING: Requested 16 jobs exceeds available CPU cores (8).
info()

Style applied to the INFO level name in log records.

Usually left at identity: INFO is the default verbosity and shouldn’t stand out from regular output.

Return type:

TypeVar(T)

Rendered with the default dark theme:

INFO: Loaded 23 records.
debug()

Style applied to the DEBUG level name in log records.

Example: DEBUG: Resolved /etc/myapp/config.toml.

Return type:

TypeVar(T)

Rendered with the default dark theme:

DEBUG: Resolved /etc/myapp/config.toml.
option()

Style applied to option names (--config, -v, --ansi/--no-ansi) wherever they appear: synopsis column, free-form descriptions, and docstrings (when cross_ref_highlight is enabled).

Return type:

TypeVar(T)

Rendered with the default dark theme:

--config CONFIG_PATH    Location of the configuration file.
-v, --verbose           Increase verbosity.
subcommand()

Style applied to subcommand names: in a group’s command list and wherever they are referenced in prose.

Return type:

TypeVar(T)

Rendered with the default dark theme:

Commands:
  backup        Snapshot the data store.
  restore       Restore from a snapshot.
choice()

Style applied to each individual value inside a click.Choice metavar (e.g. json, csv, xml within [json|csv|xml]) and to those values referenced in option descriptions.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--format [json|csv|xml]   Output format. Defaults to json.
metavar()

Style applied to type metavars (INTEGER, TEXT, PATH, FILE, …) that follow an option name in the synopsis column.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--output TEXT       Destination file.
--workers INTEGER   Worker count.
bracket()

Style applied to the literal bracket characters and label prefixes of trailing fields: [, ], default:, env var:, and the field separators between them. Also acts as the fallback for the four inner bracket-field slots — envvar, default, required, range_label — whenever any of them is left at identity. A theme that only sets bracket therefore renders the whole bracket field with a single uniform style; richer themes layer specific colors on top by setting the inner slots.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--port INTEGER    [env var: PORT; default: 8080; required]
envvar()

Style applied to environment-variable values inside [env var: ...] bracket fields, and to envvar names mentioned in option descriptions. Falls back to bracket when left at identity, so a theme that only styles bracket still gets a consistent rendering inside bracket fields.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--threshold INTEGER   Acceptable error rate.
                      [env var: THRESHOLD, TEST_THRESHOLD]
default()

Style applied to the default-value content inside [default: ...] bracket fields. Falls back to bracket when left at identity.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--output FILENAME    Destination file.  [default: out.csv]
--retries INTEGER    Retry budget.  [default: 5]
range_label()

Style applied to range expressions (0<=x<=9, x>=1024, 0<=x<100) that appear inside bracket fields for IntRange and FloatRange options. Falls back to bracket when left at identity.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--level INTEGER RANGE    Verbosity level.  [0<=x<=9]
--port INTEGER RANGE     Bind port.        [x>=1024]
required()

Style applied to the required label inside bracket fields on mandatory options. Falls back to bracket when left at identity.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--token TEXT    Authentication token.  [required]
argument()

Style applied to argument metavars (positional parameter names like MY_ARG, SCRIPT, [FILENAMES]...) in the synopsis column and when referenced in prose.

Return type:

TypeVar(T)

Rendered with the default dark theme:

Usage: cp [OPTIONS] SRC DST
Usage: pack [OPTIONS] [FILES]... [OUTPUT]
deprecated()

Style applied to (DEPRECATED) / (Deprecated: reason) markers appended to options and commands.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--old-api    Legacy endpoint. (DEPRECATED: use --new-api instead)
--legacy     Kept for compatibility. (deprecated: removed in v9)
search()

Style applied to substring matches in <cli> help --search output, so users can spot where their query matched.

Return type:

TypeVar(T)

Rendered with the default dark theme:

--retry-budget INTEGER    The retry budget.
success()

Style applied to success glyphs in pre-rendered UI elements (the in OK_GLYPH) and any text passed through this slot by downstream code.

Return type:

TypeVar(T)

Rendered with the default dark theme:

 database migration completed
 1,245 records imported
cross_ref_highlight: bool = True

Highlight options, choices, arguments, metavars and CLI names in free-form text (descriptions, docstrings).

When False, only structural elements are styled: bracket fields ([default: ...], [env var: ...], ranges, [required]), deprecated messages, and subcommand names in definition lists.

subheading()

Style for sub-section headings inside log output or inline help.

Distinct from heading (which styles the top-level help-screen section titles): subheading is intended for downstream code that wants a second styling level for its own narrative output.

See also

Used by mail-deduplicate to style N mails sharing hash log lines.

Return type:

TypeVar(T)

Rendered with the default dark theme:

◼ 3 mails sharing hash a1b2c3d4
◼ 7 mails sharing hash e5f6a7b8
with_(**kwargs)[source]

Derives a new theme from the current one, with some styles overridden.

Returns the same instance if the provided styles are the same as the current.

Return type:

HelpExtraTheme

to_dict()[source]

Serialize the theme to a plain dict suitable for TOML/JSON/YAML.

Each Style slot is emitted via Style.to_dict. Slots left at their default (identity or None) are omitted, so the output only carries what the theme actually overrides. Pair with from_dict() to round-trip.

Raises:

TypeError – when a slot holds an opaque IStyle callable that is not a Style (those cannot be serialized).

Return type:

dict[str, Any]

classmethod from_dict(data)[source]

Build a theme from the plain dict produced by to_dict().

Each value is interpreted by field type: a mapping becomes a Style via Style.from_dict, while cross_ref_highlight is read as a plain bool. Unknown keys raise TypeError so typos surface immediately.

Return type:

HelpExtraTheme

cascade(base)[source]

Layer this theme’s set slots on top of base.

Mirrors Style.cascade at the slot level: this theme’s non-default slots win, base fills the rest. Useful for layering a sparse override (typically parsed from a config file’s [tool.<cli>.themes.<name>] table) on top of a full built-in palette.

Raises:

TypeError – when base is not a HelpExtraTheme.

Return type:

HelpExtraTheme

click_extra.theme.nocolor_theme: HelpExtraTheme = HelpExtraTheme(invoked_command=<function identity>, command_help=<function identity>, heading=<function identity>, constraint=<function identity>, section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=<function identity>, alias_secondary=None, epilog=<function identity>, critical=<function identity>, error=<function identity>, warning=<function identity>, info=<function identity>, debug=<function identity>, option=<function identity>, subcommand=<function identity>, choice=<function identity>, metavar=<function identity>, bracket=<function identity>, envvar=<function identity>, default=<function identity>, range_label=<function identity>, required=<function identity>, argument=<function identity>, deprecated=<function identity>, search=<function identity>, success=<function identity>, cross_ref_highlight=True, subheading=<function identity>)

Color theme for Click Extra to force no colors.

All style slots default to identity, so styling calls return the raw text unchanged.

click_extra.theme.get_default_theme()[source]

Return the process-wide fallback theme.

Read by get_current_theme() when no Click context is active or when the active context has no theme set. The default is the built-in dark palette; click_extra.wrap.patch_click() overrides it via set_default_theme() for the duration of a patched session.

Resolved through a function rather than a module attribute so callers always observe the current value: capturing default_theme as a default function parameter (the previous pattern) would freeze whatever was set at import time.

Return type:

HelpExtraTheme

click_extra.theme.set_default_theme(theme)[source]

Override the process-wide fallback theme.

ThemeOption writes its picked theme to ctx.meta rather than calling this helper, so per-invocation choices do not leak across invocations sharing the same process. Use this only for genuinely process-wide overrides — click_extra.wrap.patch_click() is the canonical caller.

Return type:

None

click_extra.theme.get_current_theme()[source]

Return the theme active for the current CLI invocation.

Resolution order:

  1. The theme stored on the active Click context under click_extra.context.THEME (set by ThemeOption from --theme).

  2. The process-wide fallback returned by get_default_theme() (the dark default, or whatever click_extra.wrap.patch_click() set at process start).

Falling back through the active context (instead of reading a module attribute) keeps --theme scoped to the invocation that received it, so a second invocation in the same process starts from the default again.

Return type:

HelpExtraTheme

click_extra.theme.theme_registry: dict[str, HelpExtraTheme] = {'dark': HelpExtraTheme(invoked_command=Style(fg='bright_white'), command_help=<function identity>, heading=Style(fg='bright_blue', bold, underline), constraint=Style(fg='magenta'), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg='cyan'), alias_secondary=Style(fg='cyan', dim), epilog=<function identity>, critical=Style(fg='red', bold), error=Style(fg='red'), warning=Style(fg='yellow'), info=<function identity>, debug=Style(fg='blue'), option=Style(fg='cyan'), subcommand=Style(fg='cyan'), choice=Style(fg='magenta'), metavar=Style(fg='cyan', dim), bracket=Style(dim), envvar=Style(fg='yellow', dim), default=Style(fg='green', dim, italic), range_label=Style(fg='cyan', dim), required=Style(fg='red', dim), argument=Style(fg='cyan'), deprecated=Style(fg='bright_yellow', bold), search=Style(fg='green', bold), success=Style(fg='green'), cross_ref_highlight=True, subheading=Style(fg='blue')), 'dracula': HelpExtraTheme(invoked_command=Style(fg=#f8f8f2, bold), command_help=<function identity>, heading=Style(fg=#ff79c6, bold, underline), constraint=Style(fg=#ff79c6), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#8be9fd), alias_secondary=Style(fg=#8be9fd, dim), epilog=<function identity>, critical=Style(fg=#ff5555, bold), error=Style(fg=#ff5555), warning=Style(fg=#ffb86c), info=<function identity>, debug=Style(fg=#6272a4), option=Style(fg=#bd93f9), subcommand=Style(fg=#bd93f9), choice=Style(fg=#ff79c6), metavar=Style(fg=#bd93f9, dim), bracket=Style(fg=#6272a4), envvar=Style(fg=#ffb86c, dim), default=Style(fg=#50fa7b, dim, italic), range_label=Style(fg=#bd93f9, dim), required=Style(fg=#ff5555, dim), argument=Style(fg=#bd93f9), deprecated=Style(fg=#ffb86c, bold), search=Style(fg=#f1fa8c, bold), success=Style(fg=#50fa7b), cross_ref_highlight=True, subheading=Style(fg=#8be9fd)), 'light': HelpExtraTheme(invoked_command=Style(fg='black', bold), command_help=<function identity>, heading=Style(fg='blue', bold, underline), constraint=Style(fg='magenta'), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg='blue'), alias_secondary=Style(fg='blue', dim), epilog=<function identity>, critical=Style(fg='red', bold), error=Style(fg='red'), warning=Style(fg='magenta'), info=<function identity>, debug=Style(fg='blue', dim), option=Style(fg='blue'), subcommand=Style(fg='blue'), choice=Style(fg='magenta'), metavar=Style(fg='blue', dim), bracket=Style(dim), envvar=Style(fg='magenta', dim), default=Style(fg='green', dim, italic), range_label=Style(fg='blue', dim), required=Style(fg='red', dim), argument=Style(fg='blue'), deprecated=Style(fg='red', bold), search=Style(fg='green', bold), success=Style(fg='green'), cross_ref_highlight=True, subheading=Style(fg='blue', dim)), 'monokai': HelpExtraTheme(invoked_command=Style(fg=#f8f8f2, bold), command_help=<function identity>, heading=Style(fg=#a6e22e, bold, underline), constraint=Style(fg=#ae81ff), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#a6e22e), alias_secondary=Style(fg=#a6e22e, dim), epilog=<function identity>, critical=Style(fg=#f92672, bold), error=Style(fg=#f92672), warning=Style(fg=#fd971f), info=<function identity>, debug=Style(fg=#75715e), option=Style(fg=#66d9ef), subcommand=Style(fg=#66d9ef), choice=Style(fg=#ae81ff), metavar=Style(fg=#66d9ef, dim), bracket=Style(fg=#75715e), envvar=Style(fg=#fd971f, dim), default=Style(fg=#e6db74, dim, italic), range_label=Style(fg=#66d9ef, dim), required=Style(fg=#f92672, dim), argument=Style(fg=#66d9ef), deprecated=Style(fg=#fd971f, bold), search=Style(fg=#e6db74, bold), success=Style(fg=#a6e22e), cross_ref_highlight=True, subheading=Style(fg=#a6e22e)), 'nord': HelpExtraTheme(invoked_command=Style(fg=#eceff4, bold), command_help=<function identity>, heading=Style(fg=#5e81ac, bold, underline), constraint=Style(fg=#b48ead), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#8fbcbb), alias_secondary=Style(fg=#8fbcbb, dim), epilog=<function identity>, critical=Style(fg=#bf616a, bold), error=Style(fg=#bf616a), warning=Style(fg=#d08770), info=<function identity>, debug=Style(fg=#4c566a), option=Style(fg=#81a1c1), subcommand=Style(fg=#81a1c1), choice=Style(fg=#b48ead), metavar=Style(fg=#81a1c1, dim), bracket=Style(fg=#4c566a), envvar=Style(fg=#d08770, dim), default=Style(fg=#a3be8c, dim, italic), range_label=Style(fg=#81a1c1, dim), required=Style(fg=#bf616a, dim), argument=Style(fg=#81a1c1), deprecated=Style(fg=#d08770, bold), search=Style(fg=#ebcb8b, bold), success=Style(fg=#a3be8c), cross_ref_highlight=True, subheading=Style(fg=#88c0d0)), 'solarized_dark': HelpExtraTheme(invoked_command=Style(fg=#eee8d5, bold), command_help=<function identity>, heading=Style(fg=#268bd2, bold, underline), constraint=Style(fg=#6c71c4), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#2aa198), alias_secondary=Style(fg=#2aa198, dim), epilog=<function identity>, critical=Style(fg=#dc322f, bold), error=Style(fg=#dc322f), warning=Style(fg=#b58900), info=<function identity>, debug=Style(fg=#586e75), option=Style(fg=#268bd2), subcommand=Style(fg=#268bd2), choice=Style(fg=#6c71c4), metavar=Style(fg=#268bd2, dim), bracket=Style(fg=#586e75), envvar=Style(fg=#cb4b16, dim), default=Style(fg=#859900, dim, italic), range_label=Style(fg=#268bd2, dim), required=Style(fg=#dc322f, dim), argument=Style(fg=#268bd2), deprecated=Style(fg=#d33682, bold), search=Style(fg=#b58900, bold), success=Style(fg=#859900), cross_ref_highlight=True, subheading=Style(fg=#2aa198))}

Process-wide registry of named themes used by ThemeOption.

Each entry maps a theme name to its HelpExtraTheme instance. Built-in themes are seeded here at module load time from BUILTIN_THEMES (loaded from click_extra/themes.toml).

Use register_theme() to add your own at import time, or declare them in your CLI’s config file under [tool.<cli>.themes.<name>] — the latter goes through ConfigOption, lands on ctx.meta (see click_extra.context.THEME_OVERRIDES), and never mutates this module-level dict, so per-invocation choices don’t leak between sibling invocations sharing the same process.

click_extra.theme.register_theme(name, theme)[source]

Register a named theme in the module-level theme_registry.

Parameters:
Return type:

None

click_extra.theme.get_theme_registry(ctx=None)[source]

Return the theme registry visible to ctx.

Merges the module-level theme_registry with any per-invocation overrides stored on ctx.meta under click_extra.context.THEME_OVERRIDES. Per-invocation entries win on key collisions, which is what lets a config file’s [tool.<cli>.themes.dark] table override the built-in dark palette for one invocation without touching the global registry.

When ctx is None or has no overrides, returns a copy of the module-level registry.

Return type:

dict[str, HelpExtraTheme]

click_extra.theme.themes_from_config(table)[source]

Build a {name: HelpExtraTheme} mapping from a [tool.<cli>.themes] sub-tree.

For each entry, build a HelpExtraTheme via from_dict(). If name matches an existing key in theme_registry, the new theme is layered on top via HelpExtraTheme.cascade() so partial overrides (e.g. just one slot) inherit the rest from the built-in palette. Stand-alone names produce theme instances with the unset slots left at their defaults.

Return type:

dict[str, HelpExtraTheme]

click_extra.theme.inject_slot_example_docstring(app, what, name, obj, options, lines)[source]

Sphinx autodoc-process-docstring hook injecting per-slot colored examples.

For every HelpExtraTheme slot that has an entry in _PALETTE_EXAMPLES, append an ansi-color code block to the slot’s autodoc lines. The example is rendered through _render_slot_ansi(), which calls BUILTIN_THEMES["dark"].<slot>(text) to obtain the actual ANSI escapes click-extra would emit at runtime.

Wire this up from a Sphinx conf.py with:

from click_extra.theme import inject_slot_example_docstring


def setup(app):
    app.connect("autodoc-process-docstring", inject_slot_example_docstring)

The hook intentionally targets only click_extra.theme.HelpExtraTheme.<slot> names so it won’t accidentally rewrite unrelated docstrings; downstream projects can register the hook in their own conf.py if they consume HelpExtraTheme docstrings.

Return type:

None

click_extra.theme.palette_html(theme)[source]

Render a theme’s palette as an inline-styled HTML <dl> fragment.

The output is a two-column definition list (slot name → styled swatch plus attribute decorations) safe to inject into MyST or reST host documents via the python:render Sphinx directive (or any raw:: html block). Used by docs/theme.md to render every built-in theme’s palette at Sphinx build time without hand-maintaining swatch tables. Downstream projects with their own custom themes can call the same helper to get matching swatch listings in their own docs:

```{python:render}
from click_extra.theme import palette_html
from my_app.themes import MY_THEME
print(palette_html(MY_THEME))
```

Slots that hold identity (no styling applied), the boolean cross_ref_highlight toggle, the internal _style_kwargs cache, and a handful of inherited cloup slots that built-ins never style are skipped: every emitted row corresponds to a real palette choice in the theme.

Return type:

str

click_extra.theme.validate_themes_config(themes_subtree)[source]

Validate a [tool.<cli>.themes] sub-tree.

Registered as a built-in ConfigValidator by ConfigOption so malformed theme tables surface as ValidationError with a rooted path (my-cli.themes.<name>) rather than a deep TypeError from HelpExtraTheme.from_dict().

Return type:

None

class click_extra.theme.ThemeChoice(case_sensitive=False)[source]

Bases: ParamType

A click.ParamType whose choices track the live theme registry.

Implements the click.Choice-shaped duck interface (choices, case_sensitive, normalize_choice) so click_extra.colorize can collect theme names for per-token highlighting through the same code path it uses for Click’s own Choice. The choices attribute is a property that queries get_theme_registry() at every lookup, so themes registered late — typically by ConfigOption parsing [tool.<cli>.themes.<name>] tables before --theme is processed — are valid choices and appear in the --help metavar.

Implemented as a fresh click.ParamType rather than a click.Choice subclass to avoid relying on Click’s setter semantics for self.choices: the previous subclass design swallowed Click’s __init__()-time assignment with a no-op setter, which would silently break under any future Click version that uses object.__setattr__ (e.g. for slots) instead of regular attribute assignment.

name: str = 'choice'

the descriptive name of this type

property choices: tuple[str, ...]

Theme names visible in the current context, alphabetically sorted.

normalize_choice(choice, ctx)[source]

Mirrors click.Choice.normalize_choice() for colorize compatibility.

Return type:

str

get_metavar(param, ctx)[source]

Returns the metavar default for this param if it provides one.

Return type:

str | None

convert(value, param, ctx)[source]

Convert the value to the correct type. This is not called if the value is None (the missing value).

This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.

The param and ctx arguments may be None in certain situations, such as when converting prompt input.

If the value cannot be converted, call fail() with a descriptive message.

Parameters:
  • value (Any) – The value to convert.

  • param (Parameter | None) – The parameter that is using this type to convert its value. May be None.

  • ctx (Context | None) – The current context that arrived at this value. May be None.

Return type:

str | None

shell_complete(ctx, param, incomplete)[source]

Return a list of CompletionItem objects for the incomplete value. Most types do not provide completions, but some do, and this allows custom types to provide custom completions as well.

Parameters:
  • ctx (Context) – Invocation context for this command.

  • param (Parameter) – The parameter that is requesting completion.

  • incomplete (str) – Value being completed. May be empty.

Added in version 8.0.

Return type:

list[CompletionItem]

class click_extra.theme.ThemeOption(param_decls=None, default='dark', is_eager=True, expose_value=False, help='Color theme used for help screens.', **kwargs)[source]

Bases: ExtraOption

A pre-configured option that adds --theme to select the help-screen palette.

Accepts any name registered in theme_registry or in the per-invocation overrides loaded by ConfigOption from [tool.<cli>.themes.<name>]. Validation goes through ThemeChoice, which reads the live registry at parse time, so config-defined themes appear as valid choices and in the --help metavar without any further wiring.

The resolved HelpExtraTheme lands on the Click context under click_extra.context.THEME and applies for the duration of the current invocation only.

set_theme(ctx, param, value)[source]

Resolve the chosen theme name and store it on the Click context.

ThemeChoice has already validated value against the live registry by the time this fires, so the lookup is unconditional.

Return type:

None

click_extra.theme.BUILTIN_THEMES: dict[str, HelpExtraTheme] = {'dark': HelpExtraTheme(invoked_command=Style(fg='bright_white'), command_help=<function identity>, heading=Style(fg='bright_blue', bold, underline), constraint=Style(fg='magenta'), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg='cyan'), alias_secondary=Style(fg='cyan', dim), epilog=<function identity>, critical=Style(fg='red', bold), error=Style(fg='red'), warning=Style(fg='yellow'), info=<function identity>, debug=Style(fg='blue'), option=Style(fg='cyan'), subcommand=Style(fg='cyan'), choice=Style(fg='magenta'), metavar=Style(fg='cyan', dim), bracket=Style(dim), envvar=Style(fg='yellow', dim), default=Style(fg='green', dim, italic), range_label=Style(fg='cyan', dim), required=Style(fg='red', dim), argument=Style(fg='cyan'), deprecated=Style(fg='bright_yellow', bold), search=Style(fg='green', bold), success=Style(fg='green'), cross_ref_highlight=True, subheading=Style(fg='blue')), 'dracula': HelpExtraTheme(invoked_command=Style(fg=#f8f8f2, bold), command_help=<function identity>, heading=Style(fg=#ff79c6, bold, underline), constraint=Style(fg=#ff79c6), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#8be9fd), alias_secondary=Style(fg=#8be9fd, dim), epilog=<function identity>, critical=Style(fg=#ff5555, bold), error=Style(fg=#ff5555), warning=Style(fg=#ffb86c), info=<function identity>, debug=Style(fg=#6272a4), option=Style(fg=#bd93f9), subcommand=Style(fg=#bd93f9), choice=Style(fg=#ff79c6), metavar=Style(fg=#bd93f9, dim), bracket=Style(fg=#6272a4), envvar=Style(fg=#ffb86c, dim), default=Style(fg=#50fa7b, dim, italic), range_label=Style(fg=#bd93f9, dim), required=Style(fg=#ff5555, dim), argument=Style(fg=#bd93f9), deprecated=Style(fg=#ffb86c, bold), search=Style(fg=#f1fa8c, bold), success=Style(fg=#50fa7b), cross_ref_highlight=True, subheading=Style(fg=#8be9fd)), 'light': HelpExtraTheme(invoked_command=Style(fg='black', bold), command_help=<function identity>, heading=Style(fg='blue', bold, underline), constraint=Style(fg='magenta'), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg='blue'), alias_secondary=Style(fg='blue', dim), epilog=<function identity>, critical=Style(fg='red', bold), error=Style(fg='red'), warning=Style(fg='magenta'), info=<function identity>, debug=Style(fg='blue', dim), option=Style(fg='blue'), subcommand=Style(fg='blue'), choice=Style(fg='magenta'), metavar=Style(fg='blue', dim), bracket=Style(dim), envvar=Style(fg='magenta', dim), default=Style(fg='green', dim, italic), range_label=Style(fg='blue', dim), required=Style(fg='red', dim), argument=Style(fg='blue'), deprecated=Style(fg='red', bold), search=Style(fg='green', bold), success=Style(fg='green'), cross_ref_highlight=True, subheading=Style(fg='blue', dim)), 'monokai': HelpExtraTheme(invoked_command=Style(fg=#f8f8f2, bold), command_help=<function identity>, heading=Style(fg=#a6e22e, bold, underline), constraint=Style(fg=#ae81ff), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#a6e22e), alias_secondary=Style(fg=#a6e22e, dim), epilog=<function identity>, critical=Style(fg=#f92672, bold), error=Style(fg=#f92672), warning=Style(fg=#fd971f), info=<function identity>, debug=Style(fg=#75715e), option=Style(fg=#66d9ef), subcommand=Style(fg=#66d9ef), choice=Style(fg=#ae81ff), metavar=Style(fg=#66d9ef, dim), bracket=Style(fg=#75715e), envvar=Style(fg=#fd971f, dim), default=Style(fg=#e6db74, dim, italic), range_label=Style(fg=#66d9ef, dim), required=Style(fg=#f92672, dim), argument=Style(fg=#66d9ef), deprecated=Style(fg=#fd971f, bold), search=Style(fg=#e6db74, bold), success=Style(fg=#a6e22e), cross_ref_highlight=True, subheading=Style(fg=#a6e22e)), 'nord': HelpExtraTheme(invoked_command=Style(fg=#eceff4, bold), command_help=<function identity>, heading=Style(fg=#5e81ac, bold, underline), constraint=Style(fg=#b48ead), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#8fbcbb), alias_secondary=Style(fg=#8fbcbb, dim), epilog=<function identity>, critical=Style(fg=#bf616a, bold), error=Style(fg=#bf616a), warning=Style(fg=#d08770), info=<function identity>, debug=Style(fg=#4c566a), option=Style(fg=#81a1c1), subcommand=Style(fg=#81a1c1), choice=Style(fg=#b48ead), metavar=Style(fg=#81a1c1, dim), bracket=Style(fg=#4c566a), envvar=Style(fg=#d08770, dim), default=Style(fg=#a3be8c, dim, italic), range_label=Style(fg=#81a1c1, dim), required=Style(fg=#bf616a, dim), argument=Style(fg=#81a1c1), deprecated=Style(fg=#d08770, bold), search=Style(fg=#ebcb8b, bold), success=Style(fg=#a3be8c), cross_ref_highlight=True, subheading=Style(fg=#88c0d0)), 'solarized_dark': HelpExtraTheme(invoked_command=Style(fg=#eee8d5, bold), command_help=<function identity>, heading=Style(fg=#268bd2, bold, underline), constraint=Style(fg=#6c71c4), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg=#2aa198), alias_secondary=Style(fg=#2aa198, dim), epilog=<function identity>, critical=Style(fg=#dc322f, bold), error=Style(fg=#dc322f), warning=Style(fg=#b58900), info=<function identity>, debug=Style(fg=#586e75), option=Style(fg=#268bd2), subcommand=Style(fg=#268bd2), choice=Style(fg=#6c71c4), metavar=Style(fg=#268bd2, dim), bracket=Style(fg=#586e75), envvar=Style(fg=#cb4b16, dim), default=Style(fg=#859900, dim, italic), range_label=Style(fg=#268bd2, dim), required=Style(fg=#dc322f, dim), argument=Style(fg=#268bd2), deprecated=Style(fg=#d33682, bold), search=Style(fg=#b58900, bold), success=Style(fg=#859900), cross_ref_highlight=True, subheading=Style(fg=#2aa198))}

Mapping of built-in theme names to their HelpExtraTheme instances.

Loaded from the package data file click_extra/themes.toml at module import time and seeded into theme_registry. Adding a new built-in theme is a one-file edit in that TOML file: declare a new [<name>] table with one inline-table per styled slot.

Index by name to access any palette, e.g. BUILTIN_THEMES["dark"] or BUILTIN_THEMES["solarized_dark"].

click_extra.theme.OK_GLYPH: str = '✓'

Plain check-mark glyph for success indicators.

Style at the call site with the active theme’s success slot: get_current_theme().success(OK_GLYPH). Stored as a raw string so downstream code can render it under whichever theme is active rather than the (frozen) theme that happened to be loaded at import time.

click_extra.theme.KO_GLYPH: str = '✘'

Plain heavy-ballot-X glyph for failure indicators.

Style at the call site with the active theme’s error slot: get_current_theme().error(KO_GLYPH). See OK_GLYPH for why the glyph is exposed unstyled.