Yargs 4.0 is Here

I’m excited to announce that yargs 4.0 is here and it’s a big update!

I had a few major goals for this update:

  1. fix some long standing API inconsistencies.
  2. improve support for commands (this feature never felt quite right).
  3. modularize more of yargs’ components.
  4. begin moving yargs into an organization.

Breaking Changes

There a few breaking changes that you should be mindful of as you upgrade from yargs 3.x to yargs 4.x:

.help()

When called with no arguments in 3.x, help would return a string representation of the usage string that yargs would output. This felt inconsistent with other API methods (.env(), .completion()), which simply use a default option name when called with no arguments.

Calling .help() with no arguments will now default to enabling help when --help is passed to your CLI application.

.command()

There has been a major overhaul to the command API (which I will be discussing in its own section).

.version()

.version() took its arguments in the opposite order to other API methods: version #, followed by key.

.version() now takes arguments in an API consistent order: key, followed by version #. Calling version with no arguments will now default to using the --version key, and outputting the version # read from your package.json.

.strict()

strict mode will now require that any commands executed have been registered using .command().

But Wait, There’s More! Exciting New Features

.pkgConf(key, cwd)

The new .pkgConf() feature allows you to specify that yargs should load default configuration values from a key in your package.json, e.g.,:

  
  require('yargs')
    .pkgConf('nyc')
  

Would load the default reporter value from:

  
  {
    "name": "nyc",
    "version": "1.0.0",
    "nyc": {
      "reporter": "lcov"
    }
  }
  

Configure The Yargs Parser

You can now turn on and off various features in the yargs parser:

  • short-option-groups
  • camel-case-expansion
  • dot-notation
  • parse-numbers
  • boolean-negation

To do so create a yargs stanza in your project’s package.json:

  
  {
    "name": "nyc",
    "version": "1.0.0",
    "yargs": {
      "short-option-groups": false,
      "boolean-negation": false
    }
  }
  

See the Configuration Documentation of the yargs-parser project, for more information about these various parsing settings.

.number(‘foo’)

The new number type has been added to yargs, this works similar to string and boolean.

Commands 2.0

Commands always felt a bit clunky in yargs 3.x, I found myself creating a lot of boiler plate code.

yargs 4.x includes several updates to help solve this problem:

Named Positional Arguments

When creating a command you can now specify optional and required positional arguments:

  
  yargs.command('get <source> [proxy]', 'make a get HTTP request')
    .help()
    .argv
  

The above code creates a get command, with the required source argument, and the optional proxy argument.

These positional arguments will be populated in argv, like so:

  
  {
    "_": ["get"]
    "source": "the-source-you-entered",
    "proxy": "the-proxy-address-you-entered"
  }
  

Builders and Handlers

For building a complex command-line interface, yargs now allows you to specify a builder, and a handler:

builders allow you to specify what arguments a sub-command should accept.

handlers are invoked with the parsed argv object, if a command is triggered.

This design makes it easy to pull your commands into their own modules:

my-module.js:

  
  // my-module.js
  exports.builder = {
    banana: {
      default: 'cool'
    },
    batman: {
      default: 'sad'
    }
  }

  exports.handler = function (argv) {
    // do something with argv.
  }
  

my-bin.js:

  
  yargs.command('get <source> [proxy]', 'make a get HTTP request', require('my-module'))
    .help(
    .argv
  

Global Options

Globals make defining the options that commands accept less repetitive. Global options will not be reset when invoking a sub-command. Commands like help() and version() default to being global. What does this mean?

If I write:

  
  yargs.command('get <source> [proxy]', 'make a get HTTP request', require('my-module'))
    .help()
    .argv
  

Calling:

my-bin get --help

will return help specific to the get command, without me needing to redeclare this fact.

Yargs is More Modular

As part of the move to yargs 4.x, yargs has been split into more modules:

  • yargs — yargs core.
  • yargs-parser — the part of yargs that actually parses argv.
  • y18n — yargs’ i18n library.
  • cliui — yargs’ CLI layout library.

Yargs is Moving Into An Organization

One final big announcement, yargs’ is being moved into an organization. What does this mean?

There’s a Website

There is now a beautiful new website which Irina Shestak has been leading development on:

http://yargs.js.org/

There Are More Contributors

The yargs’ libraries are being moved into a GitHub organization, and several core contributors have been added:

A special thanks to James Womack and Chris Dickinson, who helped create a beautiful logo for the organization.

Read The Contributor Guidelines

In an effort to ensure that yargs is a project that is inviting to new developers, and creates a safe environment for folks to work in, a contributor’s code of conduct has been added:

http://yargs.js.org/contributing/

Thank you to everyone who has made the yargs project possible, I couldn’t be more excited about the future \o/

Ben.

We got stickers!

Yargs Sticker

Order on StickerMule.

« View More Posts