SCORE000000
HEARTS
WORLD0-0
Start (Install)

1UP Free, MIT, macOS, Linux, Windows

A REST client for your terminal.

REST, GraphQL, Server-Sent Events and WebSockets in a keyboard-driven terminal UI, with a browser UI one flag away. Collections, environments, history, tests, and cURL and Postman import. Add -gui and it opens in your browser. One static Go binary, and your requests live in a plain JSON file you can commit next to your code.

  • REST, GraphQL, SSE, WebSocket
  • Terminal or browser
  • No account, no cloud

Print a request on the arcade cabinet

TERM-REST-CLIENT
Ready Scripted demo

Try run -env Staging, then press Tab and Enter.

Scripted demo of real output; nothing is sent over the network. The Local run is the real output, with the built-in demo API running in another terminal (rest demo). -data demo.json keeps the sample collections apart from your own. run exits with status 1 when a test fails, so it drops straight into CI.

WORLD MAPHOW TO PLAY

Every section below is a level. Scroll and REQ walks the path, collecting coins on the way and lighting each level as it arrives. Use Tab or the menu to jump to any level; nothing needs a mouse.

WORLD 1-1FEATURES

What you'd reach for a REST client to do.

Everything works from the keyboard, the mouse works too, and nothing needs a login or a network service of its own.

The main screen: collections and folders, the request builder with eight tabs, and the response with tests. Every terminal screenshot on this page is generated from the real app by the project's test suite.

Inventory 9 items, each with its key or flag

  • m

    Collections and folders

    Collections, folders inside folders to any depth, and top-level requests. Rename, duplicate, reorder, and move anything with m. The request title shows its full path, so you always know which API you're editing.

  • Alt+E

    Environments

    Globals plus named environments like Local and Staging. Alt+E switches, a missing variable tells you where it looked, and run -env Staging picks one for a single run.

  • Alt+H

    History

    Every request you send, grouped by day, with the response it got. Open, resend, save to a collection, filter or delete. Stored in its own file, so your workspace stays clean in git.

  • Ctrl+R

    Tests and scripts

    One assertion per line: status == 200, json.items[0].id exists, time < 500. Capture values with set token = json.access_token, and prepare data in a pre-request script.

  • Ctrl+O

    Import Postman and cURL

    Postman collections (v2.0 and v2.1), environments and globals, with common pm.test scripts converted. Paste a curl command from browser dev tools into the URL field and it becomes a request.

  • x

    Export as Postman v2.1

    Collections, folders, environments and globals export as Postman v2.1 files. Tests written here become pm.test JavaScript, so a teammate on Postman can run them.

  • Ctrl+G

    Code snippets

    Ctrl+G shows the request as cURL, Python, JavaScript, Go or HTTPie, with real values or with variables kept. c copies it, and works over SSH too.

  • run

    Headless runs

    rest run "Shop API" sends saved requests, runs their tests and exits non-zero on failure. -v prints headers like curl -v, and -set overrides a variable for one run.

  • Alt+8

    Small comforts

    Unsaved edits survive a restart. Response sections fold and stay folded. Four themes, including a light one. Timeouts, redirects and TLS checks are all settings.

WORLD 1-2API TYPES

REST, GraphQL, streams and WebSockets.

Pick the type next to the URL. The same environments, scripts, tests and history work for all of them, and so does run on the command line.

Headers, sent and received, each foldable.

REST

GET, POST, PUT, PATCH, DELETE, HEAD and OPTIONS. JSON, text, XML and form bodies, Basic, Bearer and API key auth, and {{variables}} anywhere.

Query and variables side by side, sent as JSON.

GraphQL

Query and Variables editors side by side. Ctrl+T reads the server's schema: browse types and arguments, and i writes the query for any field, nested ones included.

Each event as it arrives, with its time.

SSE

Server-Sent Events and NDJSON show up live, each event with its time. Esc stops and keeps what arrived, and tests can check events >= 3 or event[-1].json.done == true.

A Message tab, and a log of what went out and came back.

WebSocket

