Befehlszeilentools automatisieren sich wiederholende Aufgaben, unterstützen Projekte und unterstützen die Arbeitsabläufe von Entwicklern. Node.js eignet sich hervorragend zum Erstellen von CLIs – vertrautes JavaScript, ein umfangreiches Ökosystem und einfache npm-Verteilung. In diesem Leitfaden wird ein vollständiges, veröffentlichungsfähiges CLI-Tool von Grund auf erstellt.
📋 Table of Contents
- Warum CLI-Tools erstellen?
- ausführt Projekt-Setup
- Grundlegende CLI mit Commander
- Farbige Ausgabe mit Kreide
- Interaktive Eingabeaufforderungen mit Inquirer
- Laden von Spinnern mit Ora
- Ein vollständiges Beispiel: Project Scaffolder
- Testen und Veröffentlichen auf npm
- Best Practices
- Häufig gestellte Fragen
- Conclusion
Warum CLI-Tools erstellen?
- Arbeitsabläufe automatisieren: Verwandeln Sie wiederkehrende Aufgaben in einen einzigen Befehl
- Einfach verteilen: Auf npm veröffentlichen, global mit einem Befehl installieren
- Vertraute Sprache: JavaScript/TypeScript mit einem riesigen Ökosystem
- Plattformübergreifend: Läuft überall dort, wo Node.js
ausführt Projekt-Setup
mkdir my-cli && cd my-cli
npm init -y
npm install commander chalk inquirer ora
// package.json - add the bin field and type
{
"name": "my-cli",
"version": "1.0.0",
"type": "module",
"bin": {
"mycli": "./index.js"
}
}
Grundlegende CLI mit Commander
#!/usr/bin/env node
// index.js - the shebang line makes it executable
import { program } from 'commander';
program
.name('mycli')
.description('A helpful developer CLI')
.version('1.0.0');
program
.command('greet')
.description('Greet someone')
.argument('', 'name to greet')
.option('-l, --loud', 'shout the greeting')
.action((name, options) => {
const msg = `Hello, ${name}!`;
console.log(options.loud ? msg.toUpperCase() : msg);
});
program.parse();
# Test it locally
node index.js greet Alice
# Hello, Alice!
node index.js greet Alice --loud
# HELLO, ALICE!
Farbige Ausgabe mit Kreide
import chalk from 'chalk';
console.log(chalk.green('✓ Success!'));
console.log(chalk.red('✗ Error occurred'));
console.log(chalk.yellow('⚠ Warning'));
console.log(chalk.blue.bold('Info:'), 'processing...');
// Combine styles
console.log(chalk.bgBlue.white(' TITLE '));
console.log(chalk.dim('subtle secondary text'));
Interaktive Eingabeaufforderungen mit Inquirer
import inquirer from 'inquirer';
async function setup() {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: 'Project name?',
default: 'my-app',
},
{
type: 'list',
name: 'framework',
message: 'Choose a framework:',
choices: ['React', 'Vue', 'Svelte'],
},
{
type: 'confirm',
name: 'typescript',
message: 'Use TypeScript?',
default: true,
},
]);
console.log(chalk.green(`Creating ${answers.projectName} with ${answers.framework}...`));
return answers;
}
Laden von Spinnern mit Ora
import ora from 'ora';
async function installDeps() {
const spinner = ora('Installing dependencies...').start();
try {
await runInstall(); // your async task
spinner.succeed('Dependencies installed');
} catch (err) {
spinner.fail('Installation failed');
throw err;
}
}
Ein vollständiges Beispiel: Project Scaffolder
#!/usr/bin/env node
import { program } from 'commander';
import inquirer from 'inquirer';
import chalk from 'chalk';
import ora from 'ora';
import fs from 'fs/promises';
program
.command('create')
.description('Scaffold a new project')
.action(async () => {
const answers = await inquirer.prompt([
{ type: 'input', name: 'name', message: 'Project name?' },
{ type: 'list', name: 'template', message: 'Template?',
choices: ['api', 'web', 'cli'] },
]);
const spinner = ora('Creating project...').start();
try {
await fs.mkdir(answers.name, { recursive: true });
await fs.writeFile(
`${answers.name}/package.json`,
JSON.stringify({ name: answers.name, version: '0.1.0' }, null, 2)
);
spinner.succeed(chalk.green(`Created ${answers.name}!`));
console.log(chalk.dim(`\n cd ${answers.name}\n npm install\n`));
} catch (err) {
spinner.fail('Failed to create project');
console.error(err);
process.exit(1);
}
});
program.parse();
Testen und Veröffentlichen auf npm
# Link locally to test as a global command
npm link
mycli create # test it works globally
# Unlink when done testing
npm unlink -g my-cli
# Publish to npm
npm login
npm publish
# Users install it globally
npm install -g my-cli
mycli --help
Best Practices
- Füge einen Knall hinzu (
#!/usr/bin/env node), sodass die Datei als ausführbare Datei - ausgeführt wird Stellen Sie hilfreiche –help-Ausgaben bereit — Commander generiert es aus Ihren Beschreibungen
- Behandeln Sie Fehler ordnungsgemäß – Bei Fehler mit Codes ungleich Null beenden (
process.exit(1)) - Geben Sie klares Feedback– Spinner, Farben und Erfolgs-/Fehlermeldungen
- Support –version– Benutzer erwarten es
- Eingabe validieren– Argumente überprüfen und nützliche Fehler anzeigen
Häufig gestellte Fragen
F: Commander oder Yargs für die Argumentanalyse?
A: Beide sind ausgezeichnet. Commander hat eine clean, chainable API and is very popular. Yargs is powerful with more built-in features. For most CLIs, Commander is a great default. Try both and pick what feels natural.
Q: How do I make my CLI executable?
A: Add a shebang line (#!/usr/bin/env node) at the top of your entry file, and define the bin field in package.json mapping a command name to the file. After npm install -g (or npm link), the command is available globally.
Q: Should I use TypeScript for a CLI?
A: For larger CLIs, yes — type safety helps. Compile to JavaScript before publishing (or use a bundler like tsup). For small CLIs, plain JavaScript is simpler. TypeScript pays off as the tool grows.
Q: How do I handle configuration files?
A: Read config from a file (.myclirc, package.json field, or cosmiconfig which handles multiple formats). Let users configure defaults, then override with command-line flags. cosmiconfig is the standard library for this.
Q: Can I distribute a CLI without npm?
A: Yes — bundle it into a single executable with tools like pkg or Bun’s compile feature, producing a standalone binary users run without Node.js installed. Useful for wider distribution, though npm is simplest for developer audiences.
Conclusion
Building a CLI tool with Node.js is straightforward and rewarding. Use Commander for argument parsing, Chalk for colored output, Inquirer for interactive prompts, and Ora for spinners. Add a shebang line and a bin field in package.json to make it a global command, handle errors gracefully with proper exit codes, and provide clear feedback. Test locally with npm link, then publish to npm, sodass jeder es mit einem Befehl installieren kann. CLI-Tools gehören zu den praktischsten Dingen, die Sie erstellen können – sie automatisieren Ihre Arbeitsabläufe und helfen, wenn sie veröffentlicht werden, auch anderen Entwicklern.
🔗 Share this article
✍️ Leave a Comment