How Clak compares
Clak is a class-based wrapper around Python's standard library argparse.
It is not a new parser. If you know argparse, you already know most of Clak.
This page compares Clak to argparse, Click, Typer, and Cliff. Design notes also live in the architecture ADRs (especially 2, 4, 5, 6, and 7). Feature list: Features.
Where Clak sits
- Argparse: same parser and argument kwargs. Clak changes how you author
the CLI (classes instead of imperative
add_argumentcalls). - Click / Typer: decorator and function APIs on their own parsers. Easy to start; harder to share flags in large nested apps.
- Cliff: class-based commands and views on argparse. Built for plugin-discovered OpenStack CLIs. Clak takes the class-and-views idea without that plugin machinery.
flowchart LR
argparse[argparse stdlib]
clak[Clak classes and mixins]
clickTyper[Click and Typer]
cliff[Cliff]
argparse --> clak
clak -->|"nested tree, inheritance"| apps[Git-like Python CLIs]
clickTyper -->|"decorators, own parser"| apps
cliff -->|"flat plugins, views"| apps
What Clak excels at
- Git-like nested CLIs. Each subcommand is a
Parserbound withCommand. Parent options are visible to childcli_run. Root--helplists nested subcommands (Meta.help_subcommands = "all", parent path hidden;"top"for immediate children only). - Structure at scale. Share options and behavior with class inheritance
and mixins (
LoggingOptMixin, view mixins) instead of duplicating flags on every function. - Argparse familiarity.
Argument(...)uses the same kwargs asadd_argument(...). There is no new option DSL. - Light core, optional batteries. Views, logging, XDG config, Rich help,
and completion scripts are mixins or extras. Install
colors,config,markdown, orrstonly when you need them. - Cliff-style output without Cliff. Return data from
cli_run;ShowViewMixin/ListViewMixinrender tables or--format json|yaml|csv. Suited to ops tools that need both human tables and machine output. - Stdlib-first runtime. Clak builds a real argparse tree. Startup stays close to argparse rather than a Click/Typer stack.
Clak is not aimed at one-function annotated scripts (Typer's strength) or third-party plugin-discovered CLIs (Cliff's strength).
Similarity to argparse
Canonical mapping:
argparse.ArgumentParser()->class MyApp(Parser):.add_argument(...)->dest = Argument(...).add_subparsers()/.add_parser()->name = Command(ChildParser, help=...)
Details that stay the same:
- Keyword arguments:
action,choices,help,nargs,type,default, and the rest ofadd_argument. - Positionals vs optionals: bare names vs flags that start with
-/--. Optional helpersArg(positionals only) andOpt(flags only) reject mixed names. - Re-exported constants:
OPTIONAL,SUPPRESS,ZERO_OR_MORE,ONE_OR_MORE. - Help groups:
option_group/argument_groupmap toadd_argument_group.exclusive_groupmaps to a mutually exclusive group.Command(..., command_group=)plusMeta.command_groupsis formatter-only (oneadd_subparsers). - Parse errors come from argparse (
ArgumentError); Clak wraps them for a stable message. - The help formatter subclasses
argparse.RawDescriptionHelpFormatter.
Instantiating the root parser (App()) parses argv and runs the matching
command, unless you pass parse=False.
What argparse users should not expect yet:
- Click or Typer decorator patterns
- Automatic mapping of environment variables to CLI options (planned)
- Merging two argparse parser objects (ADR 0003)
- Fully wired runtime
argcompleteduring parse (shell-script generation already ships)
Versus Click and Typer
Click and Typer optimize for a low first-command learning curve: decorate a function, get a CLI. Typer adds type annotations and Rich output.
Where Clak differs:
- API: classes (
Parser,Argument,Command), not@click.command/typer.Option. A decorator-first API is out of scope. - Parser: argparse. Click and Typer use Click's parser.
Argument(...)is argparse, not a new option language. - Scale: large nested CLIs in Click/Typer often duplicate the same flags and make help/group tweaks awkward. Clak shares them with inheritance and mixins.
- Weight: Clak's core is argparse plus descriptors. Click/Typer pull in more by default.
- Nested commands: Clak is a real subparser tree. Parent flags reach
child
cli_run. Click/Typer nest groups; running a group often needs an extra function.
Pick Click or Typer for a small annotated script. Pick Clak when the command tree will grow and you already think in argparse.
Versus Cliff
Cliff (OpenStack Command Line Interface Formulation Framework) is the closest cousin: class-based commands, argparse, git-like apps, and views.
Where Clak differs:
- Command shape: Cliff is usually a flat list plus plugin discovery
(entry points). Clak is a nested class tree you write in Python. Adding a
subcommand is
Command(...), not package metadata. - Boilerplate: Cliff targets huge, extensible CLIs. The learning curve
is high; the cliffdemo is almost required. Clak targets the same
nested-CLI problem with a
Parsersubclass and optional mixins. - Extensibility: Cliff wins when third-party plugins must register commands. Clak wins when you own the tree.
What Clak inherits from Cliff
Cliff is the main architectural influence, not only a competitor. ADR 0002 lists Cliff as the source of views, an opinionated class structure, and class-based config. ADR 0005 is the raw comparison note.
Taken from Cliff (ideas, not a code fork):
- Class-based commands on argparse. A command is a class with a
parse/run split, not a decorated function. Clak:
Parserpluscli_run. Cliff:Commandplustake_action/get_parser. - Opinionated structure. Shared base classes and mixins instead of ad-hoc argparse wiring. Clak uses inheritance more for nested trees.
- Views: return data, render later. The command does not print a table itself. It returns structured data; a view formats it. See Views.
- Show vs List. Cliff
ShowOne(one object as key/value) andLister(many rows) map toShowViewMixinandListViewMixin. - Output flags.
--format view|yaml|json|csv,--columns,--sort-columns,--sort-mode,--width. Same job as Cliff formatters (table,json,csv,yaml) and--column/--sort-column. - Ops / git-like target. Nested admin tools: many subcommands, human table plus machine JSON/YAML.
- Batteries in the same family. Completion and views are first-class (built into Cliff; mixins/extras in Clak).
Not taken from Cliff:
- Stevedore / entry-point command discovery (Cliff's strongest feature)
- A flat command namespace (Clak uses nested argparse subparsers)
- Interactive shell (Cliff plus cmd2)
- The
take_actioncontract of(column_names, data)tuples (Clak returns dicts, lists, or a view object) - App / CommandManager boilerplate and plugin settings files
In short: Clak is Cliff's class-and-views model, nested and lighter, still on argparse, without OpenStack plugin discovery.