Connect with your headers and auth, send plain text or JSON, and watch a timed log of what goes out and comes back. Tests run on the received messages when it closes.

WORLD 1-3BROWSER UI

Prefer a mouse? Add -gui.

rest -gui opens the same workspace in your browser. The page is built into the binary, nothing is loaded from the internet, and every request is still sent by term-rest-client itself, so there are no CORS errors and streams, WebSockets, scripts and tests work exactly as in the terminal.

The second screen: the browser UI following a Server-Sent Events stream. Real capture from the app.

-gui opens the browser UI on this machine, and -lan additionally lets other devices on your network open it, using the link it prints with a one-time key. By default the server listens on 127.0.0.1 only, so nothing else can reach it until you add -lan.

rest -gui -lan
$ rest -gui -lan

  term-rest-client GUI is running

  Local:   http://localhost:51234/?t=6f1c…
           http://127.0.0.1:51234/?t=6f1c…
  Network: http://192.168.1.20:51234/?t=6f1c…

  The link carries a one-time key; keep it private. Press Ctrl+C to stop.

Sample addresses and key. The real banner prints your own port and a new key each start.

Everything, with a mouse

Request tabs, the collections tree, environments, history, a JSON tree view, a GraphQL schema browser, a WebSocket composer, code snippets, cURL and Postman import (drop a file on the window) and a command palette on Ctrl+K. Light and dark.

Local by default

It picks a free port on 127.0.0.1, or the one you ask for with -port, falling back when it's taken. -lan lists a link per network address. A per-run key and Origin checks keep other sites from using it.

Light mode. A GraphQL response as a collapsible tree.
WebSocket. Type in the composer, watch the log.
WORLD 1-4CODE SNIPPETS

One request, five languages.

The sample Charge request, exactly as the app generates it. Switch languages with the arrow keys in the app, or print any of them with rest export -lang python.

curl -X POST 'https://httpbin.org/post' \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: term-rest-client' \
  --data-raw '{
  "amount": 200,
  "currency": "INR",
  "orderId": "order-831"
}'

Each language's generator is checked by the test suite. Every snippet is run with python3, node, go and http against a local server, and has to deliver the same method, URL, headers and body as the app itself.

WORLD 2-1SCREENS

Real captures, no mockups.

Each terminal screen is rendered by make screenshots, which drives the app on a simulated terminal and keeps the exact colours it draws. Press Enter on a frame to look closer, then use the arrow keys.

Gallery10 framesClick or press Enter to enlarge

Code snippets. Python with {{variables}} kept as real variables.
History. Every request you sent, grouped by day.
Environments. Globals underneath, the active environment on top.
run, from the command line. Two collections, one command, every test line ticked. Usable in CI.
Tests. Each line passes or fails, with the actual value.
Headers. Sent and received, each section foldable.
Postman import. Folders, auth, bodies and common scripts carried over.
GraphQL schema. Browse the types, then i writes the query.
Folders. Nest as deep as you like, and press m to move things.
Light theme. One of four, alongside Catppuccin Mocha, Gruvbox Dark and Original.
WORLD 2-2KEYBOARD

The keys you'll use most.

F1 shows the full list in the app. Plain letters only act as shortcuts outside text fields, so typing never triggers a command.

  • Ctrl+R
    Send the request
  • Ctrl+S
    Save
  • Ctrl+N
    New request
  • Ctrl+G
    Show as code
  • Ctrl+T
    GraphQL schema
  • c/y
    Copy the response
  • Ctrl+O
    Import cURL or Postman
  • Alt+E
    Next environment
  • Alt+H
    History
  • Alt+1…8
    Request tabs
  • y
    Copy selected as code
  • m
    Move request or folder
  • Esc
    Stop a request, stream or socket
  • Ctrl+Q
    Quit

These are drawings of keys. They press when you hover, focus or scroll to them, and they do not capture any real shortcut, so your browser keeps Ctrl+R.

WORLD 2-3INSTALL

One line, then rest.

