Mastering Commander.js: Build Powerful Node.js CLIs with Ease
This comprehensive guide walks you through installing Commander.js, declaring program variables, defining options (including booleans, required, variadic, and default values), creating commands and arguments, customizing help output, using hooks, handling async actions, and advanced parsing configurations for robust Node.js command‑line applications.
Installation
Install the library with npm install commander.
Declare program variable
Import the module and create a program instance:
const { program } = require('commander');
program.version('0.0.1');Or use the Command class directly:
const { Command } = require('commander');
const program = new Command();
program.version('0.0.1');TypeScript usage:
import { Command } from 'commander';
const program = new Command();Options
Define options with .option(). Short and long flags can be combined, and descriptions are optional.
program
.option('-j | --join', 'Join IMWeb now!');Retrieve parsed options via program.opts() or program.getOptionValue('join'). Set default values, required options, and custom processing functions for booleans, required arguments, variadic arguments, and optional parameters.
Common option types
Boolean options (no argument needed).
Options with required arguments, e.g., --expect <value>.
Options with optional arguments, e.g., --optional [value].
Default values
program
.option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
program.parse();
console.log(`cheese: ${program.opts().cheese}`);Negated options
Define a --no- prefix to set the option to false when used.
Variadic arguments
program
.option('-n, --number <numbers...>', 'specify numbers')
.option('-l, --letter [letters...]', 'specify letters');
program.parse();
console.log('Options:', program.opts());
console.log('Remaining arguments:', program.args);Commands
Create commands with .command() or .addCommand(). Commands can have their own description, arguments, and action handlers.
program
.command('clone <source> [destination]')
.description('clone a repository into a newly created directory')
.action((source, destination) => {
console.log('clone command called');
});Sub‑commands can be nested, have required or optional arguments, and support variadic parameters.
Arguments
program
.argument('<username>', 'user to login')
.argument('[password]', 'password for user', 'no password given')
.action((username, password) => {
console.log('username:', username);
console.log('password:', password);
});Custom argument processing
function myParseInt(value, dummyPrevious) {
const parsed = parseInt(value, 10);
if (isNaN(parsed)) throw new commander.InvalidArgumentError('Not a number.');
return parsed;
}
program
.argument('<first>', 'integer argument', myParseInt)
.argument('[second]', 'integer argument', myParseInt, 1000)
.action((first, second) => {
console.log(`${first} + ${second} = ${first + second}`);
});Hooks
Register lifecycle hooks such as preAction and postAction to run code before or after a command’s action.
program
.option('-t, --trace', 'display trace statements for commands')
.hook('preAction', (thisCommand, actionCommand) => {
if (thisCommand.opts().trace) {
console.log(`About to call action handler for subcommand: ${actionCommand.name()}`);
console.log('arguments: %O', actionCommand.args);
console.log('options: %o', actionCommand.opts());
}
});Help
Commander automatically generates help. Customize it with .addHelpText(), change the help flag with .helpOption(), or add a dedicated help sub‑command.
program
.addHelpText('after', `
Example call:
$ custom-help --help`);
program.helpOption('-e, --HELP', 'read more information');Show help after errors with .showHelpAfterError() and control output streams via .configureOutput().
Parsing options
Control parsing behavior with methods such as .enablePositionalOptions(), .passThroughOptions(), .allowUnknownOption(), and .allowExcessArguments(false) to suit complex CLI requirements.
Advanced features
Store options as properties with .storeOptionsAsProperties() for legacy code.
Use createCommand() to instantiate a fresh command without new.
Handle Node flags (e.g., --harmony) via shebang or command‑line.
Debug sub‑commands with node --inspect and VSCode’s autoAttachChildProcesses.
Override exit behavior with .exitOverride() and customize output streams.
Example usage
A single‑command program can be built without an explicit action handler:
const { program } = require('commander');
program
.description('Wanna Join TENCENT IMWEB?')
.option('-s, --social', "I'm a candidate with work experience")
.option('-g, --graduate', "I'm a graduate")
.option('-p, --phone <number>', 'Your phone number')
.parse();
const opts = program.opts();
console.log('Welcome to IMWEB');
if (opts.social) console.log('-- has work experience');
console.log(` - ${opts.phone || 'NA'} Phone Number`);For multi‑command programs, define each command with its own options and action:
const { Command } = require('commander');
const program = new Command();
program.version('0.0.1').option('-c, --config <path>', 'set config path', './deploy.conf');
program.command('setup [env]')
.description('run setup commands for all envs')
.option('-s, --setup_mode <mode>', 'Which setup mode to use', 'normal')
.action((env, opts) => {
env = env || 'all';
console.log(`read config from ${program.opts().config}`);
console.log(`setup for ${env} env(s) with ${opts.setup_mode} mode`);
});
program.command('exec <script>')
.alias('ex')
.description('execute the given remote cmd')
.option('-e, --exec_mode <mode>', 'Which exec mode to use', 'fast')
.action((script, opts) => {
console.log(`read config from ${program.opts().config}`);
console.log(`exec "${script}" using ${opts.exec_mode} mode and config ${program.opts().config}`);
})
.addHelpText('after', `
Examples:
$ deploy exec sequential
$ deploy exec async`);
program.parse(process.argv);Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
