Guia Completo de Construção de CLI

Neste artigo, vou abordar um guia completo de como construir uma CLI (Command Line Interface) profissional, que seja fácil de usar e, principalmente, fácil de ser integrada por outras aplicações. Se você nunca construiu uma CLI antes, não se preocupe — vamos começar do zero.

O que é uma CLI?

CLI significa Command Line Interface (Interface de Linha de Comando). É aquele programa que você usa digitando comandos no terminal, como git, npm, docker, pip, entre outros. Diferente de programas com interface gráfica (GUI), CLIs são controladas por texto, o que as torna extremamente poderosas, automatizáveis e fáceis de integrar com outros sistemas.

Entendendo o ARGV

Antes de mais nada, você precisa entender o que é o argv. A resposta é simples: argv é um array de strings que contém os argumentos passados para o programa. Tudo que foi digitado no terminal é separado por espaços e transformado nesse array.

  • argv[0] → nome do programa (ou do runtime + script)
  • argv[1] → primeiro argumento
  • argv[2] → segundo argumento
  • E assim por diante…

Como o argv funciona em diferentes linguagens

Em linguagens interpretadas (como Python), o argv[0] é o nome do seu script, e os argumentos começam a partir de argv[1].

Em linguagens compiladas (como C, C++, Go, Rust), o argv[0] é o nome do executável compilado.

Exemplo em Python

import sys
print(sys.argv)

Execute:

python3 script.py arg1 arg2 arg3

Saída:

['script.py', 'arg1', 'arg2', 'arg3']

Exemplo em C

#include <stdio.h>

int main(int argc, char *argv[]) {
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}

Compile e execute:

gcc programa.c -o programa
./programa arg1 arg2 arg3

Saída:

argv[0] = ./programa
argv[1] = arg1
argv[2] = arg2
argv[3] = arg3

Construindo a Sua CLI

Para construir uma CLI sólida e profissional, siga os passos abaixo:

1. Defina as Actions (Ações)

O primeiro argumento (após o nome do programa) deve ser a action, ou seja, a ação que o usuário deseja executar.

meu_programa <action> [flags e argumentos]

Vamos usar o git como exemplo. Ele possui várias actions como commit, pull, push, rebase, etc. Veja o comando abaixo:

git commit -m "mensagem do commit"

Nesse exemplo: - commit → é a action - -m → é uma flag - "mensagem do commit" → é o valor da flag

Dica para iniciantes: Pense na action como uma função, e nas flags como os parâmetros dessa função.

Como implementar actions

A forma mais simples de implementar actions é usar uma estrutura condicional para verificar o primeiro argumento:

Exemplo em Python:

import sys

def action_hello():
    print("Olá! Bem-vindo à minha CLI!")

def action_version():
    print("meu_programa v1.0.0")

if len(sys.argv) < 2:
    print("Uso: meu_programa <action>")
    print("Use 'meu_programa help' para ver as ações disponíveis.")
    sys.exit(1)

action = sys.argv[1]

if action == "hello":
    action_hello()
elif action == "version":
    action_version()
else:
    print(f"Ação desconhecida: {action}")
    print("Use 'meu_programa help' para ver as ações disponíveis.")

2. Defina as Flags

Agora que você separou cada ação possível da sua CLI, você deve definir as flags que cada action pode receber. Flags modificam o comportamento de uma action.

Existem dois tipos de flags:

Boolean Flags (flags sem valor)

São flags que não recebem valor — apenas indicam que algo deve ser ativado. Geralmente começam com --.

git push --force

Aqui, --force é uma flag booleana que indica que o push deve ser forçado.

Value Flags (flags com valor)

São flags que recebem um valor logo em seguida. Podem usar - (forma curta) ou -- (forma longa).

git commit -m "mensagem do commit"
git commit --message "mensagem do commit"

Aqui, -m (ou --message) é uma flag que recebe a mensagem como valor.

Como implementar flags

Exemplo em Python:

import sys

def parse_flags(args):
    """Analisa os argumentos e retorna um dicionário de flags."""
    flags = {}
    i = 0
    while i < len(args):
        if args[i].startswith("--"):
            flag_name = args[i][2:]  # Remove o prefixo --
            # Verifica se é uma boolean flag ou uma value flag
            if i + 1 < len(args) and not args[i + 1].startswith("-"):
                flags[flag_name] = args[i + 1]
                i += 2
            else:
                flags[flag_name] = True
                i += 1
        elif args[i].startswith("-"):
            flag_name = args[i][1:]  # Remove o prefixo -
            if i + 1 < len(args) and not args[i + 1].startswith("-"):
                flags[flag_name] = args[i + 1]
                i += 2
            else:
                flags[flag_name] = True
                i += 1
        else:
            i += 1
    return flags

# Exemplo de uso:
# meu_programa commit -m "mensagem" --force
action = sys.argv[1]
flags = parse_flags(sys.argv[2:])
print(f"Action: {action}")
print(f"Flags: {flags}")

3. Defina um Help (Ajuda)

Todo programa de linha de comando precisa de uma ação help. Ela deve listar todas as ações e flags disponíveis, com uma descrição clara de cada uma.

meu_programa help

Exemplo de saída:

meu_programa - Uma ferramenta incrível para gerenciar tarefas

Uso: meu_programa <action> [flags]

