Codepath

CLI

A command-line-interface (CLI) is an interface to a process that uses arguments passed on the command line and occasionally stdin as input, and stdout and stderr as output. The most common examples would be ls in bash and dir in windows.

Arguments

In node, arguments passed to the process are accessible at process.argv:

// print process.argv
process.argv.forEach((val, index) => {
  console.log(index + ': ' + val);
})
$ node index.js one two=three four
0: node
1: /Users/crabdude/node_project/index.js
2: one
3: two=three
4: four

From the above, you can see process.argv is a mere array of string values with no parsing. However, for most CLIs, there is a common convention:

  1. Use - for argument flags of one character
  2. Use -- for argument flags of more than 1 character
  3. Use = following a flag to pass a value (e.g., -f=123 or --flag=123).
  4. Separate multi-character flags or flags with values with a space (e.g., -abc ---flag1=123 --flag2=123 -d=456
  5. Arguments without - or -- are treated as commands
  6. -h displays documentation

So we will typically use a package like yargs to provide better argv parsing support:

let argv = require('yargs').argv;
console.log(`(${argv.x}, ${argv.y})`)
console.log(Boolean(argv.z))
$ node ./index.js -x 10 -y=21 -z
(10,21)
true

Stdin & Stdout

process.stdin and process.stdout are readable and writable streams respectively. Typically, we'll use process.stdout to output the contents of a readable stream like an http request instead of having to console.log every packet as it comes in:

// Use
req.pipe(process.stdout)

// Instead of
req.read(data => console.log(String(data)))

Likewise, we'll typically pipe process.stdin to a destination stream:

process.stdin.pipe(fs.createWriteStream(argv.log))

Commander

Commander is a full-featured and popular package used for easy CLI parsing. Features include auto generated help, command line prompts, and command parsing.

Commander also supports variadic arguments on the last argument, allowing for a variable number of values to be passed for the last argument.

CLI arguments are accessible using .args

let program = require('commander')
program.parse(process.argv)

// Parsed arguments in program.args
console.log('arguments: ' + program.args)
$ node ./index.js one two three
arguments: one,two,three

Define options and optional documentation with the .option() method:

let program = require('commander')
program
  .options('-c, --color [color]', 'Specify color')
  .parse(process.argv)

console.log('Color choice: ' + program.color)
$ node ./index.js -c blue
Color choice: blue
$ node ./index.js -h

Usage: index [options]

Options:

-h, --help  output usage information
-c, --color Specify color

Commander offers variadic arguments on commands. A variadic argument is specified using ... Only the last argument can be variadic.

let program = require('commander')

program
  .command('add [toppings...]')
  .action(function (toppings) {
    console.log('Pizza toppings: ' + toppings)
  })
program.parse(process.argv)
$ node ./index.js add cheese
Pizza toppings: cheese
$ node ./index.js add cheese peppers
Pizza toppings: cheese,peppers

Executables

Treat a node.js file as an executable by adding a shebang to the top of the file:

#!/usr/bin/env node
and marking it as executable:
chmod path/to/file uga+x
Fork me on GitHub