O que Ferramentas CLI faz?
Regras
- Commander.js para análise de argumentos —
.command(), .option(), .argument() com descrições
- Prompts interativos:
@clack/prompts (moderno, bonito) ou inquirer — para entrada do usuário quando argumentos não são fornecidos
- Spinners:
ora para operações longas — iniciar, atualizar mensagem, sucesso/erro
- Cores:
chalk para saída estilizada — use com moderação: vermelho para erros, verde para sucesso, amarelo para avisos, cinza para informações secundárias
- Arquivos de configuração:
cosmiconfig — busca automaticamente por .toolrc, .toolrc.json, tool.config.js, chave em package.json
- Códigos de saída:
0 para sucesso, 1 para erro geral, 2 para erro de uso — sempre use process.exit(código)
- Flags
--help e --version: Commander as adiciona automaticamente — escreva descrições claras para cada opção
- Tratamento de erros: capture erros no nível mais alto, exiba mensagem amigável no stderr, saia com código 1
- Publicação: campo
bin no package.json, shebang #!/usr/bin/env node, "type": "module" para ESM
Padrões
#!/usr/bin/env node
import { Command } from "commander";
import * as p from "@clack/prompts";
import ora from "ora";
import chalk from "chalk";
const program = new Command()
.name("my-tool")
.description("Uma CLI que faz coisas úteis")
.version("1.0.0");
program
.command("init")
.description("Inicializar um novo projeto")
.option("-t, --template <nome>", "template a ser usado", "default")
.action(async (options) => {
p.intro(chalk.bold("Configuração do Projeto"));
const name = await p.text({ message: "Nome do projeto?", placeholder: "my-app" });
if (p.isCancel(name)) { p.cancel("Cancelado."); process.exit(0); }
const spinner = ora("Criando projeto...").start();
await createProject(name, options.template);
spinner.succeed(chalk.green("Projeto criado!"));
p.outro(`Execute ${chalk.cyan(`cd ${name} && npm install`)}`);
});
program.parse();
Evitar
- Imprimir erros no stdout — use
console.error() ou process.stderr.write() para erros
- Sair sem código ao falhar — sempre use
process.exit(1) para que scripts e CI detectem a falha
- Paredes de texto sem formatação — use cores do chalk, seções e espaçamento para legibilidade
- Exigir entrada interativa sem alternativa via flag — sempre suporte sobrecarga com
--flag para CI/scripts
- Esquecer o shebang
#!/usr/bin/env node — sem ele, npx e instalações globais não funcionarão