📜 ⬆️ ⬇️

Overview of Node.js packages for parsing command line options

Node.js, like other development environments, provides basic tools for working with command line options. In our case, this is the process.argv array. But usually, except for the simplest cases of type A + B, it is very inconvenient to process command line options manually. There are several popular packages for this. The author wrote a small program that built a pivot table for these packages, chose three of the most popular ones and looked at them closer.


(The article’s material as of February 8, 2019 is still relevant, the summary table has been updated and supplemented.)


Summary table


(Because of the narrow page format, one table had to be split into two: one with information from NPM, the other with GitHub.)


#NPM PackageNPM StarsDeprecatedLast versionLast UpdateCreatedDepencies
onecommander10082.19.02019-01-012011-08-150
2yargs50812.0.52019-02-032013-11-2312
3minimist4301.2.02019-01-042013-06-250
fouroptimist143V0.6.12018-03-212010-12-212
fivemeow785.0.02019-02-042013-01-249
6cli691.0.12018-03-152011-01-012
7nopt474.0.12017-10-182011-03-302
eightcommand-line-args495.0.22018-06-252014-05-27five
9nomnom32V1.8.12018-03-172011-04-082
tenargparse211.0.102018-02-272012-05-17one
elevenstdio90.2.72017-12-012013-03-160
12dashdash91.14.12017-12-282013-02-28one
13has-flagfive3.0.02018-03-202015-07-080
14clp24.0.112019-01-032015-04-173
15clapone1.2.32017-09-202014-02-10one
sixteenargentum00.6.02016-07-292015-11-260
17getoptie01.0.22015-03-092015-03-090

#NPM PackageGithub repositoryGithub starsLast commit
onecommandertj / commander.js141112018-12-28
2yargsyargs / yargs57602019-02-08
3minimistsubstack / minimist34432015-08-29
fouroptimistsubstack / node-optimist25592014-02-05
fivemeowsindresorhus / meow16512018-11-05
6clinode-js-libs / cli7652016-10-23
7noptnpm / nopt4682019-01-26
eightcommand-line-args75lb / command-line-args3592019-01-21
9nomnomharthur / nomnom4682015-09-09
tenargparsenodeca / argparse2912018-12-01
elevenstdiosgmonda / stdio1392017-01-24
12dashdashtrentm / node-dashdash1232017-04-18
13has-flagsindresorhus / has-flag422018-12-25
14clpIonicabizau / clp122019-01-03
15claplahmatiy / clap152017-09-20
sixteenargentumrumkin / argentum02016-07-29
17getoptieavz / node-getoptie02015-03-09

This table was generated by a small JavaScript program. The source code for this review, including this program, is located in the repository on GitHub . Since after some time this data is likely to become outdated, you can download these sources to yourself, regenerate this table, and also fill it with new data simply by adding the appropriate lines to the file with the list of packages.


Packages in the table are ordered by rating, which is calculated based on the number of stars on NPM and GitHub according to the formula:


 npmStars * k + githubStars 

The coefficient k needed, since the stars on NPM look "heavier" than the stars on GitHub. The coefficient itself is considered very simple: we add the number of stars to NPM and GitHub, then we divide the number of stars by GitHub by the number of stars by NPM, round the resulting number, this is our coefficient k :


 k = floor( Sgithub / Snpm) 

From the resulting table it is clearly seen that the main favorite is the commander package. Next come the minimist and yargs packages with a close rating. The optimist package also has a good rating, but it’s declared obsolete by the author, and in his place he recommends the minimist package written by him , and also advises to see yargs and nomnom . The yargs package is also positioned as a successor to optimist . Authors of an obsolete nomnom recommend commander .


Thus, the first thing to consider is the commander , minimist, and yargs packages . It probably makes sense to also pay attention to the meow and nopt packages , but not this time.


commander


Learning to use the commander package is easy. The author provided, though not always clear, but still good documentation. To figure out how to use this package, you had to experiment. Below I will describe the highlights of this package.


So, after we downloaded the package:


 const commander = require('commander') 

