Upstream¶
Click Extra was born as a collection of patches for unmaintained or slow-moving click-contrib addons. Over time, many of these fixes were contributed back upstream, and the project grew into a significant contributor to the Click ecosystem.
This page tracks click-extra’s relationship with its upstream dependencies: code contributed back, issues reported, workarounds provided, and features that upstream declined.
Code contributed upstream¶
PRs authored by the click-extra maintainer and merged into upstream projects.
click¶
Default and sentinel handling:
#3137- Provide altered context to callbacks to hideUNSETvalues asNone#3068- HideSentinel.UNSETvalues for defaults processed byContext.invoke#3030- Differentiate absence of value and value of absence fordefaultandflag_valuearguments#2956- Fix reconciliation of envvar withdefault,flag_valueandtypeparameters for flag options#3225- Fix callableflag_valuebeing instantiated when used as a default#3224- HideSentinel.UNSETvalues asNoneinlookup_default()#3239- Reconcile default value passing and default activation
Help system:
#2811- Fix eagerness of help option generated byhelp_option_names#2840- Move--helpoption defaults from its class to its decorator
Enum and Choice support:
Testing:
Documentation:
python-tabulate¶
pygments¶
furo¶
cloup¶
pallets-sphinx-themes¶
click-contrib/sphinx-click¶
click-contrib/click-log¶
Upstreamed from click-extra¶
Issues that click-extra solved with local workarounds first. The fix was later contributed upstream and the workaround removed from click-extra.
click¶
#2811/#2563- Help option eagerness and deduplication. click-extra had customHelpOptionfixes; contributed upstream and removed locally.#2680- Callbacks not properly closed on CLI exit. click-extra patchedOptionto force-close; contributed the fix upstream.#2523/#2522-CliRunnerconflating stderr and stdout. click-extra backported the fix before the Click release.#2516/#2517- Help extra items (default, envvar, required) were computed and rendered together. click-extra needed them split to inject colorization; contributed the refactor upstream.
cloup¶
Addressed by click-extra¶
Issues that remain open or unfixed upstream. click-extra provides the solution.
Color and terminal support¶
click-extra implements NO_COLOR, FORCE_COLOR, and full help colorization with a theme system, addressing long-standing Click gaps:
Terminal captures as SVG¶
click-extra’s screenshot command renders a captured terminal to SVG with its own click_extra.screenshot.render_svg(). It was built on Rich’s Console.export_svg() until 9.0.0, which is where these came from: everything below is a defect the exported image carried, reported upstream and still unfixed.
Open upstream, and fixed here:
rich#3576- Underscores on the last captured line are clipped when exporting to SVG: the terminal’s clip path is computed as(rows + 1) × line_height - 1, one pixel shorter than the text it contains, which cuts the descenders off the last line. Reported in 2024 with the fix named in the report;rich#3611andrich#3991both propose it and neither is merged, sorich15.0.0still ships it.render_svgsizes the clip to the text block.rich#2742- SVG font rendering too narrow for Asian language: a run’stextLengthis computed from its character count while its column advance uses terminal cells, so the two disagree for every glyph that is not exactly one cell. The error runs both ways. Chinese, Japanese, Hangul, fullwidth Latin and emoji are drawn at half their width and stack on each other; a decomposedéàüis drawn at twice its width, and a zero-width-joiner family emoji at two and a half times. Open since 2023.render_svgsizes both fromclick_extra.screenshot.cell_width().rich#2536- Can we fix this render glitch in SVG output?: box-drawing characters do not meet cleanly, which the maintainer answers would need replacing them with drawn shapes. Open since 2022, and not addressed here either: click-extra’s tables and command tree draw the same characters.
Also carried by every image Rich exports, and dropped here:
The exported document references one
clipPathper line but defines them for every line but the last, so the final row of every capture carries a dangling reference. A browser ignores it, a strict SVG 1.1 renderer drops the element it is attached to.render_svgclips the text block as a whole, which removes the per-line paths and the failure mode with them.The stylesheet carries two
@font-facerules pointing at a CDN, so a committed image reaches the network to render as intended, and falls back silently offline or behind a content-security policy.render_svgnames a font stack and embeds nothing, which is also whatrich#2153andrich#2526run into from the other end.A run’s inter-column padding is written inside its
<text>element, so a column only lands correctly where the renderer both honorstextLengthand resolves the font:librsvg, and through itrsvg-convertand ImageMagick, does neither (rich#2153,rich#3034).render_svgstarts each run on its own column.Every line ends with a
<text>element containing only a newline, drawing nothing. Removing those, the per-line clip paths and the webfont rules together took this documentation’s 21 committed captures from 451 KB to 247 KB.
Themes and palettes¶
click-extra ships seven built-in themes (dark, light, dracula, monokai, nord, solarized_dark, plus a monochrome manpage) and covers every surface an end user reaches for: the --theme flag, a machine-wide CLICK_EXTRA_THEME variable next to the per-CLI <CLI>_THEME, and — alone in the Click ecosystem — new themes and overrides declared in the CLI’s own --config file ([tool.<cli>.themes.<name>]). Click itself has no theme system (formatter-level customization is still WIP upstream), and the competing rich help layers stop at Python and environment variables:
click#561- Add Custom Formatter System: open since 2016, the prerequisite for a Click-native theme API.click#3097- WIP: Help page customization low level api: open PR exploring the formatter customization Click maintainers committed to in#561.rich-click#219- Colour themes (can be set by user): closed completed in August 2025; rich-click now ships themes settable viaRICH_CLICK_THEMEenv var or Python config, but not via the wrapped CLI’s own configuration file.CLICK_EXTRA_THEMEfollows the same shape, one variable for every CLI in the ecosystem.rich-click#311- Using themes outside click: open follow-up showing the demand for richer theme reuse.
Configuration validation¶
click-extra’s config pipeline exposes an extension hook (ConfigValidator) so apps can validate data-keyed sub-tables ([tool.<cli>.managers.<id>], [tool.<cli>.plugins], …) inside the same strict-check pipeline that polices CLI-flag-bound keys. --validate-config collects every error before exiting and surfaces all failures with the same rooted ValidationError shape.
This is click-extra’s own design rather than an answer to a documented upstream issue: Click maintainers have closed every config-file proposal as out of scope (#1753, #386, #42, #971) and deferred to external packages, so validation of those external config files lives wherever each package chose to put it. The closest related upstream gap is click_config_file#11 (listed under Configuration files above): “warn when providing unsupported options in the config file?”: open since 2018 in an unmaintained package.
Configuration files¶
click-extra’s config module replaces the functionality of several unmaintained packages, with multi-format support (TOML, YAML, JSON, INI, XML), pyproject.toml integration, and a precedence chain:
Version option¶
click-extra’s VersionOption adds template variables for git metadata (branch, hash, date, tag), environment info, and Python/OS details, with pre-baking for compiled binaries:
Environment variables¶
click-extra auto-generates environment variables for all options and adds show_envvar as a global context setting:
Logging¶
click-extra’s logging module replaces the unmaintained click-log package:
Progress spinner¶
click-extra’s Spinner is a thread-animated, indeterminate progress spinner for blocking work of unknown duration. It supersedes the click-spinner package, last released in 2020 and openly looking for a maintainer since 2022. By design it resolves the issues and pull requests still open or rejected against that package:
click-spinner#27- Support for more spinner types and custom spinners: closed unmerged over maintenance concerns; click-extra accepts anyframessequence and ships a 90-entrySPINNERScatalog ported from cli-spinners (a superset of the molovo/revolver set this PR proposed), including the multi-character animations the PR had to drop because click-spinner’s backspace renderer could not erase them.click-spinner#33- PEP 561 compatible (inline types): closed unmerged and redirected to typeshed; click-extra is fully annotated and shipspy.typed.click-spinner#34- Feature request: spin clockwise /click-spinner#35: open issue, abandoned PR; click-extra exposes areverseflag.click-spinner#36- Spinner left last symbol on cmd /click-spinner#37: open; click-extra erases the line with\r\x1b[Krather than a non-destructive\bthat lingers in terminals like VS Code.click-spinner#41- Fix output in corner cases: open; click-extra always erases on exit and never rings the bell on a disabled or redirected stream.click-spinner#42- Printing to stdout breaks the spinner: open; click-extra defaults tostderrsostdoutdata stays clean, and itsecho()method prints above the animation without corrupting it.
Progress bar¶
click-extra’s progressbar is a drop-in for click.progressbar that also repairs a rendering bug in Click’s own bar:
click#3571-click.progressbardoesn’t show full completion when usingshow_pos=Truecombined withupdate_min_steps: open; a bar whose length is not a multiple ofupdate_min_stepsfreezes its position below completion (14/20instead of20/20). click-extra’s wrapper flushes the trailing sub-threshold steps on finish so the final position renders.
Option parsing¶
Multi-value options¶
click-extra’s MultiChoice type parses a single comma-separated token into a tuple of validated values: the pick-many counterpart to click.Choice, with a rendered [a,b,c] metavar that mirrors click.Choice’s [a|b|c] and per-value highlighting in the help colorizer. The canonical Click idiom for this is multiple=True + Choice, which requires the flag to be repeated (--tag a --tag b --tag c); SQL SELECT a, b, c-style syntax has been requested upstream multiple times and not shipped:
click#2771- Allownargs=-1in options with a non-whitespace separator: open, exactly the same feature request.click#2537- Allownargs=-1forclick.option: closed as not planned, the earlier space-separated variant.
The --columns option on --params is the headline consumer; the type is also exposed at the package root for arbitrary tags / categories / modes use cases in downstream CLIs.
Normalized arguments¶
Command tree¶
click-extra ships a --tree flag on every command, the standalone @tree_option decorator, and a wrap --tree mode that prints the subcommand hierarchy of any Click CLI without running it. That covers the whole checklist of the tree view rich-click has planned for its 1.10 release:
rich-click#269---treeintegration: open since August 2025, filed by rich-click’s maintainer after the author of the treeclick plugin reached out. It proposes a@click.tree_option()decorator, arich-click --tree [cmd]mode working on any Click CLI, and opt-in wiring throughcontext_settings: the same three surfaces click-extra exposes (default option, standalone decorator, CLI wrapper).rich-click#270- Subcommand tree view: first-concept PR from treeclick’s author, self-described as rough and stalled since September 2025.rich-click#275- 1.10 roadmap: tracks the--treeoption and@click.tree_option()among the planned features.
One design difference: treeclick embeds the tree inside --help output through custom TreeGroup/TreeCommand classes, and the older click-command-tree package registers a tree subcommand on the user’s group, walking the static commands mapping. click-extra renders the view behind a dedicated eager flag, like --man and --params: the plain help screen stays untouched, a flag cannot collide with the user’s own subcommand namespace, and the live-context walk includes lazily-registered commands.
Shell completion¶
click-extra exports any Click command tree to a Carapace completion spec, so a CLI gets native completion across every shell Carapace supports (Bash, Zsh, Fish, Nushell, PowerShell, Elvish, and more) from a single generated file. Click’s built-in completion is wired per shell and installed by hand; one spec covers them all:
click#3188- Native Carapace Support: closed as out of scope for the core framework, with the maintainers suggesting a separately-released project. click-extra is that project.
ANSI rendering in documentation¶
click-extra provides ANSI-capable session lexers, an HTML formatter, and Sphinx integration for rendering ANSI-colored CLI output in documentation, with 24-bit true-color rendering enabled by default:
pygments#1148- Can’t format console/shell-session output that includes ANSI colorspygments#477- Support ANSI (ECMA-48) color-coded text inputpygments-ansi-color#33-AnsiHtmlFormatterand ANSI-aware shell-like lexerspygments-ansi-color#35- AddAnsiHtmlFormatter(open, unmaintained upstream)nbsphinx#852- Sphinx & Pygments integration for ANSI rendering
Sphinx click:source and click:run directives¶
click-extra maintains and extends the click:source/click:run directives originally from pallets-sphinx-themes:
Sphinx python:* directives and live document rendering¶
The python:source, python:run, python:render, python:render-myst, and python:render-rst directives extend the click:* family to arbitrary Python (no Click CLI required). The render* variants parse the captured stdout as live document content: generated tables, headings, admonitions, and cross-references become first-class document nodes rather than a code block. This replaces the docs_update.py regenerator + marker-region pattern that many downstream click-extra-consuming projects use (Meta Package Manager, Mail Deduplicate, …), so the rendered HTML is always current at build time without a separate generation step. And when the generated Markdown should also live in the committed source (rendering on GitHub, reviewable in diffs), the :mirror: flag keeps a marker-delimited copy below the fence, refreshed by click-extra refresh-directives alongside the {matrix} blocks.
The click:* half of this story remains stuck upstream: the directives still live in pallets-sphinx-themes despite open requests to move them where Click users actually look for them, and MyST integration is unfinished:
sphinx-click#158- Move custom directives into Sphinx-click: open, acknowledged by maintainers.sphinx-click#127- Support myst-parser: open, click directives still RST-only upstream.pallets-sphinx-themes#61: open since 2022, also flagged in the previous section.
The python:* half (rendering executed Python output as live document content) is click-extra’s own design rather than an answer to a single upstream ticket.
Declined by upstream¶
PRs and features rejected by upstream maintainers. click-extra provides the functionality regardless.
python-tabulate¶
click-extra maintains a local patch for GitHub-Flavored Markdown table alignment.
dbcli/cli_helpers¶
Open upstream¶
PRs and issues still pending upstream.
click¶
pygments¶
python-tabulate¶
executablebooks/MyST-Parser¶
content_offsetis inflated by one when a directive’s option block precedes a body ending in blank line(s), shifting the reported source line of every body element. Worked around formyst-parser <= 5.1.0inclick_extra.sphinx.click._myst_content_offset_inflation; a root-cause fix is prepared upstream. (The earlierblock_textalignment#1048was superseded and merged as#1164, still unreleased.)The open rework
#1175makes a directive’scontent_offsetdocument-relative (the rST convention) but does not fix the inflation above. When it releases,click_extra.sphinx.click.ClickDirective.abs_content_offsetcollapses onto its rST branch (content_offsetverbatim) instead of addingdirective.lineno; see the sketch tracked for that migration.