A minimal, keyboard-driven HTTP client. Like Postman, minus the mouse (and 400 MB).
Built on Deno: a single process serves a tiny web UI and opens it in a native window (webview). No build step, no bundler, no framework.
deno task start # native desktop window
deno task browser # serve + open in your default browser
deno task serve # serve only, prints the URLFirst start downloads the webview native library (one time).
Modal, vim-style. ? inside the app shows the full cheatsheet.
h l |
move between panes (sidebar → request → response) |
j k gg G |
move / scroll |
i / ⏎ |
edit field · cycle choice · toggle · open item |
esc |
back to normal mode |
s or ctrl+⏎ |
send (⏎ in the URL bar also sends) |
1–5 [ ] |
request tabs: params · headers · body · auth · options |
a dd x |
add / delete / disable row (or request, in sidebar) |
tab |
sidebar: requests ⇄ history · response: body ⇄ headers |
/ |
filter sidebar · search response body (n/N to step) |
e |
cycle environment |
y |
yank response body / url |
: |
command line |
Commands: :w [name] save · :new [name] · :env [name] · :envs edit
environments · :settings edit defaults · :collection <name> · :ren <name>
· :clear-history · :clear-cookies · :q quit.
{{name}} anywhere in the URL, params, headers, body, or auth fields is
resolved from the active environment, plus any @name = value file variables
declared at the top of the collection's .http file (file variables shadow
environment variables, as in REST Client). Edit environments with :envs (raw
JSON, ctrl+s to save):
{
"active": "local",
"environments": [
{
"name": "local",
"vars": { "baseUrl": "http://localhost:3000", "token": "dev" }
},
{ "name": "staging", "vars": { "baseUrl": "https://staging.example.com" } }
]
}- Auth helpers — bearer token, basic auth, API key (header or query) on the auth tab.
- Per-request options — timeout, follow-redirects, cookie jar on the options
tab; defaults for new requests via
:settings. - Cookie jar —
Set-Cookieresponses are stored per host and replayed automatically;:clear-cookiesresets. - Self-signed TLS — the
start/browser/servetasks run with--unsafely-ignore-certificate-errors=localhost,127.0.0.1, sohttps://localhostwith a self-signed cert just works. Add hosts to that flag indeno.jsonif you need others. - Proxy — Deno's
fetchhonorsHTTP_PROXY/HTTPS_PROXY/NO_PROXY; set them before launching. - History — every send is logged (newest first in the history view,
⏎to replay/edit).
Everything is plain text under ~/.quiver (override with QUIVER_DIR or
--dir <path> — handy for a per-project, git-tracked collection):
<name>.http one file per collection — saved requests
environments.json environments + active
settings.json defaults for new requests
cookies.json cookie jar
history.jsonl request log (append-only)
Collections use the plain-text .http format (restclient.el / VS Code
REST Client
dialect), so the same files work in your editor:
# comments and @vars above the first request are kept verbatim
@base = https://api.example.com
### create user
POST {{base}}/users
Content-Type: application/json
{"name": "ada"}Supported per-request directives: # @name x, # @timeout 30s|500ms,
# @no-redirect, # @no-cookie-jar. Quiver-specific state rides in comments
other clients ignore: # @auth bearer <token> (also basic <user> <pass>,
apikey header|query <key> <value>) for the auth tab, and commented-out
# ?key=value / # Header: value lines for disabled rows. Free-form comments
inside a request block are not preserved when quiver rewrites the file. A
legacy collections.json is converted to .http files on first start (the
original is kept as collections.json.bak).
main.ts entry: flags, webview window (server runs in a worker) or browser mode
src/server.ts localhost API + static UI
src/http.ts request engine: interpolation, auth, cookies, send
src/httpfile.ts .http format: parse + serialize
src/storage.ts plain-file persistence
src/cookies.ts minimal cookie jar
ui/ index.html + app.js + style.css — vanilla, no build step