commander.js - nodejs command-line interfaces made easy
Commander.js is a small node.js module allowing you to define options and interacte with the user’s terminal in a simple and natural way, inspired by the Ruby library of the same name.
Features
- self-documenting code
- auto-generated help
- combined short flags (“-abc” == “-a -b -c”)
- option defaults
- option coercion
- command parsing
- prompts
Example
A basic commander program looks something like the following (taken from serve). It’s extremely easy to see what’s going on, all the options provided by the executable are laid out infront of you.
program
.version('0.0.1')
.option('-p, --port <port>', 'specify the port [3000]', Number, 3000)
.option('-H, --hidden', 'enable hidden file serving')
.option('-I, --no-icons', 'disable file icons')
.option('-L, --no-logs', 'disable request logging')
.parse(process.argv);
In the previous example only --port accepts an argument, and the value of program.port defaults to 3000. The options --no-icons and --no-logs default their properties to true, only when --no-icons is specified will program.icons be false.
The usage information is free!:
$ serve --help
Usage: serve [options]
Options:
-v, --version output the version number
-p, --port <port> specify the port [3000]
-H, --hidden enable hidden file serving
-I, --no-icons disable file icons
-L, --no-logs disable request logging
-h, --help output usage information
Utilities
Commander is bundled with some utilities for prompting user input, confirmations, passwords, lists of choices etc. Most of these utilities will ask for input if the user simply hits enter and should respond.
Below is an example of asking for a name using a single-line input prompt:
program.prompt('name: ', function(name){
console.log('hi %s', name);
});
Multi-line input is easy too, just leave out the trailing space in the message:
program.prompt('description:', function(name){
console.log('hi %s', name);
});
Coercion is useful for dates, numbers etc:
program.prompt('Age: ', Number, function(age){
console.log('age: %j', age);
});
Password prompts masking off input:
program.password('Password: ', function(pass){
console.log('got "%s"', pass);
});
Or providing a mask char:
program.password('Password: ', '*', function(pass){
console.log('got "%s"', pass);
});
Confirmations require “yes” or “y” to result in true:
program.confirm('continue? ', function(ok){
console.log(' got %j', ok);
});
There’s also choice support, so users can select from a list:
var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
console.log('Choose the coolest pet:');
program.choose(list, function(i){
console.log('you chose %d "%s"', i, list[i]);
});
presenting:
Choose the coolest pet:
1) tobi
2) loki
3) jane
4) manny
5) luna
Commands
Though I haven’t had time to polish them up yet, commander supports the idea of .. well… “commands”. The “root” executable is an instanceof Command, and well you can recursively define these to create a rich interface. GIT is a great example of this, many larger utilities use sub-command such as git remote to accept arguments, and may all then have their own options etc, using the same API as the root command. The following is a simple example:
#!/usr/bin/env node
var program = require('../');
program
.version('0.0.1')
.option('-C, --chdir <path>', 'change the working directory')
.option('-c, --config <path>', 'set config path [./deploy.conf]')
.option('-T, --no-tests', 'ignore test hook')
// $ deploy setup stage
// $ deploy setup
program
.command('setup [env]')
.description('run setup commands for all envs')
.action(function(env){
env = env || 'all';
console.log('setup for %s env(s)', env);
});
// $ deploy stage
// $ deploy production
program
.command('*')
.action(function(env){
console.log('deploying "%s"', env);
});
program.parse(process.argv);
Moar Libraries!
Dont forget to check out these other great CLI-related libraries:
- cli-table awesome unicode tables by Guillermo
- node-multimeter, ascii progress-bars by SubStack