How to Use Bruno: The Beginner's Guide to the Git-Native API Client
CodexFuse Team · 2026-10-30T11:14:50.428Z · 11 min read
Learning how to use Bruno takes about ten minutes, and it changes how you think about API testing: there is no cloud workspace, no account, and no sync button. Bruno is an open-source desktop API client that stores every collection as plain-text files on your own filesystem, so your API requests live in Git next to the code they test. If you are coming from Postman and want the same send-and-inspect workflow without the cloud layer, our Postman beginner guide covers the cloud-sync side of the comparison; this guide covers the offline, file-based branch — installing Bruno, building your first collection, sending your first request, setting up environments, chaining authentication, committing everything to Git, and running the collection headlessly in CI.
What is Bruno, and why is it different?
Bruno is a free, offline API client for exploring and testing REST, GraphQL, and gRPC APIs. Its defining idea is storage: instead of keeping your requests in a vendor's cloud workspace, Bruno writes every request to disk as a readable text file in its own .bru markup format. A collection is just a folder, an environment is just another file, and the whole thing can be committed, diffed, and reviewed in a pull request like any other code.
The project is fully open source under the MIT license — the usebruno/bruno repository on GitHub had passed 47,900 stars when this article was written — and the maintainers state plainly that there are no plans to add cloud sync, ever. There is no login and no account to create; that also means team sharing works through the tool teams already use for code: Git.
Desktop builds exist for Windows, macOS, and Linux (version 4.3.0 at the time of writing), installable through the usual package managers: Homebrew, Chocolatey, Scoop, Snap, Flatpak, APT, or Winget. If you prefer a download, the official downloads page links the installers directly from the GitHub releases.
How do you use Bruno for the first time?
Here is the complete first-run loop, in order. Each step builds on the last, and by step seven you will have a collection that is committed to Git and runnable from a terminal.
- Install Bruno for your OS from the official downloads page or a package manager — for example
brew install bruno
on macOS orwinget install bruno.bruno
on Windows. - Create a collection inside Bruno and point it at a folder in your project. Bruno generates the folder with a bruno.json manifest and a sample request. Convention is a
bruno/
or.bruno/
directory at the project root. - Read the sample .bru file. Open the folder in your editor and look at the request in plain text — a
get
block with a URL, a headers block, and an assert block. This readable format is the whole point; learn to recognize it now because you will be reading diffs of it later. - Send your first request. Click the request in Bruno's sidebar, check the method and URL, and press Send. Inspect the response status, headers, timing, and body in the response panel.
- Create an environment. Add an environment file for Local with
baseUrl
set to your development server, then rewrite the request URL as{{baseUrl}}/users/1so the same request works against any environment. - Add authentication. Set the request's auth to Bearer and point the token at a variable like
{{api_token}}. Never paste a real token into a shared environment file — the secrets rules below explain the safe pattern. - Commit the collection and run it from the terminal. Commit the folder to Git, install the CLI with
npm install -g @usebruno/cli
, and runbru run
from the collection directory. If the run passes, your first collection is version-controlled and CI-ready.
How do Bruno collections and environments work?
A collection is a folder that contains
bruno.json(the collection settings) plus one
.brufile per request, usually organized into subfolders such as
users/and
auth/. Because everything is a file, you can reorder requests with the
seqfield, edit requests in any text editor, and review changes to requests in pull-request diffs exactly like code changes. If you like editing config in a real editor, see our VS Code beginner guide for the editor setup most Bruno users pair with it.
Environments are separate files, one per target:
local.bru,
staging.bru,
production.bru. Each defines the same variable names with different values — typically
baseUrland any non-secret tokens — and you select the active environment in the Bruno UI or pass it to the CLI with
bru run --env Staging. Referencing variables with double curly braces, like
{{baseUrl}}, keeps one request definition working across every environment.
Bruno also supports pre-request and post-response scripts in JavaScript, inline assertions such as
res.status: eq 200, and GraphQL requests without extra configuration — set the request type to graphql and write the query. The same collection you click through by hand is the collection the CLI executes headlessly, which is why the file format matters more than the GUI.
How do you keep secrets out of Git?
This is the one rule that decides whether your Bruno setup is team-safe: never commit a real token. Bruno marks sensitive fields with the
vars:secretdirective, which stops Bruno from displaying them in the UI after entry — but the value still lives in a file on disk, so it must stay out of version control.
The standard pattern is three layers. First, put shared, non-secret environment files in Git with placeholder values — for example
api_token: your-token-here. Second, add the real-secret files to
.gitignoreand let each developer keep their own local copies, or pull secrets from a dotenv file the way the dev.to walkthroughs recommend. Third, in CI, feed secrets through shell environment variables, which Bruno reads as overrides — the token then exists only in the CI job's secret store and never in the repository at all.
A
collection.example.brutemplate file committed to the repo, with a
collection.bruholding real values and gitignored, is the convention the Bruno community settled on, and it is worth copying exactly. If Git workflows are new to you, our Git beginner guide covers committing, ignoring, and pushing before you wire a collection into a shared repo.
How do you run Bruno collections in CI?
The Bruno CLI, published on npm as
@usebruno/cli, runs any collection headlessly — no GUI, no login, no cloud call. The basic loop is: install it once on the runner, point it at the collection folder, pick the environment, and let the exit code gate the pipeline. A typical job runs
bru run bruno --env staging --reporter jsonand fails the build when any assertion fails.
For runners where you do not want Node installed, Bruno publishes official Docker images —
usebruno/clion Docker Hub and GHCR — with alpine and debian variants for amd64 and arm64 on every CLI release. The one-liner is
docker run -v $(pwd):/bruno usebruno/cli run --env Staging, which mounts the committed collection folder and runs it. Reporters output JSON, JUnit, and HTML, so the results plug into whatever your pipeline already parses; the CLI documentation covers the full flag reference.
This is where the Git-native model pays off: the same requests a developer tested by hand gate every merge, and a teammate who clones the repo gets the full API test environment with zero export-import ceremony. If Docker-based CI is new territory, our Docker beginner guide explains the mount-the-folder pattern the Bruno images rely on.
Bruno vs Postman: which should a beginner pick?
The honest answer is that they are not the same product with different paint: one stores your work in a cloud account, the other stores it in files you own. Beginners choosing between them are really choosing a storage model, and the table below makes the trade-offs concrete.
| Factor | Bruno | Postman |
|---|---|---|
| Where requests are stored | Plain-text .bru files on your disk | Cloud workspace tied to your account |
| Account required | None — offline only, no login | Yes — sign-in required |
| Team sharing | Git: clone, commit, pull request | Workspace invites and sync |
| License (core product) | MIT open source; paid Pro/Ultimate tiers add Git-integration and automation depth | Free tier with paid team plans |
| Offline use | Fully offline by design | Requires sync for full features |
| CI runner | @usebruno/cli or official Docker images | Newman / Postman CLI |
| Import from the other tool | Imports Postman/Insomnia collections | Exports to JSON for migration |
Pick Bruno if you want your API tests version-controlled next to your code, work offline, and avoid another cloud account — especially if your team already reviews everything through pull requests. Pick Postman if your team already lives in its workspaces, needs hosted collaboration without touching Git, or relies on Postman-specific cloud features. Migrating is not a cliff: Bruno imports existing Postman and Insomnia collections, so trying it on a real project costs one afternoon, not a rewrite.
One pricing note, verified at write time: the open-source core is free ($0), while Pro is $6 per user per month and Ultimate $11 per user per month, both billed annually — those tiers add deeper Git integration, automation, and support rather than unlocking basic requesting, so the beginner workflow in this guide costs nothing.
Common beginner mistakes
Five traps catch nearly every new Bruno user, and all five are cheap to avoid. First, committing a real token — use the vars:secret pattern and gitignore from day one, not after the first leak. Second, editing .bru files without learning the format — read one full request file before writing your own so the diffs make sense later. Third, hardcoding URLs — every URL should reference
{{baseUrl}} or a similar variable from the moment it is written, or your collection will not survive its first environment switch. Fourth, skipping environments — create Local, Staging, and Production files early even if Staging and Production are empty; retrofitting environments into a 50-request collection is painful. Fifth, treating the GUI as the only runner — run bru runfrom the terminal once, early, so CI is a natural next step rather than a scary migration.
Sources
- Bruno official downloads page (usebruno.com/downloads) — desktop version 4.3.0, Windows/macOS/Linux builds, Homebrew/Chocolatey/Scoop/Snap/Flatpak/APT/Winget install routes, REST/GraphQL/gRPC support. Fetched 2026-10-30.
- Bruno official pricing page (usebruno.com/pricing) — Open Source $0, Pro $6 per user per month, Ultimate $11 per user per month (billed annually); offline client with no cloud sync, no account, no login. Fetched 2026-10-30.
- Bruno GitHub repository README (github.com/usebruno/bruno) — MIT license, 47,946 stars, .bru plain-text markup, CLI install (
npm install -g @usebruno/cli
) andbru run
usage, official Docker images (usebruno/cli on Docker Hub and GHCR, alpine/debian variants). Fetched 2026-10-30. - "Getting started with Bruno: git-native API testing in 10 minutes" (dev.to) — install-to-CI walkthrough: collections as files, environments as committable files, dotenv for secrets, CLI JSON/JUnit/HTML reporters, official Docker images on every release. Published ~43 days before 2026-10-30.
- "Bruno: The API Client That Stores Requests in Git" (blog.codercops.com) — collection-on-filesystem setup, environment files with vars:secret guidance, .gitignore for real credentials, collection.example.bru template convention, CLI + GitHub Actions wiring. Published ~148 days before 2026-10-30.
- "Managing Postman became painful so I tried migrating to Bruno" (dev.classmethod.jp) — VS Code + Bruno desktop setup, per-project .bruno/ folders, auth:bearer token chaining with {{api_token}}, seq ordering. Published ~126 days before 2026-10-30.
Frequently asked questions
Is Bruno free?
Yes. The core Bruno desktop app is free and open source under the MIT license — version 4.3.0 at the time of writing — and the entire beginner workflow in this guide (install, collections, environments, auth, Git, CLI) costs nothing. Paid tiers exist: Pro at $6 per user per month and Ultimate at $11 per user per month, both billed annually, adding deeper Git integration, automation, and support.
Does Bruno work offline?
Completely. Bruno is offline-only by design, with no cloud component, no sync, and no account or login — the official pricing page states this explicitly. Your collections live as files on your disk, and teams share them through Git instead of a sync service.
Can Bruno replace Postman?
For most API testing workflows, yes. Bruno covers HTTP requests, environments, scripts, tests, and CI runs, and it imports existing Postman and Insomnia collections so migration is incremental. Teams that depend on Postman-specific cloud collaboration features should weigh the storage-model difference in the comparison table above.
Is Bruno open source?
Yes — the usebruno/bruno repository is MIT-licensed and had passed 47,900 stars when this article was written. The maintainers state there are no plans to add cloud sync, ever.
Which platforms does Bruno support?
Windows, macOS, and Linux, via direct installers and package managers (Homebrew, Chocolatey, Scoop, Snap, Flatpak, APT, Winget). The CLI runner is a separate npm package,
@usebruno/cli, and official Docker images cover CI runners without Node.