Announcing CLI11 1.6

CLI11, a powerful library for writing beautiful command line interfaces in C++11, has been updated to 1.6, the largest update ever. CLI11 output is more customizable than ever, and has a better functionality separation under the hood.

CLI11 has had the formatting system completely redesigned, with minor or complete customization of the output possible. Configuration files reading and writing also can be configured; a new example with json instead of ini formatting is included. Validators (finally) have custom help output, as well. Many odd corner cases have been made possible, such as interleaving options.

Key new features:


You can customize the default CLI::Formatter for small output changes:

app.get_formatter()->label("REQUIRED", "(MUST HAVE)");

The label in this case is a mapping from an internal label (which happens to be the default output of CLI11) to a new output string.

If you want to make larger changes, you can subclass and modify CLI11::Formatter, then set the formatter. You can also make your own brand new formatter, either by inheriting from CLI::FormatterBase or using an arbitrary function in CLI::FormatterLambda.

auto optfmt = std::make_shared<MyFormatter>();

To enable customization, all internal properties used by help printing now have a public get_* API. New support for adding a help_all flag has been added, as well.

Like most other parts of CLI11, formatters are inherited by subcommands, and you can set new ones per subcommand if you wish.

Config files

You can now customize a command’s configuration output and input. See examples/json.cpp for an example of reading and writing json instead of ini format.


Validators are now much, much more powerful. A new validator class has been added (with a lambda function version to allow old custom validators to still work). All built-in validators use the new technology. For example, if you have a file or a range:

app.add_option("--file", file)->check(CLI::ExistingFile);
app.add_option("--value", x)->check(CLI::Range(3, 6));

You now get much better help output:

  --file FILE                 File name
  --value INT in [3 - 6]      Value in range

And much better error messages:

./examples/validators  --value 9
--value: Value 9 not in range 3 to 6
Run with --help for more information.

And you can combine validators with | and &. A new Validators class allows you to create your own validators with custom output.

Smaller features

The API for types has been improved; for example, to set up a vector of two element items, where 2, 4, 6, … items are expected: ->type_name("X Y")->type_size(-2) (also newly supported). Type names are now internally lambda functions instead of strings; this means that changing a set after creation will correctly be updated in the help message!

If you want to add a simple callback, ->each(void(string)) makes this easy. You can also initialize with an empty function, so that makes odd constructions like the following possible:

std::vector<std::string> vals;
app->add_option("--vals", {})
    ->each([&vals](std::string s){ vals.push_back(s); })

This is basically how the vector add_option is implemented, with the exception that this one will add items exactly in parse order (only matters if interleaving options).

The get_options, get_subcommands have learned to accept a filter; an empty filter returns all items.

Testing has been improved, as well; you no longer have to write app.reset() before rerunning the parser, even if an exception is thrown. Testing and examples now expects submodules to be checked out.

See the release notes for more details, checkout the readme and the GitBook tutorial series, and update today!

CLI11 was developed at the University of Cincinnati to support of the GooFit library under NSF Award 1414736.

comments powered by Disqus