🌐 Detecting your location…

Como construir uma ferramenta CLI com Node.js em 2026: guia completo

⏱️6 min read  ·  1,104 words

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.

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.

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা