Referência: Uma Ferramenta CLI Distribuída para Usuários
Uma referência para ferramentas CLI voltadas para o usuário: clap 4 para parsing, erros estruturados, compilações multiplataforma com cargo-dist e saída --version amigável para suporte com metadados de SHA do git e da toolchain Rust.
Receita
Cartão de referência rápida - pronto para copiar e colar.
acme-cli/
src/
main.rs
cmd/ # subcomandos
error.rs
tests/
cli_integration.rs
dist.toml # manifesto do cargo-dist
CHANGELOG.mdQuando usar isso:
- Distribuição de ferramentas para desenvolvedores ou operadores
- Substituição de scripts bash por Rust tipado
- Clientes corporativos exigem SBOM/binários assinados
Exemplo de Trabalho
use clap::{Parser, Subcommand};
use std::process::ExitCode;
#[derive(Parser)]
#[command(name = "acme", version, about = "CLI do operador Acme")]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Exporta dados do tenant para JSON
Export { tenant_id: String, #[arg(long)] out: std::path::PathBuf },
}
fn main() -> ExitCode {
let cli = Cli::parse();
match run(cli) {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("erro: {e}");
e.exit_code()
}
}
}
fn run(cli: Cli) -> Result<(), AppError> {
match cli.command {
Commands::Export { tenant_id, out } => export(&tenant_id, &out)?,
}
Ok(())
}# release do cargo-dist (simplificado)
cargo dist build --artifacts=archives
cargo dist publish --tag v1.2.0// tests/cli_integration.rs
use assert_cmd::Command;
#[test]
fn export_requires_tenant() {
Command::cargo_bin("acme").unwrap()
.arg("export")
.assert()
.failure();
}Análise Detalhada
Convenções de UX
- Subcomandos em vez de uma sopa de flags para mais de 3 operações.
- Flag de saída JSON estável
--format jsonpara automação. - Progresso no stderr; dados no stdout.
- Documentar códigos de saída: 0 ok, 1 erro do usuário, 2 interno.
Distribuição
- cargo-dist para matriz Linux/macOS/Windows.
- Assinar binários onde a política exige.
- Tap do Homebrew ou receitas de gerenciador de pacotes como canal opcional.
Suporte
acme --version inclui semver, SHA, versão do rustc para correlação de tickets.
Armadilhas
- Quebra de flags CLI sem semver - Scripts quebram. Correção: Depreciar em uma release; bump major na remoção.
- Panics com entrada inválida - Correção:
Resultem todos os lugares emrun(). - Binário enorme - Correção:
strip, LTO, evitar features não utilizadas. - Sem testes de integração - Regressões são enviadas. Correção: Testes de fumaça com
assert_cmdem CI.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| crate xtask | Apenas tarefas de mantenedor do repositório | Produto para o usuário final |
| Wrapper Shell | Caminho de instalação legado | Validação complexa necessária |
| TUI (ratatui) | Operações interativas | Automação de CI principal |
FAQs
MSRV para CLI pública?
Declarar no README; alinhar com LTS corporativo, se aplicável.
Canal de auto-atualização?
Separado da API do servidor; documentar verificação de assinatura.
Suporte ao Windows?
Testar na matriz de CI; casos de borda de caminho e final de linha.
Arquivo de configuração + env?
Overrides de env do clap; documentar precedência em --help.
Telemetria na CLI?
Apenas opt-in; documentar em aviso de privacidade.
Relacionados
- Clap - Parsing de CLI
- Boas Práticas de Ferramentas CLI - padrões
- Gerenciamento de Releases - versionamento
- Segurança da Cadeia de Suprimentos - SBOM
- Boas Práticas de Testes - testes de integração
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4 e Polars 0.46+.