Para criar um CLI de consulta de CPF em Go com Cobra, estruture o projeto com subcomandos separados para consulta via API, validação algorítmica local e processamento em lote — compilando para um binário estático distribuível em Linux, macOS e Windows. A biblioteca Cobra, a mesma usada no kubectl e no Docker CLI, oferece flags globais, autocomplete e output em múltiplos formatos com poucas linhas de configuração.
Introdução
Ferramentas de linha de comando (CLI) são essenciais para automação, scripts e operações de suporte. Uma CLI de consulta de CPF permite que desenvolvedores e analistas consultem CPFs rapidamente sem precisar de interfaces gráficas ou chamadas manuais à API. O Cobra é a biblioteca mais utilizada para construir CLIs em Go, sendo a mesma usada no kubectl, Docker CLI e Hugo.
Estrutura do projeto
A estrutura segue o padrão recomendado pelo Cobra para projetos CLI.
// Estrutura de diretórios
// cpf-cli/
// cmd/
// root.go
// consultar.go
// lote.go
// validar.go
// internal/
// client/
// cpfhub.go
// formatter/
// output.go
// main.go
// go.mod
| Arquivo | Responsabilidade |
|---|---|
main.go | Ponto de entrada |
cmd/root.go | Comando raiz e flags globais |
cmd/consultar.go | Subcomando para consulta individual |
cmd/lote.go | Subcomando para consulta em lote |
cmd/validar.go | Subcomando para validação algorítmica |
internal/client | Cliente HTTP para a API |
internal/formatter | Formatação de output |
Comando raiz e configuração
O comando raiz define as flags globais e a estrutura base da CLI.
// main.go
package main
import "cpf-cli/cmd"
func main() {
cmd.Execute()
}
// cmd/root.go
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var (
apiKey string
outputFormat string
)
var rootCmd = &cobra.Command{
Use: "cpf-cli",
Short: "Ferramenta de linha de comando para consulta de CPF",
Long: `cpf-cli permite consultar e validar CPFs via API do CPFHub.
Suporta consultas individuais, em lote e validação algoritmica local.`,
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func init() {
rootCmd.PersistentFlags().StringVar(
&apiKey, "api-key", "",
"Chave da API do CPFHub (ou CPFHUB_API_KEY)",
)
rootCmd.PersistentFlags().StringVarP(
&outputFormat, "output", "o", "table",
"Formato de saida: table, json, csv",
)
}
func getAPIKey() string {
if apiKey != "" {
return apiKey
}
return os.Getenv("CPFHUB_API_KEY")
}
Subcomando de consulta individual
O subcomando consultar faz a consulta de um CPF específico via API.
// cmd/consultar.go
package cmd
import (
"encoding/json"
"fmt"
"net/http"
"os"
"regexp"
"text/tabwriter"
"time"
"github.com/spf13/cobra"
)
type APIResponse struct {
Success bool `json:"success"`
Data struct {
CPF string `json:"cpf"`
Name string `json:"name"`
NameUpper string `json:"nameUpper"`
Gender string `json:"gender"`
BirthDate string `json:"birthDate"`
Day int `json:"day"`
Month int `json:"month"`
Year int `json:"year"`
} `json:"data"`
}
var consultarCmd = &cobra.Command{
Use: "consultar [cpf]",
Short: "Consulta um CPF via API do CPFHub",
Args: cobra.ExactArgs(1),
Example: " cpf-cli consultar 123.456.789-01\n cpf-cli consultar 12345678901 -o json",
RunE: func(cmd *cobra.Command, args []string) error {
key := getAPIKey()
if key == "" {
return fmt.Errorf("API key nao configurada. Use --api-key ou CPFHUB_API_KEY")
}
re := regexp.MustCompile(`\D`)
cpf := re.ReplaceAllString(args[0], "")
if len(cpf) != 11 {
return fmt.Errorf("CPF deve conter 11 digitos, recebido: %d", len(cpf))
}
resultado, err := consultarAPI(cpf, key)
if err != nil {
return fmt.Errorf("erro ao consultar API: %w", err)
}
return exibirResultado(resultado)
},
}
func consultarAPI(cpf, apiKey string) (*APIResponse, error) {
url := fmt.Sprintf("https://api.cpfhub.io/cpf/%s", cpf)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("x-api-key", apiKey)
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var resultado APIResponse
if err := json.NewDecoder(resp.Body).Decode(&resultado); err != nil {
return nil, err
}
return &resultado, nil
}
func exibirResultado(resultado *APIResponse) error {
if !resultado.Success {
fmt.Println("CPF nao encontrado na base de dados.")
return nil
}
switch outputFormat {
case "json":
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
return enc.Encode(resultado.Data)
case "csv":
fmt.Printf("cpf,nome,genero,nascimento\n")
fmt.Printf("%s,%s,%s,%s\n",
resultado.Data.CPF,
resultado.Data.Name,
resultado.Data.Gender,
resultado.Data.BirthDate,
)
default: // table
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintln(w, "CAMPO\tVALOR")
fmt.Fprintln(w, "-----\t-----")
fmt.Fprintf(w, "CPF\t%s\n", resultado.Data.CPF)
fmt.Fprintf(w, "Nome\t%s\n", resultado.Data.Name)
fmt.Fprintf(w, "Genero\t%s\n", resultado.Data.Gender)
fmt.Fprintf(w, "Nascimento\t%s\n", resultado.Data.BirthDate)
w.Flush()
}
return nil
}
func init() {
rootCmd.AddCommand(consultarCmd)
}
Subcomando de validação local
O subcomando validar verifica o CPF algoritmicamente sem chamar a API.
// cmd/validar.go
package cmd
import (
"fmt"
"regexp"
"strconv"
"github.com/spf13/cobra"
)
var validarCmd = &cobra.Command{
Use: "validar [cpf]",
Short: "Valida um CPF algoritmicamente (sem consultar API)",
Args: cobra.ExactArgs(1),
Example: " cpf-cli validar 123.456.789-01",
Run: func(cmd *cobra.Command, args []string) {
re := regexp.MustCompile(`\D`)
cpf := re.ReplaceAllString(args[0], "")
if len(cpf) != 11 {
fmt.Printf("INVALIDO: CPF deve conter 11 digitos (recebido %d)\n", len(cpf))
return
}
if validarDigitosCPF(cpf) {
fmt.Printf("VALIDO: CPF %s possui digitos verificadores corretos\n", formatarCPF(cpf))
} else {
fmt.Printf("INVALIDO: CPF %s possui digitos verificadores incorretos\n", formatarCPF(cpf))
}
},
}
func validarDigitosCPF(cpf string) bool {
todosIguais := true
for i := 1; i < 11; i++ {
if cpf[i] != cpf[0] {
todosIguais = false
break
}
}
if todosIguais {
return false
}
soma := 0
for i := 0; i < 9; i++ {
d, _ := strconv.Atoi(string(cpf[i]))
soma += d * (10 - i)
}
resto := (soma * 10) % 11
if resto == 10 {
resto = 0
}
d9, _ := strconv.Atoi(string(cpf[9]))
if resto != d9 {
return false
}
soma = 0
for i := 0; i < 10; i++ {
d, _ := strconv.Atoi(string(cpf[i]))
soma += d * (11 - i)
}
resto = (soma * 10) % 11
if resto == 10 {
resto = 0
}
d10, _ := strconv.Atoi(string(cpf[10]))
return resto == d10
}
func formatarCPF(cpf string) string {
return fmt.Sprintf("%s.%s.%s-%s", cpf[0:3], cpf[3:6], cpf[6:9], cpf[9:11])
}
func init() {
rootCmd.AddCommand(validarCmd)
}
| Subcomando | Uso | Requer API Key |
|---|---|---|
consultar | Consulta CPF via API | Sim |
validar | Validação algorítmica local | Não |
lote | Consulta múltiplos CPFs | Sim |
Build e distribuição
Compile a CLI para múltiplas plataformas usando o sistema de build do Go.
// Makefile
// build:
// GOOS=linux GOARCH=amd64 go build -o bin/cpf-cli-linux-amd64 .
// GOOS=darwin GOARCH=amd64 go build -o bin/cpf-cli-darwin-amd64 .
// GOOS=darwin GOARCH=arm64 go build -o bin/cpf-cli-darwin-arm64 .
// GOOS=windows GOARCH=amd64 go build -o bin/cpf-cli-windows-amd64.exe .
| Plataforma | Binário | Tamanho Aproximado |
|---|---|---|
| Linux AMD64 | cpf-cli-linux-amd64 | ~8MB |
| macOS AMD64 | cpf-cli-darwin-amd64 | ~8MB |
| macOS ARM64 | cpf-cli-darwin-arm64 | ~8MB |
| Windows AMD64 | cpf-cli-windows-amd64.exe | ~8MB |
Perguntas frequentes
Quais dependências externas são necessárias para construir o CLI?
O projeto depende de duas bibliotecas: github.com/spf13/cobra para a estrutura do CLI e a biblioteca padrão do Go para as chamadas HTTP. Não há dependências de terceiros para networking — o net/http nativo do Go é suficiente para consumir a API da CPFHub.io com timeout configurável.
A CLI funciona sem conexão à internet?
O subcomando validar funciona completamente offline, pois executa apenas a validação algorítmica dos dígitos verificadores do CPF. Já o subcomando consultar requer conexão com a internet para acessar https://api.cpfhub.io/cpf/{CPF} e retornar nome, gênero e data de nascimento do titular.
Como distribuir a CLI para uma equipe sem Go instalado?
O Go compila para binários estáticos sem dependências de runtime. Basta compilar para cada plataforma alvo (GOOS/GOARCH) e distribuir o executável diretamente — sem precisar instalar Go, Docker ou qualquer runtime adicional nas máquinas dos usuários.
Como proteger a chave de API ao usar a CLI em scripts de CI/CD?
Prefira a variável de ambiente CPFHUB_API_KEY em vez da flag --api-key para evitar que a chave apareça nos logs do terminal. Em pipelines de CI, use secrets gerenciados pela plataforma (GitHub Actions Secrets, GitLab CI Variables etc.) e injete como variável de ambiente. Consulte as boas práticas de segurança da OWASP para proteção de credenciais em APIs.
Conclusão
Uma CLI de consulta de CPF construída com Go e Cobra é uma ferramenta poderosa para desenvolvedores, analistas e equipes de suporte. Com subcomandos claros, múltiplos formatos de saída e distribuição como binário estático, a ferramenta é portável e fácil de integrar em scripts de automação. A validação algorítmica local funciona sem API, enquanto a consulta via API retorna dados completos do titular.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a construir sua CLI de consulta de CPF com dados reais hoje mesmo.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