We can, by calling its functions sequentially or separately, configure it to process command line options. In this package provides:



Short options are declared like this:


 commander .option('-a', 'option a') 

The first argument of the option function sets the format of the option, and the second gives it a verbal description. Access to the -a option in the program code is done through the corresponding commander property:


 if (commander.a) { console.log(commander.a) } 

An example for a long option:


 commander .option('--camel-case-option', 'camel case option') 

In this case, the code will access the option by the name camelCaseOption .


It is possible to set options for parameters both mandatory and optional:


 commander .option('-s, --source <path>', 'source file') .option('-l, --list [items]', 'value list', toArray, []) 

In the second case, the parameter of the list option is optional, it is assigned a handler function and a default value.


Options parameters can also be processed using regular expressions, for example:


 commander .option('--size [size]', 'size', /^(large|medium|small)$/i) 

Subcommand implies that a separate module is written for it. In this case, if the main program is called program , and the subcommand is command , then the module of the subcommand should be called program-command . Options passed after the subcommand is passed to the command module.


 commander .command('search <first> [other...]', 'search with query') .alias('s') 

For automatic prompts, you can specify the version of the program:


 commander.version('0.2.0') 

The hint may be accompanied by additional actions, for example, supplemented by non-standard text. To do this, you need to handle the event --help .


 commander.on('--help', () => { console.log(' Examples:') console.log('') console.log(' node commander.js') console.log(' node commander.js --help') console.log(' node commander.js -h') ... console.log(' node commander.js --size large') console.log(' node commander.js search ab c') console.log(' node commander.js -abc') }) 

The configuration is completed by calling the parse function with the process.argv parameter:


 commander.parse(process.argv) 

minimist


The author of the minimist package provided very minimal documentation. But still try to figure it out.


After we have loaded the package, we will connect and use it:


 const minimist = require('minimist') const args = minimist(process.argv.slice(2)) console.dir(args) 

This uncomplicated code will allow us to start working with this package. Let's experiment:


 node minimist.js 

 { _: [] } 

What do we see here? A set of parsed options is organized into an object. The property named _ contains a list of parameters not related to options. For example:


 node minimist.js abc 

 { _: [ 'a', 'b', 'c' ] } 

Let's continue the experiment:


 node minimist.js --help 

 { _: [], help: true } 

As you can see, minimist does not provide automatic display of hints, but simply determines the presence of this option.


Let's experiment more:


 node minimist.js -abc 

 { _: [], a: true, b: true, c: true } 

That's right. Let's see more:


 node minimist.js --camel-case-option 

 { _: [], 'camel-case-option': true } 

In contrast, minimist no transformations.


Option with parameter:


 node minimist.js --source path 

 { _: [], source: 'path' } 

Signing the same works too:


 node minimist.js --source=path 

 { _: [], source: 'path' } 

The special mode of transfer of options with use -- supported:


 node minimist.js -h -- --size=large 

 { _: [ '--size=large' ], h: true } 

The arguments that follow -- not processed and are simply placed in the _ property.


Here, in general, and all that is in the database. Let's see what options the minimist offers us to customize the handling of options.


To configure the processing of command line arguments, we must pass the second parameter to the parser with our settings. Consider the examples:


 const minimist = require('minimist') const args = minimist(process.argv.slice(2), { string: ['size'], boolean: true, alias: {'help': 'h'}, default: {'help': true}, unknown: (arg) => { console.error('Unknown option: ', arg) return false } }) console.dir(args) 

 node minimist-with-settings.js --help 

 { _: [], help: true, h: true } 

 node minimist-with-settings.js -h 

 { _: [], h: true, help: true } 

We set the --help option with a synonym -h . The result, as we see, is identical.


The boolean option set to true means that all options without parameters after the equal sign will have a boolean value. For example:


 node minimist-with-settings.js --no-help 

 { _: [], help: false, h: false } 

Here we saw how boolean options are handled: the prefix no sets the value of the option to false .


But this example doesn't work anymore, you need the equal sign:


 node minimist-with-settings.js --size large 

 Unknown option: large { _: [], size: '', help: true, h: true } 

