CLI Framework for JavaScript (Node.js): Building Powerful Console Applications
Developing console (CLI) utilities is one of the key tasks in the Node.js ecosystem. Whether it's build automation, package management, code generation, or simple DevOps scripts — a quality CLI framework is essential. In this article, we'll break down three of the most popular tools: Commander, Yargs, and Inquirer. You'll learn how they work, what their strengths are, and see code examples.
Why Do You Need a CLI Framework?
You can write a simple console program without a framework — just handle process.argv. But as soon as the project grows, subcommands, flags, and interactive prompts appear — manual argument parsing becomes a nightmare. Frameworks take care of:
- parsing arguments and options;
- generating help (
--help); - input validation;
- support for subcommands (like in
git); - interactive user dialogs.
Commander — Classic and Standard
Commander is the most popular CLI framework for Node.js. It is used by giants like Vue CLI, NestJS, and many others. Key features: intuitive API, automatic help output, support for variadic arguments.
Example of a simple application:
#!/usr/bin/env nodeconst { Command } = require('commander');const program = new Command();
program .name('greet') .description('Greets the user') .version('1.0.0');
program .command('hello') .argument('<name>', 'User name') .option('-l, --lang <language>', 'Greeting language', 'ru') .action((name, options) => { if (options.lang === 'ru') { console.log(`Привет, ${name}!`); } else { console.log(`Hello, ${name}!`); } });
program.parse();Run: node app.js hello Ivan --lang ru → Привет, Ivan!
Commander automatically generates help with --help and supports method chaining. It's the ideal choice for most CLI utilities.
Yargs — Flexibility and Convenience
Yargs is another powerful framework, especially strong at parsing complex options and automatic type detection. It's popular among developers who need fine-grained control over arguments.
Example with Yargs:
#!/usr/bin/env nodeconst yargs = require('yargs/yargs');const { hideBin } = require('yargs/helpers');
const argv = yargs(hideBin(process.argv)) .command('calc', 'Calculator', (yargs) => { return yargs .option('a', { describe: 'First number', type: 'number', demandOption: true }) .option('b', { describe: 'Second number', type: 'number', demandOption: true }) .option('op', { describe: 'Operation (sum, sub)', type: 'string', default: 'sum' }); }, (argv) => { const { a, b, op } = argv; if (op === 'sum') console.log(`Sum: ${a + b}`); else if (op === 'sub') console.log(`Difference: ${a - b}`); else console.log('Unknown operation'); }) .demandCommand(1, 'Specify a command') .help() .argv;Yargs can automatically convert strings to numbers, booleans, and even arrays. Its powerful middleware system allows adding common checks for all commands.
Inquirer — Interactivity in the Terminal
Inquirer is not exactly a CLI framework, but rather a library for creating interactive console interfaces. It perfectly complements Commander or Yargs when you need selection prompts, text input, or checkboxes.
Example of an interactive prompt:
const inquirer = require('inquirer');
async function main() { const answers = await inquirer.prompt([ { type: 'inp Also in library
SceneKit for Swift: Complete Guide with Examples
Working with Markdown in TypeScript: Libraries, Parsers, and Tools