Sistema de Categorias e Subcategorias Aninhadas¶
📋 Visão Geral¶
O CLI suporta uma estrutura hierárquica de categorias e subcategorias baseada em diretórios, permitindo organizar comandos em múltiplos níveis de profundidade.
📖 Pré-requisito: Este guia assume que você já conhece os conceitos básicos de estrutura de comandos e criação de scripts. Se não, veja primeiro Como Adicionar Novos Comandos.
🏗️ Estrutura de Diretórios¶
Diferença entre Comandos e Subcategorias¶
🔑 Regra Fundamental: A existência do script executável determina o comportamento!
O sistema verifica:
- Se o diretório tem arquivo de configuração (command.json ou category.json)
- Se o
command.jsontem o campoentrypoint:definido - Se o arquivo do script existe
Resultado:
- Tem
entrypoint:E arquivo existe → É um comando executável - Sistema executa o script
-
Aparece na seção "Commands"
-
Não tem
entrypoint:OU arquivo não existe → É uma subcategoria navegável - Sistema permite navegar (listar sub-itens)
- Aparece na seção "Subcategories"
Arquivos de Configuração Diferenciados¶
Tanto comandos quanto categorias usam arquivos de configuração, mas com campos diferentes:
| Tipo | Campos de configuração |
|---|---|
| Comando (command.json) | name, description, entrypoint (obrigatório), sudo, os |
| Categoria/Subcategoria (category.json) | name, description, entrypoint (opcional) |
ℹ️ Para detalhes completos sobre campos de configuração, veja Configuração de Comandos.
Vantagens dessa abordagem:
- ✅ Mais intuitivo: "tem script = é executável"
- ✅ Mais consistente: categorias usam category.json e comandos usam command.json
- ✅ Mais lógico: comandos PRECISAM de script, subcategorias não
- ✅ Categorias podem ter entrypoint para aceitar parâmetros
Estrutura Exemplo¶
commands/
setup/ # Categoria principal
category.json # name, description (sem entrypoint)
asdf/ # Comando direto
command.json # category, id, name, description, script, sudo, os
main.sh # Script executável
python/ # Subcategoria
command.json # name, description (sem script)
pip/ # Comando
command.json # category, id, name, description, script
main.sh
poetry/ # Comando
command.json
main.sh
tools/ # Sub-subcategoria (nível 3)
command.json # name, description (sem script)
venv/ # Comando nível 3
command.json # category, id, name, description, entrypoint
main.sh
nodejs/ # Subcategoria
command.json # name, description (sem script)
npm/ # Comando
command.json # category, id, name, description, script
main.sh
🎯 Navegação¶
Comandos de Navegação¶
# Listar categorias principais
susa
# Listar subcategorias e comandos de uma categoria
susa setup
# Navegar para uma subcategoria
susa setup python
# Navegar para sub-subcategoria (nível 3)
susa setup python tools
# Executar comando direto
susa setup asdf
# Executar comando em subcategoria
susa setup python pip
# Executar comando em sub-subcategoria
susa setup python tools venv
📝 Arquivos de Configuração¶
Arquivos de Configuração¶
Categorias e subcategorias usam category.json, enquanto comandos usam command.json.
A diferença está nos campos definidos.
1. Categoria/Subcategoria (Navegável)¶
Usado para itens que contêm outros itens.
Localização: commands/{categoria}/category.json ou commands/{categoria}/{subcategoria}/command.json
2. Comando (Executável)¶
Configuração completa de um comando executável.
{
"name": "Pip",
"description": "Instala gerenciador de pacotes Python (pip)",
"entrypoint": "main.sh",
"sudo": false,
"os": ["linux", "mac"]
}
Localização: commands/{categoria}/.../{comando}/command.json
Importante: O arquivo definido em entrypoint: DEVE existir e ter permissão de execução.
✨ Campos de Configuração¶
📖 Referência completa: Veja Configuração de Comandos para detalhes sobre todos os campos disponíveis.
Resumo Rápido¶
Para Comandos (Executáveis):
- Devem ter o campo
entrypoint:apontando para um arquivo executável - Exemplo:
entrypoint: "main.sh"
Para Subcategorias (Navegáveis):
- NÃO devem ter o campo
entrypoint - Apenas
nameedescription
Lista de Categoria com Subcategorias¶
Instalar software (Ubuntu)
Usage: susa setup <command> [options]
Subcategories:
nodejs Ferramentas Node.js
python Ferramentas Python
Commands:
asdf Instala ASDF Version Manager
Lista de Subcategoria¶
Ferramentas Python
Usage: susa setup/python <command> [options]
Subcategories:
tools Ferramentas Python Avançadas
Commands:
pip Instala gerenciador de pacotes Python (pip)
poetry Instala Poetry (gerenciador de dependências Python)
🚀 Como Adicionar Comandos em Hierarquias¶
📖 Para criar comandos simples, veja Como Adicionar Novos Comandos. Esta seção foca em estruturas hierárquicas com subcategorias.
1. Comando em Categoria Existente¶
Veja guia básico para detalhes.
Resumo:
mkdir -p commands/setup/comando-novo
# Criar arquivos de configuração e main.sh conforme guia básico
2. Comando em Nova Subcategoria¶
A diferença principal: criar um category.json sem campo entrypoint para a subcategoria.
# Criar estrutura
mkdir -p commands/install/nova-categoria/comando-xyz
# Criar configuração da subcategoria (SEM campo 'script')
cat > commands/install/nova-categoria/category.json << EOF
name: "Nova Categoria"
description: "Descrição da nova categoria"
# Sem campo 'script' = subcategoria navegável
EOF
# Criar configuração do comando (COM campo 'script')
cat > commands/install/nova-categoria/comando-xyz/command.json << EOF
name: "Comando XYZ"
description: "Descrição do comando XYZ"
entrypoint: "main.sh" # ← Indica que é executável
sudo: false
EOF
# Criar script
cat > commands/install/nova-categoria/comando-xyz/main.sh << 'EOF'
#!/bin/bash
echo "Executando XYZ!"
EOF
# Tornar executável
chmod +x commands/setup/nova-categoria/comando-xyz/main.sh
Uso: ./susa setup nova-categoria comando-xyz
3. Comando em Sub-Subcategoria (3 níveis)¶
# Criar estrutura completa
mkdir -p commands/install/categoria/subcategoria/comando
# Criar arquivos de configuração para cada nível navegável
cat > commands/install/categoria/category.json << EOF
name: "Categoria"
description: "Nível 1"
EOF
cat > commands/install/categoria/subcategoria/category.json << EOF
name: "Subcategoria"
description: "Nível 2"
EOF
# Criar comando executável (COM campo 'script')
cat > commands/install/categoria/subcategoria/comando/command.json << EOF
name: "Comando"
description: "Comando no nível 3"
entrypoint: "main.sh" # ← Indica que é executável
sudo: false
EOF
cat > commands/install/categoria/subcategoria/comando/main.sh << 'EOF'
#!/bin/bash
echo "Comando profundo!"
EOF
chmod +x commands/setup/categoria/subcategoria/comando/main.sh
Uso: ./susa setup categoria subcategoria comando
🔍 Descoberta Automática¶
O sistema descobre automaticamente:
- ✅ Todas as categorias em
commands/ - ✅ Todas as subcategorias (diretórios com
category.json) - ✅ Todos os comandos (diretórios com
command.jsone campoentrypoint) - ✅ Múltiplos níveis de aninhamento
- ✅ Comandos em plugins externos
Não é necessário registrar manualmente categorias ou comandos em arquivos centrais.
📦 Plugins¶
Plugins também suportam a mesma estrutura hierárquica com subcategorias aninhadas:
plugins/
dev-tools/ # Plugin
deploy/ # Categoria
command.json # name, description (sem script)
staging/ # Comando
command.json # name, description, script
main.sh
production/ # Comando
command.json
main.sh
aws/ # Subcategoria
command.json # name, description (sem script)
ec2/ # Comando
command.json # name, description, entrypoint
main.sh
lambda/ # Comando
category.json
main.sh
test/ # Categoria
command.json
unit/ # Comando
command.json
main.sh
integration/ # Comando
command.json
main.sh
Navegação em Plugins¶
# Listar categorias do plugin
./susa deploy # Mostra: staging, production, aws (subcategoria)
# Navegar para subcategoria
./susa deploy aws # Mostra: ec2, lambda
# Executar comando em subcategoria
./susa deploy aws ec2 # Executa deploy EC2
# Outro exemplo
./susa test # Mostra: unit, integration
./susa test unit # Executa testes unitários
Importante sobre Plugins¶
✅ Plugins funcionam exatamente como commands/:
- Mesma lógica de detecção (script = comando, sem script = subcategoria)
- Mesma estrutura de arquivos de configuração (command.json/category.json)
- Mesma navegação multinível
- Mesma descoberta automática
Diferenças:
- Diretório:
plugins/{nome-plugin}/ao invés decommands/ - Comandos de plugins exibem o indicador
[plugin]na listagem
Exemplo de listagem com plugins:
Commands:
asdf Instala ASDF Version Manager
staging Deploy para staging [plugin]
production Deploy produção (requer sudo) [plugin] [sudo]
🎨 Categorias com Parâmetros (Feature Avançada)¶
Visão Geral¶
Categorias podem ter um entrypoint opcional que permite aceitar parâmetros diretamente, sem precisar criar comandos individuais. Isso é útil para operações em massa ou ações que afetam todos os comandos da categoria.
Como Funciona¶
Quando uma categoria tem um entrypoint:
- Sem parâmetros (
susa setup): Lista comandos normalmente + mostra help complementar - Com parâmetros (
susa setup --upgrade): Executa o script da categoria - Comandos específicos (
susa setup docker): Funciona normalmente
Configuração da Categoria¶
category.json com entrypoint:
{
"name": "Setup",
"description": "Instalação e atualização de softwares e ferramentas",
"entrypoint": "main.sh"
}
Script da Categoria (main.sh)¶
O script deve implementar a função show_complement_help() para exibir ajuda adicional:
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# Source libraries
source "$LIB_DIR/logger.sh"
source "$LIB_DIR/color.sh"
# Show complement help (exibida ao final da listagem de comandos)
show_complement_help() {
echo ""
log_output "${LIGHT_GREEN}Opções da categoria:${NC}"
log_output " -u, --upgrade Atualiza todos os softwares instalados"
log_output " --list Lista todos os softwares instalados"
}
upgrade_all() {
# criar logica
}
list_installed() {
# criar logica
}
# Main function
main() {
while [[ $# -gt 0 ]]; do
case "$1" in
-u|--upgrade)
upgrade_all
exit 0
;;
--list)
list_installed
exit 0
;;
*)
log_error "Opção desconhecida: $1"
echo ""
log_output "Use ${LIGHT_CYAN}susa setup --help${NC} para ver as opções"
exit 1
;;
esac
done
}
# Execute main (controlado por SUSA_SKIP_MAIN)
if [ "${SUSA_SKIP_MAIN:-}" != "1" ]; then
main "$@"
fi
Importante sobre SUSA_SKIP_MAIN¶
A variável SUSA_SKIP_MAIN é usada pelo sistema para evitar execução do main quando apenas quer chamar show_complement_help:
# Sempre adicione esta condição no final do script
if [ "${SUSA_SKIP_MAIN:-}" != "1" ]; then
main "$@"
fi
Isso permite que o sistema:
- Execute o script normalmente quando o usuário passa parâmetros
- Apenas source o script e chame
show_complement_help()ao listar comandos
Exemplo de Uso¶
# Lista comandos + mostra help complementar ao final
$ susa setup
Instalação e atualização de softwares e ferramentas
Uso: susa <comando> setup
Comandos:
docker Instala Docker
poetry Instala Poetry
uv Instala UV
Opções da categoria:
-u, --upgrade Atualiza todos os softwares instalados
--list Lista todos os softwares instalados
# Executa ação em massa
$ susa setup --upgrade
[INFO] Atualizando softwares instalados...
[INFO] Atualizando docker...
[SUCCESS] Docker atualizado!
...
# Lista softwares instalados
$ susa setup --list
[INFO] Softwares instalados (categoria setup):
docker v24.0.7
poetry v1.7.1
uv v0.1.9
# Comando específico funciona normalmente
$ susa setup docker
[INFO] Instalando Docker...
Quando Usar Entrypoints em Categorias¶
✅ Bons casos de uso:
- Operações em massa (atualizar todos, listar todos)
- Ações que afetam múltiplos comandos da categoria
- Parâmetros comuns que se aplicam a toda categoria
- Help complementar com informações da categoria
❌ Evite usar para:
- Comandos individuais (use comandos normais)
- Lógica complexa que deveria ser um comando próprio
- Categorias que são apenas contêineres de navegação
Estrutura de Exemplo Completa¶
commands/
setup/
category.json # ← Com entrypoint
main.sh # ← Script da categoria
docker/
command.json
main.sh
poetry/
command.json
main.sh
category.json:
{
"name": "Setup",
"description": "Instalação e atualização de softwares",
"entrypoint": "main.sh"
}
⚙️ Filtros de Sistema Operacional e Sudo¶
📖 Referência completa: Veja Configuração de Comandos para detalhes sobre os campos
osesudo.
Resumo:
- Use o campo
os: ["linux", "mac"]para restringir sistemas - Use
sudo: truepara comandos que requerem privilégios elevados - Comandos com
sudo: trueexibem o indicador[sudo]na listagem
Exemplo de exibição:
📊 Agrupamento de Comandos¶
Comandos podem ser agrupados para melhor organização:
// commands/install/tool1/command.json
{
"group": "Development Tools"
}
// commands/install/tool2/command.json
{
"group": "Development Tools"
}
Exibição:
Commands:
standalone-cmd Comando sem grupo
Development Tools
tool1 Primeira ferramenta
tool2 Segunda ferramenta
🎯 Boas Práticas¶
Nomenclatura¶
- Diretórios: Use kebab-case:
install-python,backup-tools - Nomes (config): Use formato legível:
"Install Python","Backup Tools" - Scripts: Sempre
main.sh(ou o nome definido ementrypoint:)
Organização¶
- Categorias principais → Grandes áreas funcionais (
install,daily,backup) - Subcategorias → Agrupamento lógico (
python,nodejs,docker) - Comandos → Ações específicas (
pip,poetry,npm)
Hierarquia Recomendada¶
✅ Boa hierarquia:
commands/install/python/pip
commands/install/python/poetry
commands/install/nodejs/npm
❌ Hierarquia excessiva:
commands/tools/dev/lang/python/pkg/pip
(muito profunda, evite mais de 3 níveis)
🐛 Troubleshooting¶
Comando não aparece na listagem¶
1:** Falta campo entrypoint: no command.json
Solução: Adicionar o campo script
Causa 2: Arquivo do script não existe ou não tem o nome correto
Solução: Verificar se o arquivo existe e corresponde ao nome em entrypoint:
Causa 3: Incompatível com o sistema operacional atual
Solução: Verificar campo os: no command.json
Subcategoria aparece como comando (não consigo navegar)¶
Causa: command.json tem campo entrypoint: definido e o arquivo existe
Explicação: O sistema identifica como comando executável pela presença do script.
Soluç 1: Script não está executável
Solução:
Causa 2: Nome do script no command.json não corresponde ao arquivo
Solução: Verificar se entrypoint: aponta para o arquivo correto
Causa 3: Script não existe
Solução: Criar o arquivo do script
Descrição não aparece¶
Causa: Falta campo description: no command.json
Solução: Adicionar descrição
Descrição da subcategoria não aparece¶
Causa: Falta arquivo de configuração (command.json ou category.json) ou está sem campos obrigatórios
Solução: Criar category.json com name e description (SEM campo entrypoint)
📚 Exemplos Completos¶
📖 Para exemplos de comandos simples, veja Exemplo Completo no guia básico.
Exemplo: Hierarquia com Subcategorias (Foco deste guia)¶
# Estrutura
mkdir -p commands/backup/{local,cloud}/{full,incremental}
# Subcategoria: backup/local (SEM campo 'script')
cat > commands/backup/local/command.json << EOF
name: "Local"
description: "Backups locais"
EOF
# Comando: backup/local/full (COM campo 'script')
cat > commands/backup/local/full/command.json << EOF
name: "Full Backup"
description: "Backup completo local"
entrypoint: "main.sh"
sudo: false
EOF
cat > commands/backup/local/full/main.sh << 'EOF'
#!/bin/bash
echo "Executando backup completo local..."
tar -czf /tmp/backup-$(date +%Y%m%d).tar.gz /home/$USER/Documents
echo "✅ Backup concluído!"
EOF
chmod +x commands/backup/local/full/main.sh
Uso:
./susa backup→ Listalocalecloudcomo subcategorias./susa backup local→ Listafulleincrementalcomo comandos./susa backup local full→ Executa o backup
Exemplo 3: Plugin com Subcategorias Aninhadas¶
# Estrutura completa para plugin dev-tools
mkdir -p plugins/dev-tools/deploy/{staging,production,aws/{ec2,lambda}}
mkdir -p plugins/dev-tools/test/{unit,integration}
# Categoria: deploy (SEM script)
cat > plugins/dev-tools/deploy/category.json << EOF
name: "Deploy"
description: "Ferramentas de deployment"
EOF
# Comando: deploy/staging
cat > plugins/dev-tools/deploy/staging/command.json << EOF
name: "Staging"
description: "Deploy para ambiente de staging"
entrypoint: "main.sh"
EOF
cat > plugins/dev-tools/deploy/staging/main.sh << 'EOF'
#!/bin/bash
echo "🚀 Deploy para Staging..."
echo "✅ Deploy concluído!"
EOF
# Subcategoria: deploy/aws (SEM script)
cat > plugins/dev-tools/deploy/aws/command.json << EOF
name: "AWS"
description: "Deploy para serviços AWS"
EOF
# Comando em subcategoria: deploy/aws/ec2
cat > plugins/dev-tools/deploy/aws/ec2/command.json << EOF
name: "EC2"
description: "Deploy para instâncias EC2"
entrypoint: "main.sh"
EOF
cat > plugins/dev-tools/deploy/aws/ec2/main.sh << 'EOF'
#!/bin/bash
echo "☁️ Deploy para AWS EC2..."
echo "✅ Deploy EC2 concluído!"
EOF
# Tornar scripts executáveis
chmod +x plugins/dev-tools/deploy/staging/main.sh
chmod +x plugins/dev-tools/deploy/aws/ec2/main.sh
Uso:
./susa deploy→ Listastaging,production,aws(subcategoria)./susa deploy staging→ Executa deploy staging./susa deploy aws→ Listaec2,lambda./susa deploy aws ec2→ Executa deploy EC2
🔗 Guias Relacionados¶
- Como Adicionar Novos Comandos - Guia fundamental para criar comandos simples
- Referência de Bibliotecas - Bibliotecas disponíveis para usar em seus scripts
- Plugins - Sistema de plugins que suporta a mesma estrutura hierárquica