Here we saw the processing of an unknown option and the default option.


The general conclusion: compared to the commander quite minimalist, but quite convenient.


yargs


Unlike minimist and commander, yargs offers quite extensive documentation, available by reference .


As usual, let's start with a minimal example:


 const yargs = require('yargs') console.dir(yargs.argv) 

 node yargs.js 

 { _: [], '$0': 'yargs.js' } 

Here we see an empty list of unprocessed options, as well as the file name of our program.


Consider a more complicated example:


 node yargs.js -abc --help --size=large 1 2 3 

 { _: [ 1, 2, 3 ], a: true, b: true, c: true, help: true, size: 'large', '$0': 'yargs.js' } 

Here it will be more interesting: firstly, the transferred options are perceived correctly; secondly, we have not written a single line of code to process them.


But here you can see that the option --help is not processed without prior configuration as intended.


Now consider how to use yargs in more complex cases using the following example:


 const yargs = require('yargs') yargs .usage('Usage: $0 -abc [--list 1,2,3] --size large|meduim|small [--help]') .version('1.0.0') .demand(['size']) .choices('size', ['large', 'medium', 'small']) .default('list', [], 'List of values') .describe('list', 'value list') .array('list') .help('help') .alias('help', 'h') .example('$0 --size=medium') .epilog('(c) 2016 My Name') console.dir(yargs.argv) 

 node yargs.js -h 

We get:


 Usage: yargs.js -abc [--list 1,2,3] --size large|meduim|small [--help] Options: --version Show version number [boolean] --list value list [array] [default: List of values] --help, -h Show help [boolean] --size [required] [choices: "large", "medium", "small"] Examples: yargs.js --size=medium (c) 2016 My Name 

In this example, we set the text to be displayed with the help option. help options we also specified the synonym h . They also indicated the version of the program that will be displayed with the version option.


The size option is required, moreover, it is given a list of valid values.


 node yargs.js --size large 

 { _: [], version: false, help: false, h: false, size: 'large', list: [], '$0': 'yargs.js' } 

If size passes a value that does not correspond to any of the list, then we get an error message:


 node yargs.js --size=middle 

 ... Invalid values: Argument: size, Given: "middle", Choices: "large", "medium", "small" 

The list option has a default value. This option is also treated as an array of values:


 node yargs.js --list 1 2 3 --size=large 

 { _: [], version: false, help: false, h: false, list: [ 1, 2, 3 ], size: 'large', '$0': 'yargs.js' } 

Summary


The commander and minimist packages are distinguished by the minimum number of dependencies, while yargs affects not only the number of their dependencies, but also the number of their capabilities.


Which package is better, obviously, can not be said. According to the author, the minimist is quite sufficient for the simplest cases, but in difficult situations when using it, you will have to write a lot of code for handling options manually. In this case, it is better to use commander or yargs , to your taste.


All three packages considered here have type definitions on TypeScript, which allows you to have IntelliSense running in Code .


Archive


In the original edition of September 13, 2016, the summary table at the beginning of the article was as follows:


Summary table


Update


Three more packages were added to the table, which were reported in the comments by the readers:



And two packages that were discovered through the npms.io service:



Accordingly, the updated table below:


Updated pivot table


Some analytics


Three months after writing and publishing this article on Habrahabr in
the period from September to December 2016 there have been some interesting changes in
pivot table.


December 2016 table



The balance of the vote on December 30, 2016 is as follows. 72 readers voted, abstained 65.
Of them cast their votes as follows:


  1. yargs 31% (22)
  2. commander 29% (21)
  3. minimist 21% (15)
  4. process.argv 8% (6)
  5. another package of 7% (5)
  6. optimist 4% (3)

The most popular among yargs and commander , with a minimist
also quite popular.


February 8, 2019 update


The pivot table has been updated, converted to the Markdown format and updated with the has-flag , clp and clap packages. The voting results remained about the same as the last update of December 30, 2016.


')

Source: https://habr.com/ru/post/309936/


All Articles