Save time managing and deploying your node.js app

Nodejitsu has joined GoDaddy

We are excited to join GoDaddy to help spearhead their largest Node.js product: Website Builder. Please read our blog post to learn more about customer transition plans and our continued support for Open Source within the node community.

Want to know all the details?
Read the full blog post or read the GoDaddy Announcement.

npmawesome: Parsing command line options with yargs

About the author

nodejitsu nodejitsu

Other popular posts

- Scaling Isomorphic Javascript Code - Keep a node.js server up with Forever - Package.json dependencies done right
- npm cheat sheet - 6 Must Have Node.js Modules

This is a guest post from Alex Gorbatchev and Nodejitsu loved what Alex was doing at and is now supporting the project. Like what you see here? Why don't you contribute on Github?

This post kicks off a small mini-series of posts about modules which making writing CLI (command line interface) tools in Node.js easier. Typically, when starting a new CLI tool, the first problem that you would encounter is how to read arguments that users pass via command line. Standard library gives us process.argv but if you want something a little bit more structured than an array, you have to look elsewhere.

This is where yargs (Github: chevex/yargs, License: MIT) comes in handy. This module was originally written by James Halliday and called optimist. It is now called yargs and the work is continued by Alex Ford. Lets get it installed:

npm install yargs


yargs covers most of the features you would need to parse out options from command line.

  • Named options: --foo=1 --bar=2, --foo 1 --bar 2 or even -foo 1 -bar 2
  • Groupped options tarball style: -x, -xz, -xzvf
  • Count options: -v, -vv, -vvv
  • Non-hyphenated options.
  • Usage / requirements.
  • Defaults.
  • Typing (boolean, string, etc).

Lets look at each one:

Named options


#!/usr/bin/env node
var argv = require('yargs').argv;

if (argv.a > argv.b) {
  console.log('a seems bigger than b');
} else {
  console.log('a is not bigger than b');

$ ./named-options.js --a=55 --b=9.52
a seems bigger than b

$ ./named-options.js --a 1 --b 8.1
a is not bigger than b

Groupped Options tarball Style


#!/usr/bin/env node
var argv = require('yargs').argv;

if (argv.x) console.log('Will extract to disk from the archive');
if (argv.z) console.log('Will compress the resulting archive with gzip');
if (argv.f) console.log('Will read the archive from the archive file');

$ ./tar.js -z
Will compress the resulting archive with gzip

$ ./tar.js -zf
Will compress the resulting archive with gzip
Will read the archive from the archive file

$ ./tar.js -zfx
Will extract to disk from the archive
Will compress the resulting archive with gzip
Will read the archive from the archive file

Count Options


#!/usr/bin/env node
var argv = require('yargs')
    .alias('v', 'verbose')

VERBOSE_LEVEL = argv.verbose;

function WARN()  { VERBOSE_LEVEL >= 0 && console.log.apply(console, arguments); }
function INFO()  { VERBOSE_LEVEL >= 1 && console.log.apply(console, arguments); }
function DEBUG() { VERBOSE_LEVEL >= 2 && console.log.apply(console, arguments); }

WARN("Showing only important stuff");
INFO("Showing semi-mportant stuff too");
DEBUG("Extra chatty mode");

$ ./count.js
Showing only important stuff

$ ./count.js -v
Showing only important stuff
Showing semi-important stuff too

$ ./count.js -vv
Showing only important stuff
Showing semi-important stuff too
Extra chatty mode

$ ./count.js -v --verbose
Showing only important stuff
Showing semi-important stuff too
Extra chatty mode

Non-hyphenated Options


#!/usr/bin/env node
var argv = require('yargs').argv;

console.log('(%d,%d)', argv.x, argv.y);

$ ./nonopt.js -x 6.82 -y 3.35 rum
[ 'rum' ]

$ ./nonopt.js "me hearties" -x 0.54 yo -y 1.12 ho
[ 'me hearties', 'yo', 'ho' ]

Usage / Requirements


#!/usr/bin/env node
var argv = require('yargs')
  .usage('Usage: $0 -x [num] -y [num]')

console.log(argv.x / argv.y);

$ ./divide.js -x 55 -y 11

$ ./divide.js -x 4.91 -z 2.51
Usage: node ./divide.js -x [num] -y [num]

  -x  [required]
  -y  [required]

Missing required arguments: y


#!/usr/bin/env node
var argv = require('yargs')


$ ./demand_count.js a
Not enough arguments, expected 2, but only found 1

$ ./demand_count.js a b
{ _: [ 'a', 'b' ], '$0': './demand_count.js' }

$ ./demand_count.js a b c
{ _: [ 'a', 'b', 'c' ], '$0': './demand_count.js' }



#!/usr/bin/env node
var argv = require('yargs')
  .default('x', 10)
  .default('y', 10)

console.log(argv.x + argv.y);

$ ./default_singles.js -x 5


#!/usr/bin/env node
var argv = require('yargs')
  .default({ x : 10, y : 10 })

console.log(argv.x + argv.y);

$ ./default_hash.js -y 7

Typing (boolean, string, etc)


#!/usr/bin/env node
var argv = require('yargs')


$ ./boolean_single.js -v "me hearties" yo ho
[ 'me hearties', 'yo', 'ho' ]


#!/usr/bin/env node
var argv = require('yargs')

console.dir([ argv.x, argv.y, argv.z ]);

$ ./boolean_double.js -x -z one two three
[ true, false, true ]
[ 'one', 'two', 'three' ]

Putting it all together

Finally, all together this makes a fully functional options parser.

#!/usr/bin/env node
var argv = require('yargs')
  .usage('Count the lines in a file.\nUsage: $0')
  .example('$0 -f', 'count the lines in the given file')
  .alias('f', 'file')
  .describe('f', 'Load a file')

Other modules to checkout

There are many other modules that can help you figure out CLI arguments, some do more, others do less.

  • minimist (Github: substack/minimist, License: MIT) by James Halliday aka substack is a light weight module without or usage functionality. James has moved on from optimist to minimist probably around the time when community started adopting mantra of smaller modules that do one thing well. It's a personal preference and I'm glad there are options.
  • cli (Github: chriso/cli, License: MIT) by Chris O'Hara is a swiss army knife module for writing CLI applications.

Closing thoughts

I've been using optimist for over a year now and is saddened to see James giving it up, but at the same time it's exciting that the idea and implementation lives on in yargs. A problem that seems so simple on the surface, such as collecting arguments, can turn out to be a major headache without proper tools. I'm very glad yargs is here to help us deal with it.