Bruno is an open source API client that stores your collections as plain text files instead of in a cloud workspace. If you have ever wanted your API requests to live in Git next to your code, this is the tool for the job. This guide walks through everything from install to running your first collection in CI, and it should take about ten minutes.
Why Bruno instead of a cloud client
Most API clients keep your work in a hosted account. Bruno takes the opposite approach and stores everything on your filesystem. Each request is a .bru file, environments are simple files, and the whole collection is just a folder. That means you can commit it, diff it, review it in a pull request, and keep it in the same repository as the code it tests. Bruno is also offline only, so nothing syncs to a server you do not control.
Step 1: install and create a collection
Download Bruno for Mac, Windows, or Linux from the official site. On first launch, create a new collection. Bruno generates a folder containing a bruno.json manifest and a sample request saved as a .bru file. Open that folder in your editor and you will see the request in readable plain text.
Step 2: understand the .bru format
A basic request looks like this:
get {
url: {{baseUrl}}/users/1
}
headers {
Accept: application/json
}
assert {
res.status: eq 200
}
Everything is human readable. The url references a variable, the headers block sets request headers, and the assert block checks the response. Because this is plain text, you can edit it in VS Code, Vim, or anything else, and it diffs cleanly in a pull request.
Step 3: set up environments and variables
Bruno stores environments as files you can commit alongside your requests. Define a base URL per environment and reference it with {{baseUrl}} so the same request works locally, in staging, and in production. For secrets, pull values from a dotenv file so tokens never get hard coded into a shared collection. Keep real secrets in a .env file that stays out of version control, and reference them so your committed files stay clean.
Step 4: write tests
Bruno supports assertions directly, and JavaScript for anything more involved. A post response test might look like this:
test("status is 200", function() {
expect(res.getStatus()).to.equal(200);
});
test("returns a user id", function() {
expect(res.getBody().id).to.be.a("number");
});
Pre request scripts let you set up data or compute a signature before the call goes out, and post response scripts let you validate results or chain values into the next request.
Step 5: run the whole collection in CI
This is where the git-native model pays off. Install the CLI and run your collection headlessly:
npm install -g @usebruno/cli
bru run --env Staging --reporter-json results.json
The CLI supports JSON, JUnit, and HTML reporters, so it plugs into whatever your pipeline expects. There are official Docker images published on every release, which means you can run collections in CI without installing Node on the runner:
docker run -v $(pwd):/bruno usebruno/cli run --env Staging
Drop that into GitHub Actions, GitLab CI, or Jenkins, and the same requests you test by hand now gate every merge.
Step 6: import what you already have
If you are coming from Postman or Insomnia, you do not have to start over. Bruno can import existing collections, and you can watch how they map to the .bru format. It is a good way to learn the structure while keeping your existing work intact.
Where to go next
That is the core loop: create a collection, write requests and tests as files, commit them, and run them in CI. Bruno supports REST, GraphQL, and gRPC, it is MIT licensed, and it never syncs your data to a cloud. For a deeper look at structuring larger collections and wiring up a full pipeline, this guide on testing APIs with Bruno goes further.
Frequently asked questions
Is Bruno free?
The core client and CLI are free and open source under the MIT license. Paid Pro and Ultimate tiers add in-app Git integration, OpenAPI sync, and enterprise features, but you can do everything in this guide on the free client.
Does Bruno work offline?
Yes. Bruno is offline only by design, with no account and no cloud sync. Your data stays on your machine.
Can I use Bruno with any version control system?
Yes. Because collections are plain files, you can use Git or any other version control system to collaborate over them.
How do I structure a large collection?
Group related requests into folders inside the collection, keep one environment file per stage, and store shared setup in pre request scripts at the folder or collection level. Since everything is plain text, you can reorganize by moving files, and the changes show up cleanly in version control.
Top comments (0)