CLI Tools: Build Command Line Apps
Learn: CLI Tools: Build Command Line Apps
Welcome to TopperBlog! π
I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.
π― What I Write About:
β’ AI/ML Engineering & LLMs
β’ Web3 & Blockchain Development
β’ System Design & Architecture
β’ Interview Preparation (FAANG)
β’ Freelancing & Remote Work
β’ Modern Tech Stacks (Next.js, React, Rust, TypeScript)
β’ Performance Optimization & Best Practices
πΌ Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.
π 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.
π Let's connect and grow together in this amazing tech journey!
#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering
CLI Tools: Build Command Line Apps with Commander and Inquirer
Problem
Building command-line applications requires handling complex argument parsing, interactive prompts, and user input validation. Without proper libraries, developers must manually parse process arguments, manage state, and create interactive experiencesβleading to repetitive, error-prone code.
Solution
Commander.js provides elegant command parsing and option handling, while Inquirer.js enables interactive prompts and user input collection. Together, they create professional CLI applications with minimal boilerplate.
Code Examples
1. Basic Setup and Installation
npm init -y
npm install commander inquirer chalk
2. Simple Command Structure
// cli.js
const { program } = require('commander');
const inquirer = require('inquirer');
const chalk = require('chalk');
program
.name('mytool')
.description('A powerful CLI application')
.version('1.0.0');
program
.command('hello <name>')
.description('Greet someone')
.action((name) => {
console.log(chalk.blue(`Hello, ${name}!`));
});
program.parse(process.argv);
Usage:
node cli.js hello World
# Output: Hello, World!
3. Commands with Options
program
.command('create <project>')
.description('Create a new project')
.option('-t, --template <type>', 'Project template', 'basic')
.option('-g, --git', 'Initialize git repository')
.action((project, options) => {
console.log(chalk.green(`β Creating project: ${project}`));
console.log(` Template: ${options.template}`);
if (options.git) {
console.log(' Git initialized');
}
});
Usage:
node cli.js create myapp --template react --git
4. Interactive Prompts
program
.command('setup')
.description('Interactive setup wizard')
.action(async () => {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: 'Project name:',
default: 'my-app',
validate: (input) => input.length > 0 || 'Name required'
},
{
type: 'list',
name: 'framework',
message: 'Choose framework:',
choices: ['React', 'Vue', 'Angular', 'Svelte']
},
{
type: 'checkbox',
name: 'features',
message: 'Select features:',
choices: ['TypeScript', 'ESLint', 'Prettier', 'Testing']
},
{
type: 'confirm',
name: 'install',
message: 'Install dependencies?',
default: true
}
]);
console.log(chalk.green('\nβ Configuration:'));
console.log(JSON.stringify(answers, null, 2));
});
5. Conditional Prompts
program
.command('deploy')
.description('Deploy application')
.action(async () => {
const answers = await inquirer.prompt([
{
type: 'list',
name: 'environment',
message: 'Deploy to:',
choices: ['staging', 'production']
},
{
type: 'input',
name: 'version',
message: 'Version number:',
when: (answers) => answers.environment === 'production',
validate: (input) => /^\d+\.\d+\.\d+$/.test(input) || 'Use semver format'
},
{
type: 'confirm',
name: 'backup',
message: 'Create backup?',
when: (answers) => answers.environment === 'production',
default: true
}
]);
console.log(chalk.yellow(`\nβ Deploying to ${answers.environment}...`));
// Deployment logic
});
6. Subcommands
const dbCommand = program
.command('db')
.description('Database operations');
dbCommand
.command('migrate')
.description('Run migrations')
.action(() => {
console.log(chalk.blue('Running migrations...'));
});
dbCommand
.command('seed')
.description('Seed database')
.option('-f, --force', 'Force seed')
.action((options) => {
console.log(chalk.blue('Seeding database...'));
});
dbCommand
.command('reset')
.description('Reset database')
.action(async () => {
const { confirm } = await inquirer.prompt([
{
type: 'confirm',
name: 'confirm',
message: chalk.red('This will delete all data. Continue?'),
default: false
}
]);
if (confirm) {
console.log(chalk.green('Database reset'));
}
});
7. Complete Project Generator Example
// cli.js - Full example
const { program } = require('commander');
const inquirer = require('inquirer');
const chalk = require('chalk');
const fs = require('fs');
const path = require('path');
program
.name('scaffold')
.description('Project scaffolding tool')
.version('1.0.0');
program
.command('generate')
.description('Generate new project')
.action(async () => {
console.log(chalk.cyan('\nπ Project Generator\n'));
const answers = await inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'Project name:',
validate: (input) => {
if (!input) return 'Name required';
if (!/^[a-z0-9-]+$/.test(input)) return 'Use lowercase and hyphens';
return true;
}
},
{
type: 'list',
name: 'type',
message: 'Project type:',
choices: ['web', 'api', 'library', 'cli']
},
{
type: 'checkbox',
name: 'tools',
message: 'Development tools:',
choices: [
{ name: 'TypeScript', checked: true },
{ name: 'ESLint', checked: true },
{ name: 'Jest', checked: false },
{ name: 'Docker', checked: false }
]
},
{
type: 'confirm',
name: 'git',
message: 'Initialize git?',
default: true
}
]);
// Create project structure
const projectPath = path.join(process.cwd(), answers.name);
if (!fs.existsSync(projectPath)) {
fs.mkdirSync(projectPath, { recursive: true });
}
// Create package.json
const packageJson = {
name: answers.name,
version: '1.0.0',
type: answers.type,
tools: answers.tools
};
fs.writeFileSync(
path.join(projectPath, 'package.json'),
JSON.stringify(packageJson, null, 2)
);
console.log(chalk.green(`\nβ Project created at ${projectPath}`));
console.log(chalk.gray(`\nNext steps:`));
console.log(chalk.gray(` cd ${answers.name}`));
console.log(chalk.gray(` npm install`));
});
program.parse(process.argv);
8. Error Handling and Validation
program
.command('config <key> <value>')
.description('Set configuration')
.action((key, value) => {
try {
if (!key || !value) {
throw new Error('Key and value required');
}
// Validate key format
if (!/^[a-z.]+$/.test(key)) {
throw new Error('Invalid key format');
}
console.log(chalk.green(`β Config set: ${key} = ${value}`));
} catch (error) {
console.error(chalk.red(`β Error: ${error.message}`));
process.exit(1);
}
});
9. Progress and Spinners
const ora = require('ora');
program
.command('build')
.description('Build project')
.action(async () => {
const spinner = ora('Building...').start();
try {
await new Promise(resolve => setTimeout(resolve, 2000));
spinner.succeed('Build complete');
console.log(chalk.green('β Ready for deployment'));
} catch (error) {
spinner.fail('Build failed');
console.error(chalk.red(error.message));
}
});
10. Help and Documentation
program
.command('help-custom')
.description('Show detailed help')
.action(() => {
console.log(chalk.cyan(`
ββββββββββββββββββββββββββββββββββββββββββ
β CLI Tool Documentation β
ββββββββββββββββββββββββββββββββββββββββββ
Commands:
create <name> Create new project
setup Interactive setup
deploy Deploy application
db <action> Database operations
Options:
-h, --help Show help
-v, --version Show version
Examples:
$ mytool create myapp --template react
$ mytool setup
$ mytool deploy --environment production
`));
});
program.parse(process.argv);
Key Takeaways
| Feature | Benefit |
| Commander | Elegant argument parsing, subcommands, options |
| Inquirer | Interactive prompts, validation, conditional logic |
| Chalk | Colored output for better UX |
| Validation | Input validation prevents errors |
| Subcommands | Organize complex CLIs hierarchically |
| Async/Await | Handle async operations cleanly |
These tools transform CLI development from tedious to enjoyable, enabling professional applications with minimal code.