An honest comparison
Bruno is very good. Here's the honest case for a Bruno alternative.
Bruno is free, MIT-licensed, offline, and stores collections as plain files in your repository. Those are the right defaults, we agree with all of them, and if you want a fast request client on plain text you can stop reading and go download it. Bandura takes the same starting position and answers a different question: what if the file described a flow, with branching, loops, parallel fan-out and subflows, and a graph canvas and a code editor were two ways of editing that one file? That is what the licence is for, and this page is going to be specific about when it isn't worth it.
v1.0.0-rc.8 is out now on Windows and Linux. v1.0.0 final, and signed macOS builds, in August 2026.
Settled arguments
Four things Bruno already got right.
These are not concessions we're making reluctantly. They are the reason Bruno is the comparison worth writing, and none of them is a differentiator for anybody.
Collections belong in the repo
Both tools store tests as plain text next to the code they test, both diff in a
pull request, and both make git clone the sharing mechanism. Bruno
made this argument mainstream. We are downstream of it.
No account, no cloud sync
Neither tool needs you to sign in to open your own files, and neither ships your requests to a vendor. If that is your requirement, both tools pass and the question is which one fits the work.
MIT is a real advantage
Bruno's source is on GitHub under MIT: auditable, forkable, and immune to us
having a bad year. Bandura is commercially licensed and does not match that.
The counterweight is that the .aether format is documented
YAML, so leaving costs you a cp -r rather than an export tool.
Free beats paid when free does the job
Bruno's Open Source tier is not a trial or a crippled edition. It is the product. Paying for a tool you don't need more from is a bad trade, and we would rather say that here than have you discover it after a purchase.
The obvious question
"Why pay for Bandura when Bruno is free?"
Because they are answering different questions. Here is the test we'd apply if we were you.
Your requests are the work
You send calls, check a status and a field or two, keep them in Git, run them in CI, and the occasional chain is short enough that a script is fine.
Then use Bruno. It is free, it does this, and it does it now. Bandura would be a purchase and a migration for something you'd notice mostly as a different-shaped UI. We would rather you kept your money.
Your scenarios are the work
Log in, capture a token, branch on what came back, loop a dataset of 200 rows, fan out four calls in parallel, poll until a job finishes, reuse the auth sequence from five other suites, and find out which step broke at 3am.
That's what the licence is for. In Bandura each of those is a node type in the file rather than JavaScript you wrote and now maintain, and there is a debugger to stop inside it.
The licence is one payment, per seat, after a 30-day evaluation that disables nothing; the price is announced when checkout opens at launch. It covers every release built in the next 12 months; after that the build you have keeps working. Bruno's paid tiers, for reference, are $6 and $11 per user per month billed annually (usebruno.com/pricing, checked August 2026), so a paid Bruno seat recurs every year while a Bandura seat is bought once, and against free Bruno the comparison is one payment versus nothing. Both shapes are on this page because both are true.
The difference in one screen
Two editors, one file, no export in between.
The canvas is not a viewer. Wire two nodes on it and the YAML changes; type in the
YAML and the canvas redraws. Node positions live in the file as ui.position,
so the arrangement you made travels to your teammate's machine instead of being
re-derived differently there.
"Poll until the job is ready"
The same wait, written twice.
This is the whole difference in one requirement. Both work. One of them is a file you read; the other is a file you maintain, test, and eventually debug at 3am when the counter is off by one.
As a script plain JavaScript, the shape in any script-based client
// Nothing wrong with this code.
// It is now yours to maintain.
const url = `${baseUrl}/jobs/${jobId}`;
let attempts = 0;
let body;
while (attempts < 20) {
const res = await fetch(url);
body = await res.json();
if (res.status === 200 &&
body.state === "ready") break;
await new Promise((r) =>
setTimeout(r, 2000));
attempts++;
}
if (attempts === 20) {
throw new Error("job never became ready");
} As a retry block the same behaviour, as fields on the node
# Flow control is data, not a script.
- id: wait_ready
type: request
config:
method: GET
url: ${{ variables.baseUrl }}/jobs/${{ variables.jobId }}
retry:
maxAttempts: 20
delayMs: 2000
until: response.status === 200 && response.body.state === "ready"
next: check_result
- id: check_result
type: condition
config:
expression: "response.body.result.total > 0"
then: assert_totals
else: report_empty
The right-hand version is not shorter by accident. maxAttempts,
delayMs and until are fields the engine reads, so the loop,
the sleep, the counter and the give-up path are not code anybody on your team owns.
The debugger can also stop on the node between attempts, which it cannot do inside a
while loop. That is the trade this page is selling, stated as concretely
as we can state it. Node reference →
What else is in the box
Five more things, each of them checkable.
A debugger over your API tests
Breakpoints, step, run-one-node, run-from-node, and loop-iteration badges, with a variables panel that names the source of every value: flow default, environment, or captured, with a link back to the node that produced it. When an assertion fails, the console carries the expected expression against the actual value, and the notification names the failing node. Breakpoints live on your machine, never in the flow file. Run and debug →
Drift detection that needs no model
Point a flow at your OpenAPI spec and Bandura compares them deterministically: renamed paths, changed methods, new required headers, each listed with a fix you can apply one at a time. It is ordinary code, runs offline, needs no AI key, and is not metered. Self-healing →
A mock server from the flows you already wrote
Bandura turns your flows into an OpenAPI document and serves a stub of it on
loopback: one palette command, or bandura mock. The limit, stated up
front: the mock is only as detailed as your assertions.
A flow that checks a status code produces a mock that returns a status code.
An MCP server, first-party and local
bandura mcp boots a stdio MCP server out of the same binary, giving
Claude Code or Cursor fourteen tools: list, read, run, search, lint and edit flows,
detect drift, import, export OpenAPI, read the .aether schema itself, and replay
this session's runs. It is a local process, so
nothing transits a vendor's cloud.
The MCP server →
AI you point wherever you like, including nowhere
Anthropic and Gemini natively, or any OpenAI-compatible
/chat/completions endpoint. Point it at a local Ollama and the chat,
flow generation, and the
ai-action node run on your hardware with no key. Or leave it
unconfigured: importing, drift detection, the mock server, and every other node
type work with the AI switched off. Local models →
Protocols: near-parity, one addition
Bruno covers REST, GraphQL, gRPC, and WebSocket, and so does Bandura. The one
addition is Server-Sent Events: an sse block on a
request node collects the event stream into response.body as an
array you can assert on. That is a genuine difference and a small one; it is
listed here rather than dressed up as protocol breadth.
Head to head
Bandura vs Bruno, as of August 2026.
| Bandura | Bruno | |
|---|---|---|
| Tests as plain files in your repo | ✓ .aether YAML | ✓ .bru / OpenCollection YAML |
| Account or cloud sync required | None; no server exists on our side | None |
| Source available | ✗ commercial licence; the file format is documented | ✓ MIT on GitHub: auditable and forkable |
| Available to install today | 1.0.0-rc.8 on Windows and Linux; the Windows installer is unsigned, and macOS waits on notarization | ✓ shipping, with an established user base |
| Free tier | Free for personal, learning and open source; one-time licence for commercial use, priced at launch | Free and open source, permanently |
| Visual flow canvas | ✓ graph and code edit the same file | ✗ request-and-folder tree |
| Flow control | Ten node types: condition, loop, parallel, subflow, script, ai-action, retry/poll-until | Scripting and a collection runner |
| Step-through debugging | ✓ breakpoints, step, run-from-node, loop-iteration badges | ✗ |
| Protocols | REST, GraphQL, gRPC, WebSocket, SSE | REST, GraphQL, gRPC, WebSocket |
| OpenAPI | Import, export, and deterministic drift detection with per-finding fixes; offline, unmetered | Import, plus an OpenAPI sync metered on the paid tiers |
| Mock server | ✓ generated from your flows, on loopback; as detailed as your assertions | ✗ |
| MCP server | ✓ first-party, fourteen tools, bundled in the CLI binary | Community wrappers around the CLI, not first-party |
| Headless runner | Compiled binary; pretty/json/JUnit/GitHub reporters, concurrency | Its own CLI, widely used in CI |
| In-app AI | BYO key (Anthropic, Gemini, OpenAI-compatible) or a local model; no markup, no credits | AI assistant on the Pro tier |
| What it costs | Free download; one-time per-seat licence for commercial use, priced at launch, with 12 months of updates | Free · Pro $6 · Ultimate $11, per user/month billed annually |
Bruno takes three rows outright, ties three more, and the cost row is a genuine "depends". The two that should weigh heaviest if you are deciding today are near the top: an MIT licence, and a mature client with an established user base against a Bandura whose first public build is a release candidate. Bruno figures and features checked August 2026 against usebruno.com/pricing, the Bruno documentation, and github.com/usebruno/bruno. If we have a detail wrong, tell us at [email protected] and it gets fixed on this page, not argued about.
If you do try it
Your .bru files import, and Bruno keeps working.
Nothing about trying Bandura removes your Bruno collection. Import is a copy, into a folder you choose, with a review step in front of it.
-
Drop a .bru file or an OpenCollection YAML on the windowFormat auto-detected. One flow per request file, headers and structured
pathParams/queryParamscarried over rather than baked into the URL string. A request with abody:graphqlblock becomes a realgraphqlrequest node, query and variables intact. -
Read the review, tick what you wantEvery flow it found with its node count and the requests it makes, an editable destination folder, and a flat option if you'd rather skip the subfolder. Nothing is written to disk until you press Import, and existing files are never overwritten. Import reference →
-
Chain them into something Bruno couldn't expressImported single-request flows are building blocks. Set
next, add assertions, capture a token, drop in a condition. That is the point at which the two tools stop overlapping.
Fit check
Stay on Bruno if any of this is you.
We would rather lose the sale than have you buy the wrong tool and find out in week three.
Stay if…
- You're on a Mac: Bandura's macOS builds wait on notarization, and its Windows installer is unsigned
- An MIT-licensed, forkable codebase is a hard requirement
- Your work is requests, not multi-step scenarios
- Your team is already fast in Bruno and the migration cost outweighs the gain
- Budget is genuinely zero and free is doing the job
- You want the OpenCollection standard specifically
Look at Bandura if…
- Your suites have grown scripts you now maintain as a second codebase
- You want to see the flow, not reconstruct it from folder order
- "Which step failed?" costs you real time
- Your API changes and your tests find out in CI, one break at a time
- You want an agent to run and repair the suite without a cloud relay
- gRPC, WebSocket, and SSE need to live in the same suite as the REST calls
Also worth naming, because they'd come up anyway: Postman if a hosted team workspace is what you actually want (the switching case is here), Insomnia if you want an Apache-2.0 client with a plugin ecosystem (covered here), Yaak for a fast file-based client without a test runner.
The questions a switch raises
FAQ
Why would I pay for Bandura when Bruno is free?
For most of what Bruno does, you shouldn't. Bruno is free, MIT-licensed, offline, git-native, and mature, and if what you need is a fast request client whose collections are plain files in your repo, it already is that and Bandura does not beat it. The licence buys a different job: flows rather than requests. A graph canvas and a code editor editing the same file, ten node types so branching, loops, parallel fan-out and subflows are declarative config instead of script you own, a step-through debugger with breakpoints, deterministic drift detection against your OpenAPI spec, a mock server generated from your flows, and an MCP server so an agent can run your suite. If none of those is a problem you have this quarter, the honest recommendation is Bruno.
What can Bandura do that Bruno can't?
Six things, all shipped and all checkable. A graph canvas that edits the same file the code editor edits; Bruno has no canvas at all. Ten node types, so a condition, a loop, a parallel fan-out, a subflow or an AI call is a block of YAML rather than JavaScript you maintain. Step-through debugging: breakpoints, step, run-one-node, run-from-node, loop-iteration badges. Deterministic drift detection against an OpenAPI spec with per-finding fixes, offline and with no model involved. A local mock server generated from your flows. And a first-party MCP server, bundled inside the CLI binary, that gives an agent fourteen tools over stdio. Server-Sent Events is a smaller seventh: Bandura collects an SSE stream into the response body as a request-node option, and SSE is not in Bruno's protocol list as of August 2026.
What does Bruno do better than Bandura?
It has years of shipping behind it and installs on any of the three desktop platforms without a warning dialog. Bandura is still on release candidates (1.0.0-rc.8 today), its Windows installer is unsigned, and its macOS builds are still waiting on notarization. It is MIT-licensed, so you can read it, fork it, and keep it running whatever happens to us. Its free tier is genuinely free rather than an evaluation, it has a large user base and community, and OpenCollection gives its format a standards story. If your team is already productive in Bruno, the cost of moving is real and the benefit has to be worth more than the disruption.
Can I import my Bruno collections?
Yes, both .bru files and OpenCollection YAML, one flow per request file. A review step shows what was detected before anything is written: every flow with its node count and the requests it makes, checkboxes to take only some, and an editable destination folder. Existing files are never overwritten. A Bruno request carrying a body:graphql block imports as a real graphql request node with the query and variables carried over, not flattened into an opaque JSON string.
Both store tests as files. What's actually different about the file?
The graph. A .aether file carries routing on each node (next, then, else, body, branches) so a flow is a directed graph in the text, and the canvas draws it rather than storing a second copy. That is why a canvas editor is possible at all without a separate layout file, and why node positions travel with the flow instead of being regenerated differently on each machine. A Bruno collection is a folder of requests plus scripts; the ordering and the logic between them live in the scripts. Both are plain text in your repo, and both diff in a pull request. That argument is settled, and neither of us wins it.
Is Bandura open source like Bruno?
No. Bandura is a commercially licensed product with a compiled CLI, and Bruno's MIT licence is a real advantage that this page is not going to argue away. What is open is the part that determines whether you can leave: the .aether format is documented YAML you can read, parse, and rewrite with your own tools, and the exit is cp -r. There is no proprietary store to be extracted from and no plan tier that decides whether you may open your own files.
How do the licences compare on price?
Bruno's Open Source tier is free; its Pro tier is $6 per user per month and Ultimate $11, both billed annually, as listed on usebruno.com/pricing in August 2026. Bandura is free indefinitely for personal projects, learning, and open source; commercial use is a one-time per-seat licence after a 30-day evaluation that disables nothing, priced when checkout opens at launch. It covers every release built in the following 12 months, after which the build you have keeps working. Nothing auto-renews, and there is no card on file. The shapes differ more than the sums: a five-person team on Bruno Pro pays $360 a year, every year, while Bandura is one payment per seat and year two costs nothing.
Can I keep Bruno and Bandura on the same repository?
Yes, and for a trial that is the sensible arrangement. Importing reads your .bru files and writes .aether files beside them; it never edits or moves the originals, so the Bruno collection keeps working exactly as it did and you can delete the flows folder and be back where you started. The two formats have no shared state and nothing to sync between them, so the practical question is only whether you want to maintain both. A common pattern is to convert the multi-step suites, the ones that chain and branch, and leave one-off requests in Bruno.
Keep reading
The parts this page skimmed.
Tests as files in your repo
The argument you and Bruno already agree on, written out: diffs, blame, clone-to-run, and what stays off the repo.
Offline, and where the data sits
The same local-first defaults you already chose Bruno for, written out file by file, including what a commercial licence does not change.
An agent that runs the suite
The capability with no Bruno equivalent: fourteen tools over local stdio, bundled in the CLI binary, with no vendor in the middle.
The same file in CI
What replaces the Bruno CLI step: one binary, exit codes, JUnit XML, GitHub annotations, and a p95 latency gate.
Postman vs Bruno, sourced
The two tools compared on their own terms, strengths conceded, with Bandura as the third option rather than the headline.
Weighing Insomnia as well?
What the 2023 account episode did and didn't change, and how Git Sync differs from files.
v1.0.0-rc.8 is out now. v1.0.0 final in August 2026
Keep Bruno. Try this on the suite that outgrew it.
You don't have to pick a side to find out. Importing is a copy, so your
.bru files are untouched, and the 30-day evaluation disables nothing:
point Bandura at the one suite that has grown scripts and leave everything else where
it is. Windows and Linux builds are up now; on a Mac, leave an
address and you get the signed build the day it is notarized.
Or settle it on paper first: the node reference is every one of the ten types with its fields, which is the concrete version of the argument above.