ยท hands on

Parse command line arguments in Node.js

There are several libraries available for building command-line interface (CLI) tools in Node.js, such as optimist, minimist, yargs, Caporal.js, and commander. In this article, the author shares their favorite CLI builder, commander, because it comes with TypeScript definitions.

There are many libraries to build CLI tools for Node.js like optimist, minimist, yargs, Caporal.js and commander to name just a few. In the following article Benny gives you an overview of his favorites.

Contents

Code samples

My favorite CLI builder is commander because it comes with TypeScript definitions:

commander-example.ts
#!/usr/bin/env node
 
import program from 'commander';
 
const pkg = require('../package.json');
const appName = Object.keys(pkg.bin)[0];
 
program
  .description(pkg.description)
  .name(appName)
  .option('-c, --config <path>', 'set path to configuration file')
  .version(pkg.version)
  .parse(process.argv);
 
console.log('Configuration path', program.config);

Biggest lack of commander.js is that it does not fail if you have mandatory arguments but don't supply any argument at all. For example, it fails when calling node program.js -c because there is no value for c but it doesn't fail when just calling node program.js. Tested with commander v2.19.0 (GitHub issue).

Luckily, this got fixed in commander.js v4 with the requiredOption feature:

commander-example.ts
#!/usr/bin/env node
 
import { Command } from 'commander';
 
const pkg = require('../package.json');
const appName = Object.keys(pkg.bin)[0];
 
const program = new Command()
  .description(pkg.description)
  .name(appName)
  .requiredOption('-c, --config <path>', 'set path to configuration file')
  .version(pkg.version);
 
program.parse();
 
console.log('Configuration path', program.opts().config);

Alternatively, you can use Caporal.js which also addresses the issue and is fully written in TypeScript:

caporal-example.ts
#!/usr/bin/env node
 
import program from 'caporal';
 
const pkg = require('../package.json');
const appName = Object.keys(pkg.bin)[0];
 
program
  .version(pkg.version)
  .description(pkg.description)
  .name(appName)
  .option('--config <config>', 'set path to configuration file', undefined, undefined, true)
  .action((args, options, logger) => {
    logger.info(`Configuration value: ${options.config}`);
  });
 
program.parse(process.argv);

Should you just care about getting arguments, you will be good with minimist:

minimist-example.ts
import * as minimist from 'minimist';
 
const argv = minimist(process.argv.slice(1));

More Features

  • If you want to equip your program with some kind of configuration file (ร  la webpack.config.js or .babelrc) I can recommend cosmiconfig to you. Cosmiconfig searches for and loads configuration files with the extensions .json, .yaml, .yml, or .js.
  • If you need pattern matching you will probably fall in love with Globs which are implemened by minimatch.
  • If you need an interactive command line user interface with prompts, try Inquirer.js.
  • For more colorful log messages on the terminal, there is chalk.
Back to Blog