Ferramentas de linha de comando automatizam tarefas repetitivas, projetos de estrutura e potencializam fluxos de trabalho de desenvolvedores. Node.js é excelente para construir CLIs – JavaScript familiar, um ecossistema rico e fácil distribuição npm. Este guia cria uma ferramenta CLI completa e publicável do zero.
📋 Table of Contents
- Por que construir ferramentas CLI?
- Configuração do Projeto
- CLI Básico com Commander
- Saída colorida com giz
- Prompts interativos com o Inquirer
- Carregando Spinners com Ora
- Um exemplo completo: andaime do projeto
- Teste e publicação no npm
- Melhores Práticas
- Perguntas frequentes
- , em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores.
Por que construir ferramentas CLI?
- Automatize fluxos de trabalho: Transforme tarefas repetitivas em um único comando
- Distribua facilmente: Publique no npm, instale globalmente com um comando
- Linguagem familiar: JavaScript/TypeScript com um enorme ecossistema
- Plataforma cruzada: Executa em qualquer lugar que o Node.js execute
Configuração do Projeto
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"
}
}
CLI Básico com 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!
Saída colorida com giz
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'));
Prompts interativos com o 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;
}
Carregando Spinners com 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;
}
}
Um exemplo completo: andaime do projeto
#!/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();
Teste e publicação no 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
Melhores Práticas
- Adicione uma coisa (
#!/usr/bin/env node) para que o arquivo seja executado como um executável - Fornece saída útil –help — O Commander gera a partir de suas descrições
- Lide com erros normalmente – sair com códigos diferentes de zero em caso de falha (
process.exit(1)) - Fornecer feedback claro— giradores, cores e mensagens de sucesso/erro
- Suporte –version— os usuários esperam isso
- Validar entrada— verificar argumentos e mostrar erros úteis
Perguntas frequentes
P: Commander ou yargs para análise de argumentos?
R: Ambos são excelentes. O Commander tem uma API limpa e encadeada e é muito popular. Yargs é poderoso com mais recursos integrados, Commander é um ótimo padrão. Experimente os dois e escolha o que parece natural.
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.#!/usr/bin/env nodeQ: How do I handle configuration files?binA: Read config from a file (
, 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.myclircBuilding a CLI A ferramenta com Node.js é direta e gratificante. Use
Commander para análise de argumentos, Chalk para saída colorida, Inquirer para prompts interativos e Ora para spinners
, em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores.
, em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores.
, em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores., em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores., em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores.bin, em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores.npm link, em seguida, publique no npm para que qualquer pessoa possa instalá-lo com um comando. uma das coisas mais práticas que você pode construir — eles automatizam seus fluxos de trabalho e, quando publicados, também ajudam outros desenvolvedores.
🔗 Share this article
✍️ Leave a Comment