Bruno: a alternativa open source ao Postman que vive no Git

Por que times estão trocando o Postman pelo Bruno: coleções em arquivo de texto versionado, sem conta e sem nuvem. O que ganha, o que perde e como migrar.

Pergunta desconfortável para fazer na próxima reunião de engenharia: onde mora a coleção de requests da sua API? A resposta honesta, em muito time, é “na conta do Postman de alguém”. Não no repositório, não no backup, não em lugar nenhum que a empresa controle. Quando essa pessoa sai, a documentação viva de como chamar o próprio sistema sai junto — e alguém vai reconstruir na mão o payload daquele endpoint de pagamento.

Este texto não é uma lista de dez alternativas ao Postman com nota de zero a cinco. É um argumento sobre um problema específico — coleção de API que não vive junto com o código — e sobre a ferramenta que resolve esse problema por desenho, não por configuração. Se o seu incômodo com o Postman é preço ou telemetria, o raciocínio ajuda; mas o caso forte do Bruno é outro.

Bruno é um cliente de API que guarda cada request como arquivo de texto dentro da pasta do seu projeto, versionado pelo Git, sem conta e sem nuvem obrigatória.

O problema não é o preço, é onde a coleção mora

O Postman é uma ferramenta boa e madura. O que mudou não foi a qualidade dela, foi a arquitetura: a partir da versão 10, o produto passou a girar em torno da conta e do workspace na nuvem. O modo offline mais usado, o Scratch Pad, foi descontinuado — a própria Postman anunciou o fim dele, com corte para novos downloads em 15 de maio de 2023 e fim do modo depreciado em 15 de setembro do mesmo ano, substituído por um cliente leve que atende quem só quer disparar requests.

O efeito colateral disso é organizacional, não técnico. Quando a coleção mora na conta de alguém:

  • Ela não passa por review. Ninguém abre pull request para discutir que o header de autenticação mudou.
  • Ela sai de sincronia com o código. O endpoint foi renomeado na sexta; a coleção ainda tem o nome antigo em março do ano seguinte.
  • Ela é de quem criou, não da empresa. Isso é o mesmo risco de continuidade que descrevo em integrações via API: conhecimento crítico guardado onde a empresa não tem chave.
  • Ela pode carregar segredo. Token de staging colado num environment que sincroniza para um servidor de terceiros é uma decisão de segurança que ninguém tomou conscientemente.

Nenhum desses problemas se resolve pagando mais caro. Eles se resolvem mudando o lugar onde o arquivo fica.

Como o Bruno guarda as coisas

O Bruno grava cada request como um arquivo de texto com extensão .bru, dentro de uma pasta no seu projeto. Uma coleção é um diretório; uma pasta na interface é uma pasta no disco. Não há banco local opaco, não há sincronização, não há login. O repositório oficial do projeto, que passa das 40 mil estrelas no GitHub, descreve exatamente isso: um cliente de API git-native.

Um arquivo .bru se parece com isto:

meta {
  name: Criar pedido
  type: http
}

post {
  url: {{base_url}}/v1/orders
  body: json
}

headers {
  Authorization: Bearer {{token}}
}

body:json {
  {
    "sku": "ABC-123",
    "quantity": 2
  }
}

É legível por humano e, o que importa mais, legível por git diff. Quando alguém muda o corpo da requisição, o pull request mostra a linha que mudou. A coleção deixa de ser um anexo binário e passa a ser código — revisável, com histórico, com autor e com data.

Isso muda um hábito prático: a coleção entra no mesmo repositório do serviço que ela testa. Quem clona o projeto já tem os requests. Quem entra no time na segunda-feira abre a pasta e vê como se chama o sistema, sem pedir convite para workspace nenhum.

Onde colocar a pasta no repositório

A decisão de layout é pequena e define se o padrão pega ou não. O que funciona na prática é a coleção viver na raiz do serviço, ao lado do código que ela exercita:

servico-pedidos/
├── src/
├── api/                    ← a coleção
│   ├── bruno.json
│   ├── environments/
│   │   ├── local.bru
│   │   └── staging.bru     ← só nomes de variável, nunca valores
│   └── pedidos/
│       ├── criar-pedido.bru
│       └── cancelar-pedido.bru
└── .gitignore

Duas regras que evitam quase toda dor de cabeça depois. Primeira: uma coleção por serviço, não uma coleção monolítica da empresa inteira — coleção compartilhada entre times vira o mesmo gargalo de sempre, com conflito de merge em arquivo que ninguém é dono. Segunda: o nome do arquivo é o nome do request, em kebab-case, porque é assim que ele vai aparecer no diff. Quem revisa o pull request lê “criar-pedido.bru” e já sabe o que olhar.

