Supr is a spec-first API tool that lives in your terminal.
Point it at a codebase and an agent writes the OpenAPI spec. Supr verifies that spec against the live API, then turns it into your daily driver: run requests, switch environments, keep secrets in the OS keychain, and search yesterday's work. Everything you keep a GUI API client around for: scriptable, offline, and a few keystrokes away.
The spec is the source of truth. Everything orbits it. Discovery produces it, verification trusts it, and the runner consumes it.
- How it works
- Install
- Quick start
- Commands
- Interactive shell
- Discovery providers
- Automation: the CLI is an API
- Stack
- Promises
- Contributing
- License
- Discover: point Supr at a repository. It launches an agent (Claude Code, Cursor, or a raw chat model) that investigates the code and hands back an OpenAPI 3.1 spec over an MCP tool. Re-runs are incremental: fix one endpoint without re-emitting the whole document.
- Verify: probe the live API and reconcile it against the spec. Drift, hallucinated parameters, unenforced auth, and wrong status codes are flagged. This is the correctness backstop that makes a generated spec trustworthy.
- Run: drive requests from the spec, either interactively or as scriptable one-liners. Environments, keychain-backed secrets with auto-injected auth, and searchable history.
curl -fsSL https://raw.githubusercontent.com/elythi0n/supr/main/install.sh | sh
# or with wget:
wget -qO- https://raw.githubusercontent.com/elythi0n/supr/main/install.sh | shInstalls the latest release to ~/.local/bin with checksum verification. Override the destination with SUPR_INSTALL_DIR=/usr/local/bin or pin a version with SUPR_VERSION=v0.1.0. Single static binary, CGO disabled. Linux and macOS are supported; on Windows, grab the .zip from the releases page.
Build from source (Go 1.26+):
git clone https://github.com/elythi0n/supr
cd supr
make install-user # builds and installs supr to ~/.local/bin
# or:
go install github.com/elythi0n/supr@latestsupr init # create a project (openapi.yaml + supr.db)
supr investigate # an agent reads the repo and writes the spec
supr env set dev --base-url https://api.dev.example.com
printf %s "$TOKEN" | supr secret set bearerAuth --env dev # value via stdin, lands in the OS keychain
supr verify # probe the live API, reconcile against the spec
supr run getUser --param id=42 # send a request defined by the specRun supr with no arguments to open the interactive shell.
supr investigate # auto mode: revises an existing spec, or discovers fresh
supr investigate --fresh # ignore the current spec and start over
supr investigate --repo ../other-service # investigate another checkout, read-only
supr investigate --only getUser # rescan just one operation (fast and cheap)
supr investigate --depth full # fast | medium (default) | full — thoroughness + time budget--provider and --model pick the agent; --hint (repeatable) nudges where to look; --include scopes the files. With no hints, the agent runs a detect-the-stack bootstrap first. --only (repeatable, accepts an operationId or "METHOD /path") does a scoped rescan: only the named operations are re-read and merged back locally, so untouched operations stay byte-identical.
supr verify # probe the active environment
supr verify --env staging
supr verify --op getUser --op listThings # narrow the probeOnly safe operations (GET/HEAD with example-filled required params) are probed; everything else is reported as skipped; partial coverage is never silent. Findings cover unreachable endpoints, 404s on declared operations, undeclared status codes, unenforced auth, and undeclared auth. Verify exits 3 when findings exist, so it drops straight into CI.
supr run getUser --param id=42
supr run createUser --body '{"name":"Ada"}'
supr run createUser --body @payload.json
echo '{"name":"Ada"}' | supr run createUser --body @-
supr run listUsers --header X-Trace=1 --cookie session=abcPath parameters fill from --param; leftover params become the query string. Auth is injected automatically from the operation's security scheme using the matching secret in the active environment. A non-2xx response is still a successful run (the API answered); branch on the status. Injected secrets are scrubbed from the URL and from stored history.
supr env set dev --base-url https://api.dev.example.com --var region=eu
supr env list
supr env use staging
printf %s "$TOKEN" | supr secret set bearerAuth --env dev # name it after the security scheme
supr secret list
supr secret rm bearerAuth --env dev --yesEnvironments are named targets (base URL + variables); the first one created becomes active. Secret values are read from stdin or a hidden prompt (never from argv) and stored in the OS keychain only. The database holds references, never values, and secrets are scrubbed from history before it is written.
supr auth login myOauth --env dev # PKCE on localhost (browser) or device flow (headless)
supr auth login myOauth --flow device
supr auth status
supr auth logout myOauth --env devFor a spec's oauth2 schemes, Supr runs the flow and stores the grant in the keychain under the scheme's name, the same slot a static secret would use. The runner injects the token and refreshes it transparently when it expires. Token values never appear in any output.
supr history # most recent requests
supr history --search getUser --since 24h
supr history show 17
supr history replay 17 # re-send exactly, with fresh authHistory is full-text searchable over the operation, URL, and bodies (substring matching, so user finds getUser). Replay re-sends a past request but never replays stored credentials; auth is re-injected fresh from the keychain.
supr request save smoke --op getUser --param id=42 --env dev
supr request save smoke --from-history 17 # lift a past request
supr request run smoke
supr request list
supr request import login --curl 'curl https://api.example.com/login -H "Authorization: Bearer x" -d ...'
supr request export smoke # emit a curl command with auth as a <scheme> placeholderSaved requests are committable by design: they never hold a secret; auth is injected at run time, exactly like supr run. The curl importer parses what browsers actually copy ("Copy as cURL"), matches the URL to a spec operation, and drops credentials (reporting what it dropped). Exports render the runner's exact URL with auth as a placeholder, so a round trip re-imports cleanly.
supr coverage # how much of the spec has been run / verified
supr diff # semantic spec diff vs HEAD
supr diff --against main --check # exit 3 on breaking changes — a CI gateCoverage joins the spec against request history and the last verify run, naming the gaps. Diff matches operations by method + path and flags breaking changes (removed operations, newly required params, type changes, operationId renames, added auth).
Run supr on its own to open the TUI: browse endpoints (grouped by tag, color-coded by method), build and send requests with sticky prefill from past values, switch environments, manage secrets, replay from history, launch an investigation, and verify, all without leaving the terminal. Long JSON bodies hand off to $EDITOR.
Selected with --provider (or the provider config key); the right one is detected from your environment when unset.
| Provider | How it runs | Detection |
|---|---|---|
claude-code |
Delegates to the Claude Code CLI | claude on PATH |
cursor |
Delegates to the Cursor agent CLI | cursor-agent on PATH |
anthropic |
Drives the Messages API directly through Supr's own agent loop | ANTHROPIC_API_KEY |
openrouter |
Any OpenRouter model through the agent loop (--model required) |
OPENROUTER_API_KEY |
ollama |
A local model, fully offline | ollama on PATH or OLLAMA_HOST |
The delegating providers reuse an installed coding agent; the rest run Supr's own in-process harness, which gives a raw chat model the repo-reading tools and the return channel it needs to produce a spec. The investigated repository is always treated as read-only. Output is only as good as the chosen model; run supr verify after, since the verifier is what makes a weak model's spec trustworthy.
Every capability is flag-complete and safe to run non-interactively:
--json: exactly one JSON object on stdout, with a versioned, stable schema.--no-input(orSUPR_NO_INPUT=1): never prompts; fails immediately, naming what was missing.--yesaccepts confirmations.- Meaningful exit codes:
0success,1user/input error,2broken environment,3spec drift (verifyfindings ordiff --checkbreaking changes). SUPR_*env overrides for every config key; stdin/stdout composability.supr schema --jsondumps the entire command surface; generate tool definitions from it instead of hardcoding.
Wrap it in a script, call it from your own tool, or hand it to an agent; the contract is the same either way. supr agent-guide prints the full integration contract, offline, straight from the binary.
| Concern | Choice |
|---|---|
| Language | Go — single static binary, CGO disabled |
| CLI | Cobra + Viper |
| TUI | Bubble Tea + Lip Gloss + Bubbles |
| Storage | SQLite (WAL, modernc.org/sqlite — pure Go) behind repository interfaces |
| Spec | OpenAPI 3.1 as openapi.yaml on disk — git-tracked, hand- and agent-editable |
| Secrets | OS keychain (zalando/go-keyring) — never in the database |
| HTTP | stdlib net/http |
- No telemetry. Ever. A tool that holds your API tokens and sees your request traffic phones home to nobody. There is no analytics endpoint to opt out of, because there isn't one.
- Secrets live in your OS keychain only: never in the database, never in anything shareable, scrubbed from history before it is written.
- Everything works offline except the things that obviously can't: discovery via a remote model and hitting a remote API.
Setup, code style, and the checks to run before pushing are in CONTRIBUTING.md.