Ismat Samadov
  • Tags
  • About
16 min read/1 views

Bruno: The Git-Native API Client That Made Me Delete Postman

Bruno stores API collections as .bru files in Git. No cloud, no account, no subscription. After Postman killed free teams, I switched.

Developer ToolsAPIOpen SourceGitHub

Related Articles

OpenTelemetry Is Eating Datadog's Lunch — The Open-Source Observability Stack in 2026

14 min read

The xz-utils Backdoor Was a Preview — Software Supply Chain Security Is Broken

13 min read

The METR Study: AI Tools Made Experienced Developers 19% Slower

16 min read

Enjoyed this article?

Get new posts delivered to your inbox. No spam, unsubscribe anytime.

On this page

  • What Bruno Is (And Isn't)
  • The .bru File: Why Plain Text Changes Everything
  • The Git Workflow
  • Project Structure
  • Environment Variables
  • Collaboration via Git
  • Running Tests in CI/CD
  • Migrating from Postman (It's Easy)
  • Step 1: Export from Postman
  • Step 2: Import into Bruno
  • Step 3: Set Up Environments
  • Step 4: Commit to Git
  • The Golden Edition (And Why I Paid $19)
  • What Bruno Gets Wrong (Honestly)
  • The Quiet Rebellion Against SaaS Dev Tools
  • What I Actually Think
  • Sources

© 2026 Ismat Samadov

RSS

On March 1, 2026, Postman eliminated free team workspaces. A five-person development team that had been collaborating on API collections for free suddenly faced a $1,140 annual bill. The new Team plan starts at $19 per user per month. No collaboration without paying.

My team switched to Bruno that week. Not because of the money — because of something better. Our API collections now live in Git, next to our code, versioned with our code, reviewed in our PRs. And I'm never going back.


What Bruno Is (And Isn't)

Bruno is an open-source, offline-first API client with 41,700+ GitHub stars. It's MIT-licensed, runs entirely on your machine, and stores API collections as plain-text files using a markup language called Bru.

Here's what it's not: it's not a platform. There's no cloud sync. No account. No login. No telemetry. No "workspace" that lives on someone else's server. Bruno is a desktop application and a CLI tool. That's it.

FeaturePostmanInsomniaBruno
Pricing (team)$19/user/month$5/user/monthFree (MIT) / $19 one-time Golden Edition
Account requiredYesYesNo
Cloud syncYes (required for teams)YesNo (Git instead)
Collections storageCloud (proprietary format)Cloud or localLocal filesystem (.bru files)
Git integrationExport/import onlyPluginNative (files are plain text)
Offline supportLimitedLimitedComplete
REST / GraphQL / gRPCYes / Yes / YesYes / Yes / NoYes / Yes / Yes
CI/CD supportNewman CLICLI available@usebruno/cli
Startup time3-5s, 300-600MB RAMUnder 2s, ~150MB RAMUnder 1s, ~80MB RAM
Open sourceNoPartialYes (MIT)

The .bru File: Why Plain Text Changes Everything

This is the core insight that Postman and Insomnia never got right. When your API collections are stored as cloud data in a proprietary format, you lose:

  • Version history: Who changed this endpoint? When? Why?
  • Code review: Can someone review API changes alongside code changes?
  • Branching: Can different feature branches have different API configurations?
  • Reproducibility: Does every team member have the same collection state?

Bruno solves all of this because collections are just files. Here's what a .bru file looks like:

meta {
  name: Create User
  type: http
  seq: 1
}

post {
  url: {{baseUrl}}/api/users
  body: json
  auth: bearer
}

auth:bearer {
  token: {{authToken}}
}

body:json {
  {
    "name": "John Doe",
    "email": "john@example.com",
    "role": "admin"
  }
}

assert {
  res.status: eq 201
  res.body.id: isNumber
}

tests {
  test("should create user", function() {
    expect(res.status).to.equal(201);
    expect(res.body.name).to.equal("John Doe");
  });
}

That's it. Human-readable. Diff-friendly. Greppable. It lives in your repo as api/users/create-user.bru. When someone changes the endpoint URL or adds a new header, it shows up in the PR diff. Your code reviewer can see the API change alongside the code change that requires it.

Compare this to Postman, where collections are JSON blobs synced to Postman's cloud. You can export them, but the exported JSON is thousands of lines of nested objects with UUIDs and metadata. Nobody reviews that in a PR.


The Git Workflow

Here's what the actual day-to-day experience looks like:

Project Structure

my-project/
├── src/
│   ├── routes/
│   └── services/
├── api-collections/
│   ├── bruno.json          # Bruno collection config
│   ├── environments/
│   │   ├── local.bru
│   │   ├── staging.bru
│   │   └── production.bru
│   ├── auth/
│   │   ├── login.bru
│   │   └── refresh-token.bru
│   └── users/
│       ├── create-user.bru
│       ├── get-user.bru
│       └── list-users.bru
├── package.json
└── .gitignore

Your API collections sit right next to your application code. When you create a new feature branch and add a new endpoint, the .bru file for testing that endpoint is part of the same branch.

Environment Variables

vars {
  baseUrl: http://localhost:3000
  authToken: dev-token-123
}

vars:secret [
  stripeApiKey,
  databaseUrl
]

Environment files are also .bru format. Secret variables (marked with vars:secret) are never stored in the file — Bruno prompts you to enter them locally. This means you can commit environment files to Git without leaking secrets.

Collaboration via Git

# Alice adds a new endpoint
git checkout -b feature/user-profiles
# ... creates api-collections/users/get-profile.bru in Bruno
git add api-collections/users/get-profile.bru
git commit -m "Add user profile API test"
git push origin feature/user-profiles
# Creates PR — reviewer sees the .bru file in the diff

No sync conflicts. No "who has the latest collection version?" No "can you re-export the Postman collection and push it?" The collection is in Git. Git handles collaboration.


Running Tests in CI/CD

Bruno isn't just a GUI tool. The @usebruno/cli package runs collections from the command line:

# Install the CLI
npm install -g @usebruno/cli

# Run all requests in a collection
bru run --env staging

# Run a specific folder
bru run api-collections/auth --env staging

# Output as JUnit XML (for CI integration)
bru run --env staging --output junit.xml

A GitHub Actions workflow:

name: API Tests
on: [push, pull_request]

jobs:
  api-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm install -g @usebruno/cli
      - run: bru run api-collections --env staging

Your API tests run in CI alongside your unit tests. If someone changes an endpoint and the .bru test fails, the PR fails. This is the workflow Postman tried to build with Newman, but Bruno makes it natural because the collections are already in the repo.


Migrating from Postman (It's Easy)

Step 1: Export from Postman

In Postman, go to your collection, click the three dots, select "Export," and choose Collection v2.1 format. Save the JSON file.

Step 2: Import into Bruno

Open Bruno, click "Import Collection," select "Postman Collection," and point it to your exported JSON file. Bruno converts the Postman JSON into .bru files in a directory structure.

Step 3: Set Up Environments

Create environment files in environments/ for each environment you had in Postman. Map your variables.

Step 4: Commit to Git

git add api-collections/
git commit -m "Migrate API collections from Postman to Bruno"

The migration typically takes under 30 minutes for a collection with 50-100 endpoints. The hardest part is recreating pre-request scripts — Bruno uses a slightly different scripting API than Postman. But for basic variable extraction and assertion testing, the translation is straightforward.


The Golden Edition (And Why I Paid $19)

Bruno's Golden Edition is a one-time payment of $19 that unlocks additional features:

  • Visual variable viewer: See all variables and their current values
  • Load testing: Basic load testing built into the client
  • OpenAPI import: Import from OpenAPI/Swagger specs
  • Inbuilt Git support: Git operations within the Bruno UI (though you can always just use your terminal)

The Golden Edition is per-user, one-time, forever. Not per month. Not per year. $19. Once. Compare that to Postman's $228/year/user for the Team plan.

For a team of 10 developers over 3 years:

  • Postman Team: $6,840
  • Bruno Golden Edition: $190
  • Bruno Free: $0

What Bruno Gets Wrong (Honestly)

No mock servers. Postman's built-in mock server feature is genuinely useful for frontend developers who need to work against API contracts before the backend is ready. Bruno doesn't have this. You'll need a separate tool like MSW or Prism.

No API documentation generation. Postman can generate beautiful, hosted API documentation from your collections. Bruno doesn't do this. You'll want Swagger UI, Redoc, or your framework's built-in docs (FastAPI's /docs, for example).

Scripting API differences. If your Postman collections have complex pre-request scripts and test scripts using pm.* APIs, you'll need to rewrite them for Bruno's API. The core concepts (setting variables, assertions) are the same, but the syntax differs.

No real-time collaboration. If multiple people need to edit the same collection simultaneously (think: a shared design session), Postman's cloud sync works better. Bruno's Git-based collaboration is async by nature — which is usually fine, but not always.

Plugin ecosystem. Postman has a rich ecosystem of integrations — monitoring, API gateways, documentation. Bruno is younger and has fewer integrations.


The Quiet Rebellion Against SaaS Dev Tools

Bruno is part of a broader trend I've been watching: developers rejecting cloud-first SaaS tools in favor of local-first alternatives that work with version control.

SaaS ToolLocal-First AlternativeKey Difference
PostmanBrunoAPI collections in Git
FigmaPenpotSelf-hostable design tool
NotionObsidianMarkdown files on disk
SlackMatrix / ZulipSelf-hosted messaging
Google DocsMarkdown + GitPlain text, version controlled
GitHub Copilot (cloud)Local LLMsModels on your machine

The pattern: take something that a SaaS company hosts in the cloud, make it work with plain files and Git, and give developers ownership of their data. It's a reaction to exactly what happened with Postman — the tool you depended on changes its pricing, and suddenly you're either paying up or scrambling to migrate.

Bruno's stated philosophy makes this explicit: "A devtool should be extensible and work with the other tools in your stack... not against them." No cloud sync — ever. Not as a feature. Not as an option. It's a design principle, not a limitation.


What I Actually Think

I deleted Postman three months ago and haven't missed it once.

That sounds dramatic, but here's the thing: I was a Postman user for seven years. I watched it evolve from a simple Chrome extension into a bloated platform with workspaces, team management, API monitoring, mock servers, flow diagrams, and API design tools I never asked for. The startup time went from instant to 5 seconds. The RAM usage went from 100MB to 600MB. And now they want $19/month/user for the privilege of collaborating on collections.

Bruno does one thing: send API requests and test responses. It does that thing very well. It starts in under a second. It uses 80MB of RAM. And my collections are .bru files in my Git repo, right next to the code they test.

I think the API client market is at an inflection point. Postman built a platform nobody asked for, and then they started charging for features most developers don't need. Bruno proved that the core use case — "I need to test an API endpoint" — doesn't require cloud infrastructure, user accounts, or monthly subscriptions.

For solo developers and small teams, Bruno is a no-brainer. For enterprise teams that need mock servers, API documentation, and centralized governance, Postman still has features Bruno doesn't. But honestly? Most teams I've worked with use maybe 20% of Postman's features. And that 20% maps perfectly to what Bruno offers for free.

The strongest argument for Bruno isn't the price. It's the Git integration. Having API collections version-controlled alongside your code, reviewable in PRs, and runnable in CI is the workflow that should have always existed. Postman made API testing a separate activity. Bruno makes it part of your development workflow.

That's why I deleted Postman. And that's why I won't be going back.


Sources

  1. Bruno — Official Website
  2. usebruno/bruno — GitHub
  3. Bruno Documentation
  4. Bruno vs Postman — Official Comparison
  5. Version Control with Bruno and GitHub
  6. Postman Ends Free Team Plans — DEV Community
  7. Postman Pricing 2026: What They Changed — Apidog
  8. Postman New Plans and Pricing March 2026 — Postman Blog
  9. Postman Pricing — Official
  10. Postman vs Insomnia vs Bruno: Best API Client in 2026 — DEV Community
  11. Postman Alternatives 2026 — Yuri Kan
  12. Bruno API Client: Open-Source Alternative to Postman — Yuri Kan
  13. Bruno: The Developer-Friendly Alternative to Postman — Perficient
  14. Why I Switched to Bruno for API Testing — Medium
  15. Bruno — Open Source, Sustainability, Privacy — GitHub Discussion
  16. Postman vs Bruno — Postman Official Comparison