A lightweight, open-source desktop client for .http files —
with response history, scripting, and capture-back-into-the-file.
Every API client (Postman, Bruno, Insomnia, Yaak) invents its own file format and
locks you into it. Meanwhile the .http / .rest format used by VS Code REST
Client, JetBrains, and httpYac is plain text, git-native, and editable
anywhere — but no standalone desktop app treats it as the source of truth.
Forge does. It reads your .http files directly and adds the things they lack:
- A browsable tree of files, folders, and endpoints.
- First-class examples, docs, and "possible errors" — parsed from ordinary comments, so they never break the file.
- Per-endpoint history of every response you've seen.
- Bruno-compatible JS scripting — pre-request (
req.setBody(),req.setHeader(),bru.setVar()) and post-response (expect(),test(),bru.visualize()). - Editable auth, form fields, scripts, method, URL, headers, body — all from
the UI, all persisted back into the
.httpfile. - OpenAPI export — convert your
.httpcollection to an OpenAPI 3.0 spec. - Static HTML docs — generate self-contained documentation from any collection.
- The wedge: run a request → capture the real response → write it back into
the
.httpfile as an example/doc block. The loop closes, in git, in plain text.
.http stays the single source of truth. Forge never rewrites your file except
to append metadata you asked it to capture — and that metadata is just comments,
so REST Client / JetBrains keep working too.
Early development. See the roadmap.
| Phase | Scope | State |
|---|---|---|
| 0 | Project setup, icon, license | ✅ |
| 1 | forge-core: .http parser + model + CLI + tests |
✅ |
| 2 | forge-engine: HTTP execution + {{var}}/env interpolation |
✅ |
| 3 | forge-history: SQLite history + capture-response-into-file |
✅ |
| 4 | Desktop app (Tauri): tree + run + response pane | ✅ |
| 5 | UI variables, send+save capture, response/history diff + themes | ✅ |
| 6 | Packaging + CI (cross-platform release) | ✅ |
| 7 | Environments, request chaining, JSON highlighting, copy-as-cURL | ✅ |
| 8 | Assertions + collection runner (test suite) | ✅ |
| 9–10 | Auth: bearer / basic / api-key / oauth2 client-credentials | ✅ |
| 11 | Collection search & filter (⌘K, collapsible groups) | ✅ |
| 12 | GraphQL body mode (query + variables → JSON payload) | ✅ |
| 13 | Cookie jar · cURL import · multipart/binary · capture button | ✅ |
| 14 | Postman import · request tags · expanded auth (digest/ntlm/aws4/oauth1/wsse) | ✅ |
| 15 | Pre/post-request scripting (req, res, bru.*, expect, test) | ✅ |
| 16 | Editable auth/form/scripts in UI · dirty-state save workflow | ✅ |
| 17 | OpenAPI export · HTML docs generation | ✅ |
Requires a Rust toolchain (stable).
cargo build # build the workspace
cargo test # run the full test suite
cargo build --release # lightning-fast, stripped binary
# CLI
forge parse <file.http> # parse → JSON model
forge run <file.http> -r <n> # execute request n
forge run <file.http> -r 1 -e token=abc --save # interpolate + capture into the file
forge run-all <file|dir> # run every request in order (chaining + assertions)
forge curl <file.http> -r <n> # print as a curl command
forge import <collection.json> -o <dir> # import Postman/OpenAPI/Bruno → .http files
forge history <file.http> [-r <n>] # show recorded response timeline### login
POST {{host}}/auth/login
Content-Type: application/json
{ "user": "sara" }
# @auth bearer {{token}} ← auth: bearer | basic | apikey | oauth2 (client-creds/
# ← password) | digest | ntlm | aws4 | oauth1 | wsse
# @tag smoke auth-flow ← label requests (searchable; shown in the tree)
# @graphql ← send body as a GraphQL query (+ trailing {…} variables)
# @form title = Hello ← form field (urlencoded, or multipart if any @file)
# @file document = /path/to.pdf ← file upload part (→ multipart/form-data)
# @body-file /path/to.bin ← send a file's raw bytes as the body
# @capture token = body.data.token ← chain: reuse later as {{token}}
# @assert status == 200 ← test: status / time / size / headers.X / body.path
# @assert body.data.token exists ← ops: == != > < >= <= contains matches exists empty
# @script:pre ← pre-request JS (req.setBody, req.setHeader, bru.setVar)
# req.setUrl('{{baseUrl}}/search')
# bru.setVar('q', 'hello')
# @end
# @script:post ← post-response JS (res, expect, test, bru.setVar)
# test('status is 200', () => {
# expect(res.status).to.equal(200)
# })
# bru.setVar('id', res.json.id)
# @endrun-all exits non-zero if any assertion fails, so it doubles as an API test
suite in CI. Directives are plain # comments — other .http tools ignore them.
run records every response to a local SQLite history store; --save also
writes the response back into the .http file as a ### Example Response:
block the parser recognizes and other .http tools ignore.
cd app
npm install
npm run tauri dev # launch the desktop app (hot-reloaded)
npm run tauri build # produce a native bundle (.dmg/.app, .msi, .deb/.AppImage)The app has a collection tree, request detail with editable method/URL/headers/body/auth/form/scripts, a Send + Save capture button, a response pane with view tabs (body/headers/preview/script tests), an examples/possible-errors viewer, response↔history diff, and a theme picker (Forge Dark + WebStorm New UI light/dark).
Auth, form fields, and scripts are all editable inline — change the auth type in
a dropdown, toggle form field rows, edit pre/post-response JavaScript, and save
it all back into the .http file via the save button.
# Export a collection to OpenAPI 3.0 JSON (via the core library)
forge-core::to_openapi(files) # → OpenAPI 3.0 JSON string
# Generate self-contained HTML documentation
forge-core::generate_docs(files) # → standalone HTML pageBoth functions are available from forge-core for scripting or integration
into CI pipelines. The Tauri app exposes them as well (OpenAPI export via
save-dialog, docs generation via export menu).
- CI (
.github/workflows/ci.yml): rustfmt, clippy (-D warnings), and tests on the library crates, plus a frontend typecheck/build, on every push & PR. - Release (
.github/workflows/release.yml): pushing av*tag builds signed bundles for macOS (arm64 + x64), Windows, and Linux viatauri-actionand attaches them to a draft GitHub release.
crates/
forge-core/ # pure, UI-less engine (parser, model, scripts, docs, OpenAPI)
src/model.rs # serde data model (HttpFile, HttpRequest, Auth, etc.)
src/parser.rs # .http parser
src/import_collection.rs # Postman/Bruno collection import
src/import_openapi.rs # OpenAPI/Swagger import
src/export_openapi.rs # .http → OpenAPI 3.0 export
src/docs.rs # HTML documentation generation
src/capture.rs # response capture → file
src/curl_import.rs # cURL command → HttpRequest
tests/ # integration test suite
forge-engine/ # async HTTP execution + variable interpolation + scripting
src/exec.rs # HTTP client (reqwest), proxy, TLS
src/script.rs # Boa JS sandbox (req, res, bru, expect, test)
src/runner.rs # collection runner (chaining, assertions)
src/interpolate.rs # {{var}} resolution
src/auth.rs # all 12 auth scheme implementations
src/assert.rs # assertion evaluation
forge-history/# SQLite history store
forge-cli/ # CLI front-end that exercises the core
app/
src-tauri/ # Tauri backend (Rust commands)
src/ # Vanilla TypeScript frontend (Vite)
A Cargo workspace in Rust: the core is decoupled from any UI so it stays testable headless and the desktop app is a thin layer on top.
MIT © Forge contributors