Skip to content

picocli vs JCommander

Remko Popma edited this page May 25, 2020 · 46 revisions

How does picocli compare to JCommander?

If you like JCommander you’ll love picocli. Picocli is like JCommander on steroids.

JCommander is a great product and is one of the sources of inspiration for picocli. This page gives a quick overview of the differences between picocli and JCommander. The views below are my views, and as picocli’s author I am biased. I still hope this page is useful for people that are trying to decide which command line parsing library to use.

Unique in picocli

  • Picocli is designed to avoid becoming an external dependency. Its source code is in a single file so application authors have the choice to include it in their project as source. Of course it is also available from Maven Central and Bintray as a binary dependency.

  • Customizable usage help. Like many command line parsers, JCommander is focused on command line parsing, with a fixed usage help message. To customize the usage help in JCommander, one needs to programmatically build a custom help message using the ParameterDescription objects returned from the JCommander object in your application. By contrast, picocli provides annotations to easily customize common aspects of the usage help message. If the annotations are not sufficient, picocli provides a Help API for uncommon customizations.

  • Ansi colors and styles. Picocli usage help uses unobtrusive and easily customizable colors and styles where supported. Ships with a simple markup notation to allow application authors to colorize custom usage messages like headers, footers, description, etc.

  • Autocomplete. Picocli can generate a completion script for Bash and ZSH to autocomplete options and subcommands, for any level of subcommand depth.

  • Annotations API and programmatic API (since picocli v3). JCommander only offers annotations. The programmatic API is useful for dynamic applications where the options are discovered at runtime, useful for building a command-line DSL (domain-specific languages) and allows the use of picocli in JVM languages that don’t work well with annotations.

  • Picocli-based applications can be ahead-of-time compiled to GraalVM native images, with extremely fast startup time and lower memory requirements, which can be distributed as a single executable file.

  • Picocli is an explicit JPMS module (since picocli v4), so the jlink tool can be used to provide a trimmed binary image that has only the required modules.

Parser Comparison

  • Positional parameters are first-class citizens in picocli: strong typing, arity and self-documented in the usage help message. JCommander only supports a list of Strings for positional parameters.

  • Support for clustered POSIX short options, so you can say <command> -xvfInputFile as well as <command> -x -v -f=InputFile, JCommander only supports the latter.

  • Powerful and intuitive arity model that allows a minimum, maximum and variable number of parameters, e.g, "1..*", "3..5". With JCommander one needs to choose between minimum arity or variable arity, and both are weakly typed - Strings only.

  • Argument groups for mutually exclusive and mutually dependent options (since picocli v4). Argument groups can be nested, so groups can be exclusive or dependent on other groups. There is no equivalent for this in JCommander.

  • Negatable options automatically add negative aliases of the option (since picocli v4). If a --force option is defined as negatable = true, the parser will also recognize --no-force on the command line. There is no equivalent for this in JCommander.

  • Quoted values: when splitting parameters, quoted strings are not split. For example, given a command line argument like "-Dvalues=a,b,c","-Dother=1,2" and using , as the split regex, picocli will return two values: "-Dvalues=a,b,c" and "-Dother=1,2". No custom code required.

  • JCommander splits comma-separated values by default. Picocli will only do this if a split regex is specified.

Less Custom Code

  • Converters can be registered on the CommandLine object; no need to implement a IStringConverterFactory interface

  • Arguments can be broken up by specifying a split regular expression; no need to implement a IParameterSplitter interface

  • Strongly typed collections (not only Lists) just work; no need to implement a IStringConverter<List> interface

  • Strongly typed Maps (not only Map<String, String>) just work; no need for a @DynamicParameter annotation

  • No IParameterValidator (I’m open to be convinced otherwise, but I just didn’t see how picocli interfaces would add more value than applications either using JSR-380-BeanValidation or implementing a custom solution.)

Picocli Conveniences

  • Register nested subcommands via annotations or fluent API.

  • Fluent and compact API for executing commands: Runnable and Callable classes and @Command-annotated methods can parse the command line and run the business logic in a single line of code.

  • Simple and powerful exit code support (since picocli v4).

  • Powerful parser tracing.

  • Variable interpolation: all annotation attributes that are Strings may have embedded ${variables} that are resolved at runtime. Picocli has some predefined variables, and you can define your own variables.

  • Easy integration with Dependency Injection containers.

  • Many built-in type converters for commonly used types.

  • Works with Java 5 or higher (but is designed to facilitate the use of Java 8 lambdas). JCommander requires Java 8.

Some JCommander features not yet implemented in picocli (but on the todo list)

  • support for abbreviated options (scheduled for picocli 4.4)