A fast, keyboard-driven API client for the terminal.
Built for developers who think in keystrokes, not mouse clicks.
╭──────────────────┬──────────────────────────────┬─────────────────────────────╮
│ Saved (2) │ ● Request │ ● Response │
│──────────────────│──────────────────────────────│─────────────────────────────│
│▌ GET Health Check│ URL Headers Body │ Body Headers ⏱ Metrics│
│ https://httpbin │ ──────────────────────────── │ ────────────────────────── │
│ │ │ 200 OK · 142ms · 348B │
│ POST Post JSON │ [GET] > https://httpbin.org │ │
│ https://httpbin │ │ { │
│ │ │ ├ "args": {} │
│ │ [m] method [i] edit │ ├ "headers": { │
│ │ [enter] send │ │ ├ "Host": "httpbin.org" │
│ │ │ │ └ ... │
│ │ │ └ "url": "https://..." │
│──────────────────┴──────────────────────────────┴─────────────────────────────│
│ NORMAL local [i] edit [m] method [r] send [ctrl+s] save [?] help │
╰───────────────────────────────────────────────────────────────────────────────╯
Goblin is designed around one idea: your API workflow should never leave your terminal.
- 🚀 Instant startup — a single Go binary, no runtime, no Electron, no browser tab
- 🔒 100% offline & private — no account, no telemetry, no cloud sync
- ⌨️ Vi-native navigation — Normal, Insert and Command modes feel like home
- 🌳 Interactive JSON tree — navigate, fold and search deeply nested responses
- 📊 Rich metrics — TTFB, DNS, TLS, total time and response size on every request
- 🎨 Multiple themes — four hand-crafted, eye-friendly color schemes
- 🔐 Encrypted vault — AES-256-GCM secrets, never stored in plain text
- 🌍 Environments — switch between
local,stagingandprodin one keystroke
From source (recommended):
git clone https://github.com/you/goblin
cd goblin
go install ./cmd/goblinQuick build:
make build # produces ./goblin binaryCross-compile:
make build-linux # Linux AMD64
make build-mac # macOS ARM64 (Apple Silicon)
make build-windows # Windows AMD64goblinOn launch, focus starts on the Request panel. The natural flow is left → right:
[Collections sidebar] → [Request panel] → [Response panel]
browse & save edit & send inspect results
- Edit the URL — press
ito enter Insert mode, type your URL, pressEsc - Set the method — press
mto cycleGET → POST → PUT → PATCH → DELETE - Send — press
rorEnter - Save — press
Ctrl+Sor type:w
Press ? at any time to open the full keyboard reference.
| Mode | Indicator | Enter | Exit |
|---|---|---|---|
| Normal | NORMAL |
default | — |
| Insert | INSERT |
i |
Esc |
| Command | COMMAND |
: |
Esc |
| Key | Action |
|---|---|
Tab / l / Right |
Move to next panel (column) |
Shift+Tab / h / Left |
Move to previous panel (column) |
j / ↓ |
Move down / scroll (contextual) |
k / ↑ |
Move up / scroll (contextual) |
[ / ] |
Cycle tabs within the active panel |
? |
Open help screen |
Space |
Toggle (Header checkbox or JSON node) |
| Key | Action |
|---|---|
i |
Edit URL or body (Insert mode) |
m |
Cycle HTTP method |
r / Enter |
Send request |
Ctrl+S |
Save request to collection |
| Key | Action |
|---|---|
j / k |
Navigate headers |
Space |
Toggle header on/off |
x |
Delete selected header |
| Key | Action |
|---|---|
j / k |
Scroll or navigate JSON tree |
Space / Enter |
Fold / expand JSON node |
/ |
Search in response body |
y |
Yank response body |
[ / ] |
Cycle Body / Headers / Metrics |
| Key | Action |
|---|---|
[ / ] |
Switch between Collections and History |
/ |
Filter / fuzzy search |
a |
Import history entry into collection |
Enter Command mode with :.
| Command | Action |
|---|---|
:w |
Save current request |
:wq |
Save and quit |
:q |
Quit |
:new |
Create a new request |
:rename <name> |
Rename the selected request |
:delete |
Delete the selected request |
:curl <cmd> |
Import a cURL command into the active request |
:diff |
Diff current response against the previous one |
| Command | Action |
|---|---|
:header <key> <value> |
Add a custom request header |
:auth bearer <token> |
Add Authorization: Bearer <token> |
:auth basic <user> <pass> |
Add Authorization: Basic ... (base64 encoded) |
| Command | Action |
|---|---|
:env <name> |
Switch active environment |
:setenv <key> <value> |
Set a variable in the current environment |
:getenv <key> |
Look up an environment variable |
:extract <var> <path> |
Extract value from response JSON into environment |
Use {{VAR}} syntax anywhere in your URL, headers or body — variables are substituted at send time.
# Example
:setenv BASE_URL https://api.example.com
# Then use in URL:
{{BASE_URL}}/users/meSecrets are stored encrypted with AES-256-GCM at ~/.goblin/secrets.enc.
| Command | Action |
|---|---|
:vault <passphrase> |
Unlock the secrets vault |
Once unlocked, use {{SECRET_KEY}} just like environment variables. The vault indicator appears in the status bar when active.
| Command | Action |
|---|---|
:theme <name> |
Switch color theme |
Available themes:
| Theme | Description |
|---|---|
muted |
Warm neutral, soft blue accents (default) |
nord |
Cool arctic blue-grey |
rosepine |
Dusty rose and teal on deep violet |
kanagawa |
Japanese ink with warm parchment text |
Collections and environments are stored at ~/.goblin/data.json. The file is plain JSON — you can edit it directly, commit it to version control, or share it with your team.
{
"environments": [
{ "name": "local", "vars": { "BASE_URL": "http://localhost:8080" } },
{ "name": "prod", "vars": { "BASE_URL": "https://api.example.com" } }
]
}Goblin can run collections non-interactively, making it a natural fit for CI pipelines, shell scripts, and automation.
# Run all requests in the default collection
goblin run
# Run a specific collection
goblin run -collection "Payment API"
# Run a single request against a specific environment
goblin run -request "Health Check" -env prod
# JSON output — pipe into jq, scripts, CI tools
goblin run -format json | jq '.[] | select(.status >= 400)'
# Text summary
goblin run -format text -verboseExit codes: 0 if all requests return < 400, 1 if any request fails or returns an error — making it straightforward to fail a CI build on broken endpoints.
Flags:
| Flag | Default | Description |
|---|---|---|
-collection |
first | Collection name to run |
-request |
all | Run a single request by name |
-env |
active | Environment name |
-format |
pretty |
Output format: json, pretty, text |
-timeout |
30 |
Request timeout in seconds |
-verbose |
off | Print request details to stderr |
- cURL import —
:curl <command> - CLI mode —
goblin runfor CI pipelines - Request rename & delete
- Response diffing
- Collection export/import (shareable JSON/YAML)
- Request chaining & variable extraction
- WebSocket client
- OpenAPI spec import
Goblin is intentionally lean. Only 3 external packages are used — all from the same terminal UI ecosystem:
| Package | Purpose |
|---|---|
charmbracelet/bubbletea |
TUI event loop and architecture |
charmbracelet/bubbles |
TUI components (inputs, lists, viewport) |
charmbracelet/lipgloss |
Terminal color and layout styling |
Everything else — HTTP client, JSON parsing and formatting, AES-256-GCM encryption, base64 encoding, cURL parsing — is implemented using the Go standard library with zero additional dependencies.
MIT © Goblin Contributors