Bruno
Open-source, offline-first API client that stores collections as plain text files alongside your source code. No cloud sync, no account, no subscription - commit your requests to Git and review them in pull requests like any other code.
What is Bruno?
Bruno is an open-source API client built for developers who want their HTTP collections to live where their code lives - in a Git repository. While tools like Postman store collections in the cloud and require an account to collaborate, Bruno takes the opposite approach: every request is a plain text .bru file you can read, edit, diff, and commit without ever opening the GUI.
Bruno supports REST, GraphQL, and other HTTP APIs. It includes environments and variables, pre/post-request JavaScript scripting, assertions, authentication (bearer, basic, API key, OAuth 2.0), and a CLI runner for CI pipelines. The GUI app is available for macOS, Windows, and Linux. The project is fully open source under the MIT license with no paid tier or proprietary cloud component.
Key Features
- Offline-first - works without an internet connection; no cloud sync, no telemetry, no account required
- Git-native storage - collections are plain text .bru files; diff them, review them in PRs, search with grep
- Bru language - human-readable format for requests: method, URL, headers, body, scripts, and assertions in one file
- Environments & variables - switch between dev/staging/production configs; secrets kept out of version control
- JavaScript scripting - run pre/post-request scripts to set variables, chain requests, or validate complex responses
- Assertions - declare expected status codes, body properties, and header values directly in the .bru file
- Import from Postman/Insomnia - migrate existing collections with a single import action
- CLI runner - run collections headlessly with
bru runin any CI environment
Installation
# Install the Bruno CLI globally (for CI/scripting) npm install -g @usebruno/cli # Run a collection from the CLI bru run --env production # Run a specific folder of requests bru run requests/users --env staging # Run with environment variables and output JUnit XML (for CI) bru run --env ci --reporter junit --output results.xml # Download the GUI app (macOS / Windows / Linux) # https://www.usebruno.com/downloads
GET Request with Assertions
Each request is a standalone .bru file. The assert block lets you declare expected response values inline - no separate test file needed.
# requests/users/get-user.bru
meta {
name: Get User by ID
type: http
seq: 1
}
get {
url: {{baseUrl}}/api/users/{{userId}}
body: none
auth: bearer
}
headers {
Accept: application/json
X-Request-ID: {{$randomUuid}}
}
auth:bearer {
token: {{authToken}}
}
assert {
res.status: eq 200
res.body.id: eq {{userId}}
res.body.email: isDefined
} POST Request with Post-Response Script
Scripts run after a response arrives and can read the body, set variables, and chain into subsequent requests. Here a login request saves its returned token for use in later requests.
# requests/auth/login.bru
meta {
name: Login
type: http
seq: 1
}
post {
url: {{baseUrl}}/api/auth/login
body: json
auth: none
}
headers {
Content-Type: application/json
}
body:json {
{
"email": "{{userEmail}}",
"password": "{{userPassword}}"
}
}
script:post-response {
// Save the token for subsequent requests
const token = res.getBody().token;
bru.setVar("authToken", token);
}
assert {
res.status: eq 200
res.body.token: isDefined
} Environments
Environment files define variables per target. Secret variable names are declared but their values are stored outside Git - Bruno keeps sensitive data out of your repository automatically.
# environments/staging.bru
vars {
baseUrl: https://staging.api.example.com
userId: 42
userEmail: [email protected]
}
vars:secret [
userPassword,
authToken
]
# environments/production.bru
vars {
baseUrl: https://api.example.com
userId: 42
userEmail: [email protected]
}
vars:secret [
userPassword,
authToken
] Scripting API
Bruno's scripting layer exposes bru helpers for reading and writing variables, environment values, and request/response data. Use the Chai-style expect API for programmatic assertions.
// script:pre-request - runs before the HTTP request is sent
const timestamp = new Date().toISOString();
bru.setVar("requestTime", timestamp);
// Access environment variables
const baseUrl = bru.getEnvVar("baseUrl");
console.log("Sending request to:", baseUrl);
// script:post-response - runs after the response arrives
if (res.getStatus() === 401) {
bru.setVar("authToken", "");
console.warn("Token expired - clear and re-authenticate");
}
// Assertions in scripts (alternative to the assert block)
expect(res.getStatus()).to.equal(200);
expect(res.getBody()).to.have.property("id"); Bruno vs Postman
| Feature | Bruno | Postman |
|---|---|---|
| Collection storage | Plain text files on disk | Cloud (proprietary JSON export) |
| Git integration | Native - commit .bru files | Requires export/import |
| Account required | No | Yes |
| Open source | Yes (MIT) | No |
| CI/CD runner | Yes (bru CLI, free) | Paid (Newman / Postman Cloud) |
| Published collection ecosystem | Growing | Large (Public API Network) |
Pros and Cons
Pros
- ✓ Collections stored as plain text - fully version-controllable
- ✓ No cloud account, no telemetry, no subscription
- ✓ Works offline without any setup
- ✓ MIT open source - no vendor lock-in
- ✓ Free CLI runner for CI/CD pipelines
- ✓ Secrets never written to disk or committed to Git
Cons
- ✗ Smaller ecosystem than Postman (fewer published collections)
- ✗ GUI is less mature than Postman's (fewer advanced UI features)
- ✗ No built-in team cloud sharing (Git repo is the collaboration layer)
- ✗ Mock server support is limited compared to Postman
- ✗ Fewer integrations with monitoring/alerting platforms
Frequently Asked Questions
What is Bruno?▼
Bruno is an open-source, offline-first API client for testing REST, GraphQL, and other HTTP-based APIs. It is designed as a direct alternative to Postman and Insomnia, with one key difference: every collection is stored as plain text files using Bruno's own Bru format on your local filesystem. There is no cloud sync, no account required, and no subscription - your API collections live alongside your source code in Git.
How does Bruno differ from Postman?▼
The biggest difference is that Bruno stores collections as plain text .bru files on disk, making them fully version-controllable with Git. Postman stores collections in its cloud by default and requires an account. Bruno has no cloud sync, no telemetry, no pricing tiers that gate features, and is open source under the MIT license. Postman has a more mature GUI, a larger ecosystem of published collections, and built-in cloud collaboration. If Git-native workflows and offline-first operation matter to you, Bruno is the better choice.
What is the Bru file format?▼
Bru is a simple, human-readable plain text format developed specifically for Bruno. Each .bru file represents one HTTP request and contains the method, URL, headers, body, authentication, pre/post-request scripts, and assertions - all in a clearly structured, diff-friendly format. Because .bru files are plain text, they can be reviewed in pull requests, searched with grep, and edited in any text editor without needing the Bruno GUI.
Can Bruno run in CI/CD pipelines?▼
Yes. Bruno ships a CLI tool (@usebruno/cli, installed via npm) that lets you run collections headlessly in any CI environment - GitHub Actions, GitLab CI, Jenkins, and others. You can target a specific environment file, output results as JUnit XML or JSON, and fail the build on assertion errors. This makes Bruno a complete API testing solution from local development through automated CI.
Is Bruno open source?▼
Yes. Bruno is fully open source under the MIT license. The source code is available on GitHub at github.com/usebruno/bruno. The core GUI application, the CLI runner, and the Bru language parser are all open source. There is no paid tier or proprietary cloud component - the entire tool is free to use, self-host, and contribute to.
Can I import existing Postman or Insomnia collections into Bruno?▼
Yes. Bruno supports importing collections exported from Postman (v2.1 JSON format) and Insomnia. After importing, Bruno converts each request into the .bru plain text format so you can immediately commit them to Git. Environment variables and authentication configs are also migrated. Some advanced Postman features may require manual adjustment after import.
Related Products
on GumroadDeveloper Productivity Bundle
Stop rebuilding the same setup every project. 51 VSCode snippets, 40 Git aliases, 5 Docker Compose stacks, 5 GitHub Actions workflows, 5 README templates, and a dotfiles kit. Set up a professional dev environment in under an hour.
Buy on Gumroad →Developer Cheat Sheet Bundle
10 print-ready cheat sheets for the tools developers use every day: Git, Docker, Linux CLI, SQL, Regex, HTTP Status codes, VS Code shortcuts, Bash scripting, jq/JSON, and Markdown.
Buy on Gumroad →AI Prompt Engineering Toolkit
58 structured prompt templates for Claude, ChatGPT, and Gemini — organized by use case. Code Review, Debugging, Documentation, Architecture, and 10 model-specific tips. Stop writing prompts from scratch.
Buy on Gumroad →You Might Also Need
Git Stash Manager
Visual reference for git stash commands. Copy-ready stash push, pop, apply, drop, list, and branch commands with stash index control. Free git stash cheat sheet.
Open free tool →
OpenAPI Validator
Paste your OpenAPI 3.x spec (YAML or JSON) to validate structure, find missing required fields, detect duplicate paths, check for missing operationIds, and get errors and warnings with path references.
Open free tool →
Git Cheatsheet Interactive
Searchable, interactive Git cheatsheet with 50+ commands. Filter by category, copy commands instantly. Covers setup, staging, branching, remotes, history, undo, and tags. Free.
Open free tool →
More Free Tools
Related Articles
curl 深度使用手冊:API 測試從入門到進階
curl 是每位開發者必備的 CLI 工具。本文涵蓋 GET/POST/PUT/DELETE 請求、認證、header 設定、檔案上傳、除錯技巧,以及 REST API 測試的完整實戰範例。
API Testing Best Practices 2026: Postman vs Insomnia vs Bruno
Complete guide to API testing in 2026. Compare Postman, Insomnia, and Bruno, learn best practices for REST and GraphQL testing, and build automation pipelines that catch regressions before production.
MSW 2.0: The Best Way to Mock APIs in Frontend Tests
A complete guide to Mock Service Worker (MSW) 2.0 — setup, request handlers, Vitest and Jest integration, Storybook mocking, and best practices for realistic API mocking in frontend tests.
GraphQL Federation vs REST Microservices: Which Architecture in 2026?
Compare GraphQL Federation vs REST microservices — Apollo Federation, schema stitching, performance, team scaling, migration paths, and when to choose each in 2026.
tRPC vs GraphQL vs REST: Type-Safe APIs in 2026
Compare tRPC, GraphQL, and REST for building type-safe APIs in 2026. Covers DX, performance, bundle size, schema management, and when to use each approach.
Enjoying this tool? Get more like it.
Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.
Unlock AI-Powered Dev Tools
- ⚡ AI Code Review, Doc Generator & SQL Builder
- ⚡ All premium templates & early access
- ⚡ Member discounts on Gumroad products
$9/mo after trial · Cancel anytime
Want the full toolkit?
Get DevPlaybook Pro
Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.
MIT licensed · Instant download · No subscription
See what's included → Browse all deals →