Licença: o que exatamente é gratuito

Vale ser específico, porque “open source” virou palavra elástica. O desktop do Bruno é distribuído sob licença MIT — a licença permissiva clássica, sem cláusula de uso comercial restrito. Você roda, modifica e usa dentro da empresa sem pedir autorização.

A empresa por trás do projeto monetiza por plano pago, com recursos adicionais e suporte corporativo, e existiu uma edição vitalícia paga que foi descontinuada. Nada disso é pré-requisito para o uso normal: não há limite de requests, de coleções ou de pessoas, porque não existe servidor contando. É a diferença entre um produto grátis e um produto que não tem como cobrar por volume.

Bruno no CI: bru run

A parte que costuma decidir a adoção não é a interface, é a CLI. O comando bru run executa uma coleção inteira a partir do terminal, roda os testes e assertions escritos em JavaScript e devolve exit code — que é o que um pipeline precisa para falhar o build. A documentação da CLI cobre geração de relatório em JSON, JUnit e HTML, além de guias para GitHub Actions, Jenkins, GitLab CI e Azure DevOps.

O ganho aqui é sutil e grande: o mesmo artefato serve para os dois usos. O request que você dispara na mão para depurar é o request que roda no pipeline. Não existe uma coleção “de desenvolvimento” e uma suíte separada “de contrato” que divergem em três meses. É o mesmo princípio de CI/CD sem drama — pipeline que roda o que as pessoas realmente usam, não uma cópia paralela — e complementa bem a bateria de testes antes do go-live.

Um teste típico ocupa poucas linhas:

test("cria pedido e devolve id", function () {
  expect(res.getStatus()).to.equal(201)
  expect(res.getBody().id).to.be.a("string")
})

Segredos: a parte em que dá para errar feio

Colocar a coleção no repositório aumenta a chance de alguém commitar um token. O padrão correto é curto e não é negociável: no arquivo de ambiente versionado vai apenas o nome da variável; o valor vem de um arquivo local ignorado pelo .gitignore ou de um gerenciador de segredos, e é injetado como variável de ambiente na hora de rodar.

No CI, o valor vem do cofre de segredos do próprio pipeline. Em nenhum momento o segredo precisa existir dentro de um arquivo .bru.

Vale repetir o que costuma ser aprendido do jeito caro: token que entrou em commit vazou, mesmo que você apague no commit seguinte. O histórico continua lá, e qualquer pessoa que já clonou tem uma cópia. A única resposta é rotacionar a credencial. É a mesma disciplina de arquitetura segura para dados sensíveis aplicada a um arquivo pequeno que parece inofensivo.

O que você perde ao sair do Postman

Migração honesta declara o custo. O que o Postman faz melhor:

  • Colaboração pronta. Workspace compartilhado, histórico, comentários e permissões vêm de graça com a conta. No Bruno, colaboração é o seu fluxo de Git. Para um time que já vive em pull request, isso é vantagem; para um time com pessoas de produto ou QA que não usam Git, é atrito real.
  • Documentação publicável. Gerar um portal de API a partir da coleção e mandar o link para um parceiro é um caso em que o Postman resolve com um clique.
  • Ecossistema e mocks. Servidores de mock, monitores e integrações prontas têm anos de vantagem.
  • Scripts existentes. A importação traz requests e ambientes bem; scripts de pre-request e testes que dependem de APIs próprias do Postman costumam precisar de revisão manual.

Se o seu uso principal é justamente colaboração com gente fora da engenharia, o Bruno resolve menos do que promete.

Como decidir em uma tarde

Não migre o time inteiro de uma vez — isso transforma uma escolha reversível em um projeto. Escolha um serviço, de preferência um que já tenha pipeline. Exporte a coleção do Postman, importe no Bruno, coloque a pasta dentro do repositório do serviço, aponte os segredos para variáveis de ambiente e adicione um passo de bru run no CI.

Depois de duas ou três semanas, faça as três perguntas que importam: alguém abriu um pull request alterando a coleção? O pipeline pegou uma quebra de contrato antes do deploy? Quem entrou no projeto conseguiu chamar a API sem pedir acesso a ninguém? Se as três respostas forem sim, o padrão se prova sozinho e os outros serviços seguem atrás — sem reunião de decisão, que é como as boas mudanças de ferramenta costumam acontecer.

Serviços relacionados

Continue com a Pixelize

Conecte este tema aos serviços certos — ou fale com um consultor.