Ações disponíveis:
  help                Mostra esta mensagem de ajuda
  version             Mostra a versão do programa
  add                 Adiciona uma nova tarefa
    --title <texto>     Título da tarefa (obrigatório)
    --priority <n>      Prioridade de 1 a 5 (padrão: 3)
  list                Lista todas as tarefas
    --filter <status>   Filtra por status (pendente, concluída)
    --limit <n>         Limita o número de resultados
  done                Marca uma tarefa como concluída
    --id <id>           ID da tarefa (obrigatório)

Exemplos:
  meu_programa add --title "Comprar café" --priority 1
  meu_programa list --filter pendente
  meu_programa done --id 42

Dica: Sempre inclua exemplos práticos no help. Isso ajuda muito os iniciantes.

4. Defina um Version (Versão)

Crie uma action chamada version que mostra a versão atual da sua CLI. Isso é essencial para debugging e para que os usuários saibam qual versão estão usando.

meu_programa version

Exemplo de saída:

meu_programa v1.0.0

Dica: Siga o padrão Semantic Versioning (SemVer) para numerar suas versões: MAJOR.MINOR.PATCH (ex: 1.2.3).

5. Defina Stored Configs (Configurações Armazenadas)

Muitas vezes é conveniente que sua CLI armazene configurações do usuário para que ele não precise digitá-las toda vez. Isso é muito comum — pense no git config ou no npm config.

Exemplo:

meu_programa config-user --username "Mateus" --email "mateus@gmail.com" --password "senha"

Depois de configurado, nas próximas ações você pode exigir apenas a flag identificadora:

meu_programa set-profile-picture --username "Mateus" --picture foto.png

Onde armazenar as configurações?

É fortemente recomendado que você salve todos os dados em um único local, de preferência em uma pasta oculta na home do usuário (diretórios que começam com . são ocultos no Linux/macOS).

Exemplo: as configurações poderiam ser salvas no arquivo ~/.meu_programa/config.json:

{
    "username": "Mateus",
    "email": "mateus@gmail.com",
    "password": "teste"
}

Formas comuns de armazenamento: - JSON → simples e amplamente suportado - SQLite → ideal para dados mais complexos ou relacionais - TOML/YAML → bom para arquivos de configuração legíveis - Arquivos de texto → para dados muito simples

6. Tratamento de Erros

Uma CLI profissional deve tratar erros de forma clara e amigável. Nunca deixe o programa “quebrar” com um erro incompreensível.

Boas práticas:

import sys

if len(sys.argv) < 2:
    print("Erro: nenhuma ação fornecida.")
    print("Uso: meu_programa <action> [flags]")
    print("Use 'meu_programa help' para mais informações.")
    sys.exit(1)

Dicas para bons erros: - Diga o que deu errado - Diga por que deu errado (se possível) - Sugira como corrigir

Exemplo:

Erro: a flag --title é obrigatória para a ação 'add'.
Uso: meu_programa add --title "Minha tarefa"

7. Códigos de Saída (Exit Codes)

Programas de linha de comando comunicam sucesso ou falha através de códigos de saída. Isso é fundamental para que outros programas e scripts consigam saber se sua CLI executou corretamente.

  • Código 0sucesso
  • Código 1 ou superior → erro
import sys

# Sucesso
sys.exit(0)

# Erro genérico
sys.exit(1)

Isso permite que outros programas usem sua CLI assim:

meu_programa add --title "Tarefa" && echo "Sucesso!" || echo "Falhou!"

8. Saída Estruturada (Output para Outras Aplicações)

Se sua CLI pode ser utilizada por outros programas (e ela deveria!), considere oferecer saída em formatos estruturados como JSON.

meu_programa list --output json

Saída normal (para humanos):

ID  | Título          | Status
1   | Comprar café    | pendente
2   | Estudar CLI     | concluída

Saída JSON (para programas):

[
    {"id": 1, "titulo": "Comprar café", "status": "pendente"},
    {"id": 2, "titulo": "Estudar CLI", "status": "concluída"}
]

Isso torna sua CLI facilmente integrável com outros sistemas, scripts e pipelines.

Dicas Extras

  1. Nunca misture padrões de nomenclatura. Se uma action se chama set-profile-picture (separando por -), use o mesmo padrão em todas as actions. Isso facilita a legibilidade e a intuição de uso.

  2. Se as informações forem sensíveis, criptografe-as. Nunca armazene senhas em texto puro. Use alguma forma de criptografia e exija a senha de descriptografia como argumento ou configuração armazenada.

  3. Adicione cores ao output. Cores tornam a saída muito mais legível. Por exemplo, erros em vermelho, sucesso em verde, avisos em amarelo. Na maioria das linguagens existe bibliotecas para isso (como colorama em Python ou chalk em Node.js).

  4. Suporte auto-complete. Se possível, permita que o usuário configure auto-complete no shell (Bash, Zsh, Fish). Isso melhora drasticamente a experiência de uso.

  5. Escreva uma boa documentação. Além do help embutido, considere manter um README ou uma página de documentação com exemplos detalhados.

  6. Teste sua CLI. Escreva testes automatizados para cada action e para combinações de flags. Isso evita regressões e garante que tudo funcione como esperado.

Conclusão

Construir uma CLI profissional vai além de apenas ler argumentos do terminal. Envolve pensar na experiência do usuário, na consistência dos comandos, no tratamento de erros e na integrabilidade com outros sistemas. Seguindo os passos deste guia, você terá uma base sólida para criar CLIs que são agradáveis de usar e fáceis de manter.

Lembre-se: uma boa CLI é aquela que o usuário consegue usar sem precisar consultar a documentação a todo momento. Invista em boas mensagens de ajuda, nomes de ações intuitivos e mensagens de erro claras.