Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

req

A minimal, terminal-first HTTP client in the spirit of restclient.el: plain-text .http files are the source of truth, the TUI is a vim-flavored editor and runner around them. No collections database, no mouse, nothing between you and the request.

$ req api.http
→ cursor on a request, Enter → response opens in a split, pretty-printed

The flow

┌───────────── editor (vim) ───────────────┬──── response ─────────────────┐
│ @base = http://localhost:3000            │ 200 OK · 12ms · 1.2 KB · login│
│                                          │ {                             │
│ ### Login                                │   "token": "…"                │
│ # @name login                            │ }                             │
│ POST {{base}}/auth/login                 │                               │
│ Content-Type: application/json           │                               │
│                                          │                               │
│ {"user": "me", "pass": "{{$dotenv PW}}"} │                               │
├──────────────────────────────────────────┴───────────────────────────────┤
│ NORMAL │ api.http │ env:local                                        4:1 │
└───────────────────────────────────────────────────────────────────────────┘

Keys

Key Action
Enter send the request under the cursor
Esc cancel the in-flight request
]] / [[ next / previous request
Tab cycle focus editor ↔ response (↔ tree)
ge environment picker
gs request picker — fuzzy-pick a request and send it
gt toggle the file/request tree
gH history (Enter re-runs, ctrl-y copies as curl)
yc yank request under cursor as a curl command
: command line
vim hjkl w b e 0 $ gg G i a o dd yy ciw v / n N u ctrl-r …

Pickers filter as you type (fzf-style subsequence match): arrows or ctrl-n/ctrl-p move, Enter picks, Backspace widens, Esc closes.

In the response pane: q close, gh toggle headers, gr raw/pretty, / search, y yank — the pane is a read-only vim buffer.

Commands: :w :q :wq :env <name> :var <name> [value] :send :hist :curl <paste a curl command> :sav <path> (write response body to a file).

.http format

Compatible with the common restclient.el / VS Code REST Client / IntelliJ HTTP Client subset:

@base = http://localhost:3000        # file-level variable

### Login                            # ### separates requests
# @name login                        # names it for chaining
POST {{base}}/auth/login
Content-Type: application/json

{"user": "a", "pass": "b"}

### Profile
GET {{base}}/me
Authorization: Bearer {{login.response.body.$.token}}   # JSONPath into a named response

### Upload from a file
POST {{base}}/import
Content-Type: application/json

< ./payload.json

Per-request directives: # @name x, # @timeout 30s, # @no-redirect, # @no-cookie-jar, # @no-verify-ssl.

Variables resolve in this order: --var CLI overrides (headless send) → chained captures → file @vars → selected environment → .env file. Builtins: {{$uuid}}, {{$timestamp}}, {{$isoTimestamp}}, {{$randomInt 1 100}}, {{$processEnv NAME}}, {{$dotenv NAME}}. Bare localhost:3000/x URLs work — http:// is implied.

Environments

http-client.env.json next to your .http files (VS Code REST Client compatible), plus an optional http-client.env.json.user overlay for secrets — gitignore that one:

{
  "$shared": { "api_version": "v2" },
  "local":   { "base_url": "http://localhost:8080" },
  "staging": { "base_url": "https://staging.example.com" }
}

Switch with ge or :env staging; the last-used environment per project is remembered across sessions. With exactly one environment defined it is selected automatically.

:var token abc123 sets a variable in the active environment and writes it to http-client.env.json (key order preserved); :var token shows the resolved value. Keys defined in the .user overlay still win — the status line says so if your new value is shadowed.

Config

~/.config/req/config.toml, overridden by ./req.toml in the project, overridden per request by # @directives:

timeout = "30s"
follow_redirects = true
verify_tls = true          # false: accept self-signed certs everywhere
cookie_jar = true          # session-wide cookie jar (in memory)
proxy = ""                 # explicit proxy; HTTP(S)_PROXY env is respected

[default_headers]
User-Agent = "req"

History

Every executed request (as actually sent, variables resolved) is appended to a per-project JSONL file under the platform data dir, capped at 10 MB. gH lists it newest-first; Enter re-runs an entry, y copies it as curl. Note: headers are stored as sent — including Authorization.

Headless

req send api.http --name login --env local | jq .token
req send api.http -i             # include status line + headers
req send api.http --fail         # exit 22 on HTTP 4xx/5xx (for CI)
req send api.http --var token=abc --var host=dev.local   # per-run overrides
req list api.http                # request names, one per line
req send api.http -n "$(req list api.http | fzf)"        # fuzzy-pick + send

Body goes to stdout, the 200 OK · 12ms · 1.2 KB summary to stderr. --var name=value beats every other variable source for that run. Every req list line is a valid --name, including unnamed METHOD url requests.

Build

cargo build --release            # binary at target/release/req
cargo test

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages