Subcommander 1.0.0
After almost 3 years after the initial commit, I have finally released subcommander v1.0.0.
Even though it sounds like yet another command-line argument parser for Node.js, subcommander is a bit different. Supporting multiple sub-command levels, it can help you create a rich CLI for your Node.js application.
A bit of history
Back in 2014 I was working on Bender.js – a bespoke test runner for CKEditor 4. One of its features was a pretty neat command line interface with multiple commands, sub-commands and plenty of parameters assigned to them. To make it all possible, I needed something more powerful than the famous commander by TJ Holowaychuk, a module which actually was an inspiration for the API subcommander exposes.
The biggest difference between those two modules is command nesting. While commander allows a single level of sub-commands, in subcommander there’s no limit.
Example CLI
To give an example let’s consider implementing the following CLI structure:
- example (our executable)
- init
- configure
- server
- start
- stop
- restart
- status
- connections
- uptime
- version
Here’s a code snippet for such a CLI:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
const sc = require('subcommander'); // configure command sc.command('configure', { desc: 'Configure the app', callback: () => {} }); // server command group let server = sc.command('server', { desc: 'Control the server' }) .option('port', { abbr: 'p', desc: 'Server port', default: '8080' }) .option('hostname', { abbr: 'H', desc: 'Server hostname' }); // server subcommand - start server.command('start', { desc: 'Start the server', callback: (options) => { let port = options.port; let hostname = options.hostname; console.log(port, hostname); } }); // server subcommand - stop server.command('stop', { desc: 'Stop the server', callback: () => console.log('server stopped') }); // server subcommand - restart server.command('restart', { desc: 'Restart the server', callback: () => console.log('server restart') }); // server subcommand - status let status = server.command('status', { desc: 'Show server status', callback: () => console.log('server status') }); // server status subcommand - connections status.command('connections', { desc: 'Display active connections', callback: () => console.log('active connections') }); // server status subcommand - uptime status.command('uptime', { desc: 'Show server uptime', callback: () => () => console.log('server uptime') }); // version command sc.command('version', { desc: 'Display app\'s version', callback: () => console.log('version') }); sc.parse(); |
Here’s how it looks when executed with -h
flag (or --help,
shows the usage information):
1 2 3 4 5 6 7 8 9 |
$ node example.js -h Usage: example.js <command> Commands: configure Configure the app server Control the server version Display app's version |
When we pass the server command and display usage information we get:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ node example.js server -h Usage: example.js server <command> [options] Commands: restart Restart the server start Start the server status Show server status stop Stop the server Options: -H, --hostname Server hostname -p, --port Server port [8080] |
And finally, server status
command and its usage info:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ node examples/example.js server status --help Usage: example.js server status <command> [options] Commands: connections Display active connections uptime Show server uptime Options: -H, --hostname Server hostname -p, --port Server port [8080] |
Notice the available options which were inherited from the parent command – server
.
Final words
Subcommander started as a tiny Node module, which originally was meant to be used exclusively in my personal projects.
It’s really nice to see it became useful to some other folks too:

To find out more about the module, please visit subcommander’s github page, where you can find more examples, usage guide and detailed API documentation.