Master Node.js CLI Development with Commander, Inquirer, and Chalk
This guide walks you through setting up a Node.js project and using the commander, inquirer, and chalk packages to build, configure, and style powerful command‑line tools, including global installation, custom help, interactive prompts, and colored output.
Prerequisites and Project Setup
Start a new project, run npm init to generate package.json, create a main entry file without an extension, and install the required modules: npm install commander inquirer chalk --save-dev The devDependencies section of package.json will now contain these packages:
{
"name": "app",
"version": "1.0.0",
"description": "玩转命令行开发",
"main": "index.js",
"scripts": { "test": "echo \"Error: no test specified\" && exit 1" },
"author": "ykg",
"license": "ISC",
"devDependencies": {
"chalk": "^1.1.3",
"commander": "^2.9.0",
"inquirer": "^1.1.2"
}
}Commander Overview
Commander, inspired by Ruby's option parser, simplifies command‑line argument parsing and sub‑command handling. Its main features include parameter parsing, polymorphic commands, variadic arguments, Git‑style sub‑commands, automatic help generation, and customizable help text.
Parameter parsing
Polymorphic commands
Variadic arguments
Git‑style sub‑commands
Automatic help information
Customizable help
Simple Example
const program = require('commander');
const inquirer = require('inquirer');
const chalk = require('chalk');
program
.command('module')
.alias('m')
.description('创建新的模块')
.option('-a, --name [moduleName]', '模块名称')
.action(option => {
console.log('Hello World'); // 示例输出
});
program.parse(process.argv);Run the script with node app.js module (or the alias m) to see the "Hello World" output.
Running as a Global Command
To make the CLI tool globally executable:
Add a bin field to package.json: "bin": { "app": "app" } Execute npm link to create a symbolic link in the global node_modules directory and add the command to PATH.
Place a shebang line at the top of the entry file: #!/usr/bin/env node After these steps, the command can be run globally with app module or app m.
Commander API Details
command – defines a sub‑command, e.g., .command('app [name]').
alias – creates a short alias, e.g., $ app m.
description – text shown in the help output.
option – declares an option; supports short and long flags, description, optional callback, and default value.
action – registers the callback executed when the command runs (note: let is not supported in the callback).
parse – parses the command‑line arguments.
Generating Help Information
Automatic help is available via --help: $ app m --help Custom help can be added by listening to the --help event:
program.on('--help', function() {
console.log(' Examples:');
console.log('');
console.log('$ app module moduleName');
console.log('$ app m moduleName');
});Inquirer for Interactive Prompts
Inquirer provides a simple way to ask questions in the terminal. Basic usage:
var inquirer = require('inquirer');
inquirer.prompt([/* questions */]).then(function(answers) {
// handle answers
});Older code may use a traditional callback style:
inquirer.prompt([/* questions */], function(answers) {
// handle answers
});Inquirer Features
input – free‑form text entry
validate – input validation
list – selectable list
confirm – yes/no prompt
checkbox – multiple selection
A more complete example combines commander, inquirer, and lodash to collect module name, description, and optional CSS pre‑processor choice:
const program = require('commander');
const inquirer = require('inquirer');
const _ = require('lodash');
const chalk = require('chalk');
program
.command('module')
.alias('m')
.description('创建新的模块')
.option('--name [moduleName]')
.option('--sass', '启用sass')
.option('--less', '启用less')
.action(option => {
const config = _.assign({
moduleName: null,
description: '',
sass: false,
less: false
}, option);
const prompts = [];
if (typeof config.moduleName !== 'string') {
prompts.push({
type: 'input',
name: 'moduleName',
message: '请输入模块名称',
validate: input => input ? true : '不能为空'
});
}
if (typeof config.description !== 'string') {
prompts.push({
type: 'input',
name: 'moduleDescription',
message: '请输入模块描述'
});
}
if (!config.sass && !config.less) {
prompts.push({
type: 'list',
name: 'cssPretreatment',
message: '想用什么css预处理器呢',
choices: [
{ name: 'Sass/Compass', value: 'sass' },
{ name: 'Less', value: 'less' }
]
});
}
inquirer.prompt(prompts).then(answers => {
console.log(chalk.green('收工咯'));
console.log(chalk.blue('收工咯'));
console.log(chalk.blue.bgRed('收工咯'));
console.log(chalk.blue(answers));
});
})
.on('--help', function() {
console.log(' Examples:');
console.log('');
console.log('$ app module moduleName');
console.log('$ app m moduleName');
})
.parse(process.argv);Chalk for Colored Output
Chalk adds color and style to terminal strings with a lightweight API:
const chalk = require('chalk');
console.log(chalk.red('开启前端工程化之路'));
console.log(chalk.green('收工咯'));
console.log(chalk.blue.bgRed('收工咯'));References
Athena (frontend workflow tool): https://github.com/o2team/athena
Commander npm package: https://www.npmjs.com/package/commander
Inquirer npm package: https://www.npmjs.com/package/inquirer
Chalk npm package: https://www.npmjs.com/package/chalk
Example source code: https://github.com/yangzicheng/command-line
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.
Aotu Lab
Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.
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.