The installer picks the right binary for your machine, checks it against the release's SHA-256 sums, and puts it on your PATH as rest. The old name, term-rest-client, still works as a link to it.

# Apple Silicon or Intel Macs, Linux on x86_64 or arm64
curl -fsSL https://raw.githubusercontent.com/AbyAbyss/cli-rest-client/main/get.sh | sh
  • 1 x rest, one static Go binary
  • Your requests, one JSON file
  • MIT licensed, no account, free

Then try the samples offline: run rest demo in one terminal, and rest -data demo.json in another. The demo API answers every sample request, including GraphQL, streaming and WebSocket.

Prefer to download by hand? Every release has archives for macOS (arm64, amd64), Linux (amd64, arm64) and Windows, plus SHA256SUMS, on the releases page. If a browser download on macOS won't open, run xattr -d com.apple.quarantine rest once.

WORLD 2-4UNDER THE HOOD

A plain file you own.

Collections, environments, settings and unsaved edits live in one JSON file, written atomically. History goes in a file next to it. Point -data at a file in your repo and the whole team shares the same requests through git.

The app is written in Go with tview and tcell. The tests drive the real interface on a simulated screen, typing and clicking, and pass under the race detector.

Save file workspace.json

  • Linux~/.config/term-rest-client/workspace.jsonon Linux
  • macOS~/Library/Application Support/term-rest-client/on macOS
  • Windows%AppData%\term-rest-client\on Windows
  • OverrideOverride with -data FILE or TERM_REST_CLIENT_DATA
  • ClipboardClipboard through pbcopy, wl-copy, xclip, xsel or clip, and OSC 52 over SSH
WORLD 2-5LOAD TEST

Ramp it up. See what holds.

rest load sends a saved request, or every request in a folder in order, from many virtual users at once. Each user keeps its own variables, so a token captured at login is used by that user's next request. You get requests per second, p50/p95/p99 latency, errors, and your tests as checks, live and at the end.

Swap the gentle ramp for a spike to 100 users and watch p95 cross the line. Drawn for illustration; your numbers depend on your server.
rest load
$ rest load -stages 30s:50,1m:50,30s:0 -threshold "p95<300ms" "Shop API"

  ramping 0 → 50 → 0 virtual users over 2m, ran 2m

  requests        48,210     401.8/s
  failed          0%
  response time   p50 41.2ms  p95 96.4ms  p99 131ms

  Thresholds
    ✓ p95<300ms  96.4ms          EXIT 0

Sample numbers, in the format rest load prints.

Virtual users send requests back to back. A fixed rate (-rate 200/s) starts them on schedule however slow the server gets, so a slowdown shows up as latency instead of quietly lowering the load. Load tests ask before hitting anything that isn't your machine or a private network. Only test servers you own.

Ramp, hold, spike

-vus 20 -duration 1m holds steady. -stages 30s:50,1m:50,30s:0 ramps up, holds and ramps down; add /s to ramp a request rate instead.

Pass or fail CI

-threshold "p95<300ms,errors<1%" exits 1 when one breaks. -out results.json or .csv keeps the per-second timeline.

Watch it live

Alt+L in the terminal app shows sparklines; the browser UI draws live charts for requests/s, users and p50/p95/p99.

In the browser. Thresholds, then the charts.
In the terminal. Alt+L, the same summary.
WORLD 3-1THE CASTLE

Drops into CI.

rest run "Shop API" sends saved requests, runs their tests and exits non-zero on failure: status 1 if a request fails or any test fails. -v prints headers like curl -v, and -set overrides a variable for one run.

Flip it, press Space on it, or keep scrolling. The scene shows what a pipeline sees when one assertion fails.

All three tests pass. run exits 0 and the pipeline carries on to deploy.

CI RUNSAMPLE
$ rest -data demo.json run -env Local "Payment Gateway"
POST Charge
200 OK 0 ms 328 bytes
status == 200
time < 5000
json.json.orderId == {{orderId}}
Total3 / 3
EXIT 0LEVEL CLEAR

A three-step pipeline drawn for illustration. Scripted sample, not tied to any CI product.