Benchmark¶
Feature comparison between Click Extra and competing CLI frameworks across ecosystems. The tables below track where Click Extra leads, where it matches, and where it can still improve.
Every cell links to its evidence. A ✅ marks support built in, on by default or behind one documented switch, and links its documentation or source line. A 🟡 marks partial or opt-in support, or support from an official companion package, and links the proof. A ❌ links a statement that rules the feature out: a maintainer’s refusal, a feature request left open, a documented limit. A blank cell means no citable source was found either way, and N/A marks a row that does not apply to the framework. A row label links to click-extra’s documentation of the feature.
Developer experience¶
Feature ↴ \ Framework → |
|
|
|
|
|
|
|
|
|
|
|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
Type-hint-driven params |
||||||||||||
Persistent / inherited flags |
||||||||||||
N/A |
||||||||||||
click-extra reads TOML, YAML, JSON, INI, and XML config files, including [tool.*] sections from pyproject.toml and remote URLs. Config-file precedence is layered through Click’s default_map, so command-line flags and environment variables always win. The strict-check pipeline ships an extension mechanism so apps can validate data-keyed sub-tables alongside click-extra’s own CLI-flag checks. cobra achieves similar coverage through Viper (YAML, TOML, JSON, HCL, INI, env vars). Cyclopts supports TOML, YAML, JSON, and env vars. Cement uses INI by default with YAML and JSON via extensions. clap requires a companion crate for config file support.
End-user experience¶
Feature ↴ \ Framework → |
|
|
|
|
|
|
|
|
|
|
|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
click-extra’s colored help uses a theme system with semantic highlighting for options, choices, metavars, defaults, env vars, and subcommand names. Seven built-in themes ship out of the box (dark, light, dracula, monokai, nord, solarized-dark, plus a monochrome manpage); users can override any slot of an existing palette or define brand-new themes directly in the CLI’s --config file ([tool.<cli>.themes.<name>]), with overrides scoped per-invocation so concurrent runs in the same process don’t bleed into each other. A machine-wide CLICK_EXTRA_THEME variable, or the per-CLI <CLI>_THEME Click derives, picks a palette without touching either. cobra’s help is plain text. Cyclopts uses Rich for formatted help output and ships a single style. rich-click also renders through Rich and ships over a hundred themes, which end users select with the RICH_CLICK_THEME variable or its wrapper’s own flag, but a custom palette is declared in Python rather than in the wrapped CLI’s configuration file, and it has no background-detection equivalent of --theme=auto. Shell completion in Click and click-extra covers command names, option names and values in bash, zsh and fish, with no installer. click-extra also offers --params, --time, --table-format and git-aware --version out of the box, and an opt-in --telemetry/--no-telemetry.
Parser flag scoping¶
Behavior when placing global flags before vs. after a subcommand:
Framework |
Global flags before subcommand |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Every framework accepts a parent command’s flags before the subcommand. Fire gets 🟡 because a bare boolean flag there takes the subcommand name as its value. The clig.dev table covers the other position: Click, and the frameworks built on it, reject a parent’s flags after the subcommand.
clig.dev guidelines¶
The Command Line Interface Guidelines are an open-source guide to command-line design. The table grades each framework against the 50 guidelines a framework can implement, out of the guide’s 96. The other 46 are advice on what an app prints and how it behaves, listed below the table.
Graded in October 2026 from source code and probes of minimal apps, against click-extra 9.4.1, Click 8.5.0, Cloup 4.0.0, cobra 1.10.2, Fire 0.7.1, Typer 0.27.2, clap 4.6.7, Cement 3.0.16, Cyclopts 5.1.1, Tyro 1.0.16, rich-click 1.9.9 and bpaf 0.9.28.
Guideline ↴ \ Framework → |
|
|
|
|
|
|
|
|
|
|
|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
Help instead of waiting on a TTY |
||||||||||||
N/A |
||||||||||||
N/A |
N/A |
N/A |
N/A |
N/A |
N/A |
N/A |
||||||
Traceback behind a debug switch |
||||||||||||
N/A |
N/A |
N/A |
N/A |
N/A |
N/A |
|||||||
Parent flags after the subcommand |
||||||||||||
No prompt when |
N/A |
N/A |
N/A |
N/A |
N/A |
N/A |
||||||
|
N/A |
N/A |
N/A |
N/A |
N/A |
N/A |
||||||
N/A |
N/A |
N/A |
N/A |
N/A |
N/A |
|||||||
|
||||||||||||
Total ✅ / 🟡 |
39 / 5 |
23 / 13 |
25 / 12 |
20 / 11 |
10 / 12 |
23 / 13 |
20 / 9 |
16 / 18 |
21 / 9 |
16 / 9 |
26 / 12 |
20 / 9 |
click-extra prints JSON and plain tables through the json and plain values of its --table-format option.
No framework skips prompts when stdin is not a TTY, accepts --no-input, or shows help instead of waiting on a terminal stdin. No framework puts a support or documentation link in the help on its own either: all of them leave it to free-form epilog text.
The 46 guidelines left out
The basics: use an argument-parsing library, which every framework is.
Help: move a long list of examples out of the help.
Output: put humans first, keep success output brief, report state changes, make the state easy to see, suggest the next command, make actions outside the program explicit, add density with ASCII art, use color with intention, use symbols and emoji where they help, hide output only the developers understand, and do not treat
stderras a log file.Errors: keep the signal-to-noise ratio high, and put the most important information where the user looks first.
Arguments and flags: prefer flags to arguments, avoid two arguments for different things, make the default right for most users, accept a word like
nonefor an optional value, and never read secrets from flags.Interactivity: let the user escape.
Subcommands: stay consistent across subcommands, name each level consistently, and avoid ambiguous names.
Robustness: work in parallel with care, time out, recover from failures, design for crashes, and expect misuse.
Future-proofing: keep changes additive, feel free to change human output, avoid a catch-all subcommand, and avoid time bombs.
Signals: skip slow clean-up on a second Ctrl-C.
Configuration: ask before changing the configuration of another program.
Environment variables: use them for context-dependent behavior, keep values on one line, do not take over common names, do not use
.envas a configuration file, and never read secrets from them.Naming: pick a simple, memorable word that is not too generic, use only lowercase letters and dashes, keep it short, and make it easy to type.
Distribution: make it easy to uninstall.
Analytics: consider alternatives to analytics.
Startup time¶
The “under 100 ms” row times a hello-world --help on an Apple Silicon Mac with Python 3.14, as the median of 15 runs: Click 36 ms, Cloup 55 ms, Fire 57 ms, Tyro 59 ms, Cement 66 ms, rich-click 73 ms, Typer 90 ms, Cyclopts 113 ms (on 5.0.0) and click-extra 141 ms. 🟡 marks a time between 100 and 200 ms. cobra, clap and bpaf compile to native executables, with no interpreter to start.
Unique strengths¶
Features unique to click-extra or significantly stronger than all competitors:
Multi-format config with
pyproject.toml: no other framework reads[tool.*]frompyproject.tomlnatively. Cobra/Viper comes closest but targets Go projects.Help colorization with theme system: click-extra highlights options, choices, metavars, defaults, env vars, and subcommand names with configurable themes. Seven built-in themes (six color palettes
dark,light,dracula,monokai,nord,solarized-darkand a monochromemanpage) plus user-defined and partial-override themes declared directly in the CLI’s--configfile ([tool.<cli>.themes.<name>]). Theme overrides are scoped per invocation viactx.meta, so back-to-back runs in the same process don’t cross-contaminate, and a machine-wideCLICK_EXTRA_THEMEsets the palette of every Click Extra CLI at once. rich-click is the only other framework shipping a theme catalog an end user can pick from, and it reads no palette from the wrapped CLI’s configuration file; the rest offer basic ANSI colors without semantic highlighting.Table and data serialization:
print_table()andserialize_data()with fifty output formats. Cement offers table output but with fewer format options and no serialization pipeline.Parameter introspection:
--paramsexposes every parameter’s value, source, default, and environment variable. Click, cobra, Typer, clap and Cyclopts expose parameter sources to code only: no other framework gives the end user an option for it.Version with git metadata: template variables for branch, hash, date, tag, with pre-baking for compiled binaries (Nuitka, PyInstaller).
Configuration validation extension hook:
ConfigValidatorlets apps declare extension paths ([tool.<cli>.managers.<id>],[tool.<cli>.plugins], …) that click-extra’s strict check skips and the app validates with rootedValidationErrors.--validate-configcollects every error in one pass. No other framework exposes the strict-check pipeline this way.wrapsubcommand: applies click-extra’s help colorization, themes, and config loading to any installed Click CLI without touching its source code. The wrapped CLI inherits the--configtheme loader, so users can theme a third-party tool from their ownpyproject.toml.Man page generation:
render_manpages()andwrite_manpages()emit one roff man page per command. They work on a command object (noconsole_scriptsentry point) and discover subcommands dynamically, superseding the unmaintained click-man (last released0.4.2in 2021). The long-standing click-man limitations are fixed by construction: Click’s\bmarkers (click-man#9), modern Python (#72), dynamic subcommands (#14, #56), plus the ENVIRONMENT, FILES and EXIT STATUS sections it never grew. cobra and bpaf are the only compared frameworks with comparable native man page output; Click itself closed the topic in 2018 (pallets/click#434).
Gaps and opportunities¶
Todo
Close the click-extra-side gaps the sections below identify:
a
@persistent_optiondecorator (or apersistent=Truekwarg on@option) registering an option on a group and injecting it into every subcommand at decoration time, covering the inherited-flags family Click has consistently declined;populate
ctx.paramsduring shell completion, so a completion callback can depend on parameter values already typed on the command line;native
NushellCompleteandPowerShellCompleteclasses, for users without thecarapacebinary the Carapace spec needs;a
@completion_optionbundling multi-shell detection and auto-install, matching Typer’s--install-completion.
Persistent / inherited flags¶
cobra’s persistent flags propagate from a parent command to all subcommands automatically. Click’s maintainers have consistently stated that options belong to the command they modify, and positional dependence (cli --opt subcmd vs cli subcmd --opt) is intentional (pallets/click#66, pallets/click#1034). The official workaround is custom decorators that apply the same options to multiple commands.
This is one of Click’s most requested features. The highest-demand closed issues all center on the same family of problems: parent group options are invisible to subcommands (pallets/click#108, 9 thumbs-up), required group options block --help on child commands (pallets/click#814, 14 thumbs-up; pallets/click#295, 15 thumbs-up), and group options are lost in CommandCollection (pallets/click#347, 13 thumbs-up: closed as not_planned in September 2025, formalizing the rejection).
The ongoing parser rewrite (pallets/click#2205) and related PR for dynamic context parameters (pallets/click#2784) could eventually unblock this upstream, but both have been in progress since 2022 with no merge date in sight. click-extra could add a @persistent_option decorator (or a persistent=True kwarg on @option) that registers the option on the group and injects it into all subcommands at decoration time. The config file support already handles cross-command defaults; persistent flags would complete the story for the CLI layer.
Enhanced shell completion¶
Click’s built-in completion covers command names, option names and values, but has several known gaps. clap, cobra, bpaf, Cyclopts, and Typer all provide richer completion out of the box. The upstream issues below represent the main areas where click-extra could close the gap:
Context-dependent completions (pallets/click#2303, pallets/click#2184, pallets/click#928): the Context object during shell completion is missing already-parsed parameter values, so completions cannot depend on previous arguments (like completing tags based on a previously typed project name). This is the highest-demand open completion issue (14+ thumbs-up). click-extra could override the completion resolution to populate ctx.params properly.
Broken --option=value completion (pallets/click#2847): completing --option=val<TAB> is broken in both bash and zsh. The = separator parsing in _resolve_context needs fixing.
Default callbacks evaluated during completion (pallets/click#2614): since Click 8.0, default value callbacks run during tab-completion even when resilient_parsing should suppress them. Makes completion slow for apps with expensive defaults.
Fish multiline help (pallets/click#3043): help text containing newlines used to break fish completion. Fixed upstream in pallets/click#3126 (merged 2026-04-29), which also closes the bug report. click-extra’s >=8.4.1 floor ships the fix, so fish completion handles multi-line help text out of the box and no click-extra workaround is needed.
Enum Choice mismatch (pallets/click#3015): click.Choice(MyEnum) completed MyEnum.foo instead of foo because completion skipped the normalization the Choice type applies at parse time. Fixed upstream in pallets/click#3471 (merged 2026-05-19, first released in Click 8.4.1), which routes completion through Choice.normalize_choice() so suggestions match what the parser accepts. click-extra’s >=8.4.1 floor closes the gap for every supported Click version. click-extra’s own EnumChoice was never affected: it stores choice strings rather than Enum members, so its completions never carried the Enum.member form.
Additional shells rejected upstream (pallets/click#2888, pallets/click#3188, pallets/click#2672): Click explicitly rejected adding nushell, Carapace, and PowerShell completion to core: all three issues are closed as not_planned, so the door is closed upstream and remains a click-extra opportunity. click-extra already answers pallets/click#3188 with the Carapace spec generator, which drives nushell and PowerShell completion through the carapace binary. Native NushellComplete and PowerShellComplete classes would close the remaining gap for users who do not install it.
Multi-shell auto-install: Typer’s --install-completion detects the current shell and installs the completion script automatically. click-extra could bundle a similar @completion_option.
Activity¶
Popularity¶
The vertical axis counts by powers of ten: Click, Typer, cobra and clap each outweigh click-extra by at least an order of magnitude, and a linear axis would draw click-extra and most of the smaller frameworks flat along the bottom edge.
GitHub restricted its stargazer endpoints to a repository’s own admins in June 2026, which left every third-party star chart on the web, this page’s star-history.com embed included, rendering an error card. repomatic sample-metrics reads every project on this page weekly into metrics.csv instead, so the history accrues here and cannot be revoked.
A line only bends where that store holds readings to bend it. click-extra is reconstructed exactly from the timestamp of every star it still holds, so its curve runs back to its first star. The alternatives are instead mined from archived copies of their GitHub pages, one capture at a time and only as far back as the archive was crawling them: a project not yet reached shows one straight line from its creation date to its first sampled reading. Read those straight segments as how far the mining has got, not as how the project grew. The star counts below are live in every case.
Distribution¶
Metadata¶
Excluded frameworks¶
Sorted by last commit, most recent first:
docopt-ng (~200 stars), last commit July 2026: the maintained fork of docopt has not released since
0.9.0in May 2023. Jazzband, the organization hosting it, is winding down and moves its projects to new homes by the end of 2026.Cleo (~1,400 stars), last commit March 2026: only automated pre-commit updates since
2.1.0in October 2023, and the 3.0 rewrite has stalled. Cleo is maintained as a part of Poetry, not on its own.docopt (~8,000 stars), last commit June 2025: no release since
0.6.2in 2014. Its docstring-driven way to declare a CLI was influential, and lives on in docopt-ng above.argh (~400 stars), last commit July 2024: no commit or release since
0.31.3.