# \[ANN\] Cmdliner 2.0.0

**URL:** https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324
**Category:** Community
**Tags:** announce, ocsf
**Created:** [September 26, 2025, 8:41pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324 "2025-09-26T20:41:03Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [September 26, 2025, 8:41pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/1 "2025-09-26T20:41:03Z")

</div>

Hello,

It is my pleasure to announce the release of cmdliner 2.0.0.

> Cmdliner is a library that allows the declarative definition of command line interfaces with outstanding support for command line interface user conventions and standards.

The main points of this release are:

- ANSI styled error and deprecation messages ([details](https://erratique.ch/software/cmdliner/doc/cli.html#error_message_styling))
- Support for manpage installation ([details](https://erratique.ch/software/cmdliner/doc/cli.html#install_tool_manpages))
- Support for shell auto-completion ([details](https://erratique.ch/software/cmdliner/doc/cli.html#cli_completion))

The latter was made possible by good initial [ground work](https://github.com/dbuenzli/cmdliner/pull/187) of @andreypopp who can now claim to have unblocked my mind and the [very first](https://github.com/dbuenzli/cmdliner/issues/1) and 11 years old Cmdliner issue. Many thanks to him!

This addition has the following consequences:

1. The problematic feature that allowed you to specify command names, option names and enumerant values by a prefix if the prefix was unambiguous has now been removed. See [this issue](https://github.com/dbuenzli/cmdliner/issues/200) for the rationale. Set `CMDLINER_LEGACY_PREFIXES=true` in your environment if you find yourself in need of a quick backward compatibility fix because one of your scripts is failing due to a prefix being used (but do eventually correct the script!).

2. It finally triggered making the type `Arg.conv` abstract as [announced](https://github.com/dbuenzli/cmdliner/blob/master/CHANGES.md#v100-2017-03-02-la-forclaz-vs) it would become in 2017. See [this issue](https://github.com/dbuenzli/cmdliner/issues/206) for details.

If you are a user of cmdliner based tools. You may want to have at a look how to [configure your shell](https://erratique.ch/software/cmdliner/doc/cli.html#user_configuration) in order to benefit from their completion scripts, especially if said tools are installed via `opam`. After installing `cmdliner` you should be able to check that your configuration works correctly on the new `cmdliner` tool that now gets installed with cmdliner itself.

For other changes that may affect you or your users please head to the [release notes](https://github.com/dbuenzli/cmdliner/blob/master/CHANGES.md#v200-2025-09-26-zagreb) which have many other details.

Other than that a full pass was made over the documentation to try to improve and bring it up-to-date with the latest style and additions. Notably the [tutorial](https://erratique.ch/software/cmdliner/doc/tutorial.html) and [examples](https://erratique.ch/software/cmdliner/doc/examples.html) were updated to make use of the binding operators; however obscure [let punning](https://ocaml.org/manual/5.2/bindingops.html#ss%3Aletops-punning) may feel, these are less error prone as your number of cli arguments grow.

I also added a [cookbook](https://erratique.ch/software/cmdliner/doc/cookbook.html) which tries to distill in shorter snippets some of cmdliner’s features and the experience I gathered over the past 14 years of using cmdliner to define dozens of command line interfaces. It includes [source code structure tips](https://erratique.ch/software/cmdliner/doc/cookbook.html#tip_src_structure) and a few bootstrapping [blueprints](https://erratique.ch/software/cmdliner/doc/cookbook.html#blueprints) to cut and paste for when you start your next command line tool.

For this release I’m very thankful to a private one-time donation\[1\], a grant from the [OCaml software foundation](https://ocaml-sf.org/) and, as always, my few but faithfull [donors](https://github.com/sponsors/dbuenzli). All of which are essential for these releases to eventually get out. They do take quite a bit longer to devise that one would expect :–)

Home page: [https://erratique.ch/software/cmdliner](https://erratique.ch/software/cmdliner)  
API docs & manuals: [https://erratique.ch/software/cmdliner/doc/](https://erratique.ch/software/cmdliner/doc/) or `odig doc cmdliner`  
Install: `opam install cmdliner` (once [the PR](https://github.com/ocaml/opam-repository/pull/28599) is merged, may take a few days)

Best,

Daniel

* * *

1. Which are as nice as recurring donations ;–)

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [September 26, 2025, 9:19pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/2 "2025-09-26T21:19:44Z")

</div>

To follow up on the completion feature. It should be stressed that I don’t consider it to be fully “done” as it stands. I’m pretty sure the completion API, protocol, features and the generic completion scripts can be improved. The main problem is that it seems shell programmers are more interested in cajoling the look of their prompts than defining sane cross-shell standard protocols for tool/shell interaction. The current completion mecanisms are [broken](https://github.com/dbuenzli/cmdliner/issues/220) beyond imagination.

Issues about completion are tagged accordingly in the issue tracker. Do not hesitate to chime in if you have ideas or more knowledge than I do for improvements. I’m also happy to add support for more shells but it’s better if you help for that because working with shells makes me want to throw my computer out of the window.

Meanwhile I’d like to show two completion feature that I’m quite happy to have support for in this release.

# Context sensitive completion

The idea here, suggested by @andreypopp, is that completion can depend on a context that is specified via a cmdliner term itself. This is typically useful for configuration dependent completions: you have a cmdliner term that represents your configuration and you access it when doing a completion.

For example in the next release of `odig` you can autocomplete package names on `odig doc [PKG]`. The available packages depend on looking up a libdir which can be specified with a command line argument itself. So for example this completes according to the automatic libdir lookup

```sh
# Auto discovered libdir
> odig doc c␉
camlp-streams checkseum cmarkit camlpdf cairo2  
containers cmdliner cpuid cppo cpdf    
cstruct-lwt cstruct ctypes crunch csexp   
ctypes-foreign      

```

But the following looks for packages in another switch:

```sh
# Explicit libdir
> odig doc c␉ --lib-dir $(opam var lib --switch=myswitch) 
capitalization cerberus-lib calendar charon        
core_kernel core_unix cmdliner cppo core  
cstruct csexp  

```

[The commit](https://github.com/b0-system/odig/commit/e713f0c62c31f7009cb9d0d580094980fe93b1e6) that implements this in `odig` is rather straightforward, it simply reuses the existing `conf` term for the completion context. Also the cookbook has a [simple self-contained example](https://erratique.ch/software/cmdliner/doc/cookbook.html#args_completion) to start from.

# Compositional completion (restart and raw)

The second completion feature is to retain completion on the tools that another tool invokes – commands like `sudo`.

For example in the `b0` tool, the build system I’m using for all my developments. The `b0 vcs [OPTION]… -- VCS [ARG]…` command allows to bulk operate the VCSs of the projects you included in a `B0.ml` build description file.

Using appopriate cmdliner completion directives the completion of this command first completes the `VCS` enum (which can be `git` or `hg`) and then gracefully drops back to the completion of  
your VCS:

```sh
> b0 vcs -- ␉
git hg --
> b0 vcs -- git sh␉
shell -- restricted login shell for GIT-only SSH access
shortlog -- summarize git log output
show -- show various types of objects
show-branch -- show branches and their commits
show-index -- show packed archive index
show-ref -- list references in a local repository

```

This is a [restart](https://erratique.ch/software/cmdliner/doc/Cmdliner/Arg/Completion/index.html#val-restart) completion type. It restarts the completion context as if the cli started after the `--` token.

It is the kind of behaviour you want from e.g. `opam exec`, though arguably in the case of `opam exec` it will be sligthly misleading since completions will occur using the outer environment rather than the one setup by `opam exec -- TOOL [ARG]…`. Still, sometimes inaccurate completion is better than no completion.

Note that this would be quite easy to solve with a good cross-shell completion standard: just invoke `TOOL` in the environment setup by `opam exec` according to the completion standard (e.g. the [cmdliner completion protocol](https://erratique.ch/software/cmdliner/doc/cli.html#completion_protocol)) and propagate the result back in the completion for `opam exec`, but we do not live in that world. Still the API is ready for such a technique to be used, by using a [raw](https://erratique.ch/software/cmdliner/doc/Cmdliner/Arg/Completion/index.html#val-raw) completion type (I [use this](https://github.com/b0-system/b0/blob/9c9810ad158a83ccfbbf37a7e65b11a3a3e8a922/src/tool/b0_cmd_build.ml#L355-L384) in `b0` to complete custom, library and user-defined, actions like `b0 -- .opam` or `b0 -- .ocaml`).

---

<div class="post-metadata">

### Author: ![Rucikir](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rucikir/32/2094_2.png) [@Rucikir](https://discuss.ocaml.org/u/Rucikir)
#### Post date: [September 29, 2025, 11:58am UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/3 "2025-09-29T11:58:18Z")

</div>

This looks amazing, and I can’t wait to try it out. Thanks for all the hard work, and thanks for the great documentation! The cookbook is especially useful.

---

<div class="post-metadata">

### Author: ![anentropic](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/anentropic/32/2509_2.png) [@anentropic](https://discuss.ocaml.org/u/anentropic)
#### Post date: [September 29, 2025, 2:05pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/4 "2025-09-29T14:05:47Z")

</div>

I’m curious about this part:

> ### Avoid default option values
> 
> Optional arguments [with values](https://erratique.ch/software/cmdliner/doc/Cmdliner/Arg/index.html#val-opt "Cmdliner.Arg.opt") can have a default value, that is be of the form `--opt[=VALUE]`. In general it is better to avoid them as they lead to context sensitive command lines specifications and surprises when users refine invocations. For examples suppose you have the synopsis
> 
> ```auto
> tool --opt[=VALUE] [FILE]
> 
> ```
> 
> Trying to refine the following invocation to add a `FILE` parameter is error prone and painful:
> 
> ```auto
> tool --opt
> 
> ```
> 
> There is more than one way but the easiest way is to specify:
> 
> ```auto
> tool --opt -- FILE
> 
> ```
> 
> which is not obvious unless you have `tool`’s cli hard wired in your brain. This would have been a careless refinement if `--opt` did not have a default option value.

Optional arguments with default values are often useful. Or at least I often use them in things I’ve made with Python argparse.

Optional arguments as flags whose presence or absence are treated as setting a value, usually true/false, are also useful.

But if the optional arg takes a value then the user entering `tool --opt` seems meaningless, and `tool --opt <file>` I would expect it to take as meaning `opt=<file>`.

Is the caveat above saying that if the user enters something meaningless (`opt` with no value) then the parse is ambiguous and it’s hard to give an error? Or that the useful cases are also problematic?

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [September 29, 2025, 2:23pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/5 "2025-09-29T14:23:09Z")

</div>

> [@anentropic](#):
>
> But if the optional arg takes a value then the user entering `tool --opt` seems meaningless,

As mentioned in the synopsis it takes an _optional value_ (`--opt[=VALUE]`), so it’s not meaningless.

> [@anentropic](#):
>
> then the parse is ambiguous and it’s hard to give an error?

You can’t give an error. If you specify a non-optional argument (does not start with `-`) after an `--opt` token this will be taken as `VALUE`.

Technically this arises from being nice to users and allow option values to be specified as a separate `argv` argument rather than force them to be glued to the option after an `=` (or to the option name in the case of short options). It’s a usability tradeoff.

---

<div class="post-metadata">

### Author: ![WardBrian](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/wardbrian/32/3971_2.png) [@WardBrian](https://discuss.ocaml.org/u/WardBrian)
#### Post date: [September 29, 2025, 2:38pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/6 "2025-09-29T14:38:43Z")

</div>

Is there a way for me to provide manpages or completion scripts to end users who are downloading my tool as a binary (i.e., will not have an opam environment or cmdliner installed themselves)?

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [September 29, 2025, 3:00pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/7 "2025-09-29T15:00:38Z")

</div>

Sure you can generate all the support file beforehand yourself and add them to your tarball, see `cmdliner --help` and [here](https://erratique.ch/software/cmdliner/doc/cli.html#install_tool_manpages) for manpages and [there](https://erratique.ch/software/cmdliner/doc/cli.html#install_completion) for completion scripts.

---

<div class="post-metadata">

### Author: ![threepwood](https://avatars.discourse-cdn.com/v4/letter/t/8dc957/32.png) [@threepwood](https://discuss.ocaml.org/u/threepwood)
#### Post date: [September 29, 2025, 3:29pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/8 "2025-09-29T15:29:10Z")

</div>

The python equivalent of the thing we’re talking about is setting `nargs` to `'?'` for an optional argument which I suspect you don’t actually use a lot. (Btw if you want to use it you need to set two defaults, `default` _and_ `const`.)

Whereas you seem to be talking about simply setting `default` for actions that take exactly one argument.

---

<div class="post-metadata">

### Author: ![anentropic](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/anentropic/32/2509_2.png) [@anentropic](https://discuss.ocaml.org/u/anentropic)
#### Post date: [September 29, 2025, 7:14pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/9 "2025-09-29T19:14:51Z")

</div>

> [@dbuenzli](#):
>
> As mentioned in the synopsis it takes an _optional value_ (`--opt[=VALUE]`), so it’s not meaningless.

I guess what I really meant is `tool --opt[=VALUE] [FILE]` seems fine to me

- I’d assume just `tool` with no args would mean `opt` is set to its default value
- `tool --opt=something` would be explicitly setting it to a new value
- but `tool --opt` by itself doesn’t seem meaningful, user is using it wrong
- …so interpreting `tool --opt FILE` as `opt=FILE` seems fine and expected

And then in other cases you have optional args which are just flags (`store_true` in argparse)

like `tool --verbose` might set `verbose=true`, with `false` as the default value if omitted

and for args like that `tool --verbose FILE` is no prob because `verbose` doesn’t expect a value

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [September 29, 2025, 7:36pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/10 "2025-09-29T19:36:33Z")

</div>

> [@anentropic](#):
>
> but `tool --opt` by itself doesn’t seem meaningful, user is using it wrong

But then the synopsis is `tool --opt=VALUE [FILE]` which is something else and not what the cookbook is talking about.

In what I’m talking about the synopsis is `--opt[=VALUE] [FILE]` and `tool --opt` is meaningful so the user “is not using it wrong”.

(I think you are confusing the notion of default value taken in your program if the option is not specified on the cli and the ability to have _on the cli_ an option name that takes a value but that can be left unspecified).

---

<div class="post-metadata">

### Author: ![hannes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hannes/32/2302_2.png) [@hannes](https://discuss.ocaml.org/u/hannes)
#### Post date: [October 1, 2025, 8:29am UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/11 "2025-10-01T08:29:46Z")

</div>

Thanks a lot for this release. I notice some ecosystem utilities are not yet up-to-date with cmdliner 2.0, but fortunately lots of them have cmdliner 2.0.0 support merged in their development branches. When I come across these (ready, but not released), I open issues to ask whether they could cut a release.

So far:

- ocp-indent: [Can there be a new release, please? · Issue #335 · OCamlPro/ocp-indent · GitHub](https://github.com/OCamlPro/ocp-indent/issues/335)
- alcotest: [possible to cut a release with the cmdliner 2.0.0 support? · Issue #425 · mirage/alcotest · GitHub](https://github.com/mirage/alcotest/issues/425)
- ocamlformat: [Feature request: cut a release with the cmdliner 2.0 changes · Issue #2726 · ocaml-ppx/ocamlformat · GitHub](https://github.com/ocaml-ppx/ocamlformat/issues/2726)

(I’m aware there’s still the unsolved issue of [cmdliner 2.0.0 support · Issue #1602 · mirage/mirage · GitHub](https://github.com/mirage/mirage/issues/1602) - I lost steam when trying to work on it again.)

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [October 1, 2025, 1:02pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/12 "2025-10-01T13:02:57Z")

</div>

Thanks for the summary.

If you are dying to use `cmdliner.2.0.0` then don’t die for that but you can always use the repo version for those package that support it. I have been living with `opam pin add ocp-indent.dev --dev` for a couple of months now. `ocp-indent` has seen a bit of activity by @NathanReb recently so I’m hopeful we’ll get a release soon.

For `alcotest` I see a release is on the way (thanks @dinosaure) but technically `alcotest` can be unblocked without a release: one can also PR the opam-repository to modify the `opam` file not to `run-test:` (that’s the case for a few other packages). See [this discussion](https://discuss.ocaml.org/t/reminder-opam-repository-package-tests-do-not-snapshot-test-cmdliners-end-user-outputs/17331).

---

<div class="post-metadata">

### Author: ![Leonidas](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/leonidas/32/4039_2.png) [@Leonidas](https://discuss.ocaml.org/u/Leonidas)
#### Post date: [October 1, 2025, 1:14pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/13 "2025-10-01T13:14:05Z")

</div>

If it is just tests that are failing maybe the opam file in opam-repository could be updated to make `run-test` only execute if the alcotest version is `< 2.0`? That would unblock a lot of older versions as well.

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [October 1, 2025, 1:28pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/14 "2025-10-01T13:28:59Z")

</div>

Yes this can be done. But not by me.

I decided that I would not deal with such a granularity of details to maintain the OCaml opam-repository health on cmdliner releases (which are not the most pleasant thing to do given the amount of reverse dependencies). If your package fails because of the release, it gets a constraint.

I’m also a bit annoyed in this in case since I’m pretty sure I already warned the project on an earlier `cmdliner` release that they should not run expect tests in the repo on error message they don’t control.

This wastes everyone’s time. I repeat, [be mindful](https://discuss.ocaml.org/t/reminder-opam-repository-package-tests-do-not-snapshot-test-cmdliners-end-user-outputs/17331/3) about the tests you run in the OCaml opam-repository.

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [October 5, 2025, 8:48am UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/15 "2025-10-05T08:48:03Z")

</div>

One more seems to be:

- js\_of\_ocaml: [[FEATURE REQUEST] Update to cmdliner 2.0.0 · Issue #2104 · ocsigen/js\_of\_ocaml · GitHub](https://github.com/ocsigen/js_of_ocaml/issues/2104)

This one seems again to be a `run-test:` issue. A work around is:

```auto
opam install js_of_ocaml --ignore-constraints-on=cmdliner

```

---

<div class="post-metadata">

### Author: ![hhugo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hhugo/32/1143_2.png) [@hhugo](https://discuss.ocaml.org/u/hhugo)
#### Post date: [October 5, 2025, 4:58pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/16 "2025-10-05T16:58:37Z")

</div>

Js\_of\_ocaml doesn’t run test with opam AFAIK..

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [October 7, 2025, 8:11am UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/17 "2025-10-07T08:11:42Z")

</div>

You are right. These was a kerfuffle during the cmdliner merge due to the unexpected interference of an experimental tool. This has now [been resolved](https://github.com/ocaml/opam-repository/pull/28654).

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [October 25, 2025, 9:37am UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/18 "2025-10-25T09:37:20Z")

</div>

With the new release of `ocamlformat` it seems that all the packages that @hannes mentioned no longer block use of `cmdliner.2.0.0`.

Is there anything still preventing people from using the release ?

---

<div class="post-metadata">

### Author: ![rixed](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rixed/32/56_2.png) [@rixed](https://discuss.ocaml.org/u/rixed)
#### Post date: [November 3, 2025, 2:41pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/19 "2025-11-03T14:41:14Z")

</div>

Not totally off topic, but a couple of times I’ve wished there would be a way to have flag options with a default value of “true”, that could just be reversed with `--no-flag`. I usually use `vopt` for that (`--flag=false`). Maybe it’s worth considering for a future version?

---

<div class="post-metadata">

### Author: ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)
#### Post date: [November 3, 2025, 3:30pm UTC](https://discuss.ocaml.org/t/ann-cmdliner-2-0-0/17324/20 "2025-11-03T15:30:09Z")

</div>

> [@rixed](#):
>
> Maybe it’s worth considering for a future version?

I’d rather not add too much, especially since it’s just a `Term.app` away.

```auto
let flag = Term.(const not $ Arg.(value & flag & info ["no-flag"]))

```
