Zagel is a cross-platform, GUI REST workbench built with Rust + iced. It scans your workspace for request collections (.http) and environments (.env), lets you pick a request, edit it, and send it. Think of it as a workspace-native alternative to Postman or Insomnia for teams that already keep requests in .http files.
The UI is still rough around the edges but it's functioning with good keyboard shortcuts.

- GUI request composer (method, URL, headers, body)
- Auth helpers: Bearer, API key, Basic, OAuth2 client credentials
- Loads requests from
.httpfiles (blocks separated by###) - Loads environments from
.envfiles (simpleKEY=VALUEformat) - Variable substitution in URL/headers/body via
{{VAR_NAME}} - Add/remove multiple project roots from the sidebar
- Per-project environment files plus optional global environment roots
- Periodic rescan of configured folders
Download a prebuilt binary from GitHub Releases (recommended), or build from source (below).
cargo runYou can run scripted UI flows for repeatable testing and screenshot capture:
cargo run -- \
--state-file ./.tmp/zagel-state.toml \
--project-root ./tests/ui/fixtures/workspace \
--automation ./tests/ui/scenarios/smoke.toml \
--screenshot-dir ./artifacts/ui \
--automation-state-out ./artifacts/ui/state.json \
--exit-when-doneWhen --automation-state-out is provided, Zagel writes a full JSON snapshot of
runtime/app/workspace state at the end of the run (both success and failure), so
E2E tests can assert behavior without parsing logs.
Supported scenario actions:
select_request(value = "relative/path.http#0")sendwait_for_status(value = 200or"200")wait_for_text(value = "Received response")wait_for_millis(value = 1000)screenshot(value = "after-send")
Each action is declared as a [[step]] block in TOML.
Bundled scenarios in tests/ui/scenarios/:
smoke.toml: basic selection, send, and screenshot flowui_navigation.toml: selection + ready-state screenshots (no network dependency)rest_send_status.toml: send +wait_for_status+ body text assertion against a local test stubsnapshot_only.toml: minimal flow for state snapshot generation
Run E2E automation test locally (opt-in):
ZAGEL_E2E=1 ZAGEL_E2E_ARTIFACTS_DIR=artifacts/e2e cargo test --locked --test e2e_automation -- --nocapture --test-threads=1Release build:
cargo build --releaseThis repo now includes a flake.nix so nix-based CI can run nix flake check
directly.
Local verification:
nix flake checkFor an interactive shell with Rust + Linux GUI deps:
nix develop
cargo test --lockedIf you want local parity on Windows, install Nix in WSL and run checks there:
wsl -d Ubuntu
curl -fsSL https://install.determinate.systems/nix | sh -s -- install
cd /mnt/c/Users/<your-user>/projects/zagel
nix flake checkZagel treats each request as a block. Blocks are separated by lines starting with ###.
Example requests.http:
GET https://httpbin.org/get
Accept: application/json
###
POST https://httpbin.org/post
Content-Type: application/json
{"hello":"world"}Rules:
- First non-empty line:
METHOD URL - Subsequent non-empty lines until the first blank line: headers (
Name: Value) - After the blank line: body (optional)
Any file whose name ends with .env is treated as an environment. Format is KEY=VALUE per line; # starts a comment.
Example dev.env:
API_URL=https://httpbin.org
TOKEN=secretYou can use variables in requests as {{API_URL}} / {{TOKEN}}.
Zagel stores UI/application state in ~/.config/zagel/state.toml (exact location depends on your OS).
Relevant keys:
project_roots(folders scanned for.httprequest collections and project-scoped.envfiles)global_env_roots(folders scanned for global.envfiles)active_environment(last selected environment label)
Contributions are welcome. See CONTRIBUTING.md for setup, linting, and the suggested workflow.