Minimal HTTP client that returns only what you need — status, timing, and the specific JSON fields you ask for. Run templates, save snapshots, test your features e2e quickly.
Note
✨ Built for AI agents too. Filtered output saves tokens, --list-templates lets agents discover existing test scenarios, --diff catches regressions, and --install-skill teaches Claude Code to use reqcap automatically.
A typical curl -s https://httpbin.org/json dumps 42 lines. reqcap gives you just the fields you asked for:
reqcap GET https://httpbin.org/json -f "slideshow.title,slideshow.author"STATUS: 200
TIME: 45ms
BODY:
{
"slideshow": {
"title": "Sample Slide Show",
"author": "Yours Truly"
}
}
Save requests as reusable templates, snapshot known-good responses, diff them later to catch regressions — all from the CLI.
reqcap -t list-users
reqcap -t list-users --snapshot baseline
reqcap -t list-users --diff baseline
reqcap --list-templates- Templates — reusable YAML request scenarios with variables, auth, and chaining
- Snapshots — save responses and diff to detect regressions
- Response filtering — extract nested fields, array slices, specific indices
- Assertions —
--assert status=200exits 1 on failure - Request chaining — export response values and feed them into the next request
- Template dependencies — declarative
depends:for multi-step flows - Config file — base URLs, default headers, env var substitution
- Placeholders —
{{uuid}},{{date}},{{env.VAR}}auto-expand in templates - Auth types — bearer, API key, basic auth in config or per-template
- Form data —
--formfor multipart uploads - Curl import — paste a curl command and run it through reqcap
- History — replay recent requests
- Project init — scaffold config and directories
Requires uv.
uv tool install reqcapScaffold config and directories:
reqcap --initThis creates .reqcap.yaml, templates/, and snapshots/.
Test an endpoint with filtered output:
reqcap GET https://httpbin.org/json -f "slideshow.title,slideshow.author"POST with a JSON body:
reqcap POST https://httpbin.org/post -b '{"name": "test", "email": "[email protected]"}'Run a saved template:
reqcap -t login -v [email protected] -v password=secretSnapshot a response, then diff later:
reqcap GET /api/health --snapshot baseline
reqcap GET /api/health --diff baselineSee what templates are available:
reqcap --list-templatesTemplates are standalone YAML files — each template is its own file, not embedded in the config. This keeps templates portable, version-controllable, and easy to share.
Tip
For AI agents: An agent can run reqcap --list-templates at the start of a task to discover what test scenarios already exist, then re-run them as it makes changes — like lightweight e2e tests it didn't have to write.
Create a YAML file in your templates/ directory:
# templates/login.yaml
description: Authenticate user
url: /api/auth/login
method: POST
body:
email: ""
password: ""
fields:
- name: email
path: email
- name: password
path: password
exports:
token: body.access_token
filter:
body_fields: [access_token, expires_in]Run by name (resolves to templates/login.yaml):
reqcap -t login -v [email protected] -v password=secretRun by file path:
reqcap -t templates/login.yaml -v [email protected] -v password=secretList all available templates:
reqcap --list-templatesTemplates are resolved in this order:
- Exact file path (e.g.
reqcap -t path/to/my-template.yaml) templates_dirfrom config + name (e.g.custom-templates/login.yaml)./templates/+ name (e.g.templates/login.yaml)
| Property | Description |
|---|---|
name |
Optional identifier (defaults to filename) |
description |
Shown in --list-templates |
url |
Endpoint path (appended to base_url) |
method |
HTTP method: GET, POST, PUT, PATCH, DELETE |
base_url |
Override the default base_url for this template |
headers |
Template-specific headers (merged with defaults) |
auth |
Template-specific auth (overrides default) |
body |
Request body template (JSON object) |
fields |
Variables injected into body via -v |
exports |
Auto-export response values (see Request chaining) |
filter |
Template-specific response filter |
depends |
List of template names to run first (see Template dependencies) |
snapshot |
Auto-save response: {enabled: true, name: "..."} |
The fields array defines variables that get injected into the request body at the specified JSON path.
# templates/chat.yaml
url: /api/chat
method: POST
body:
messages:
- role: "user"
content: ""
fields:
- name: prompt
path: messages[0].contentreqcap -t chat -v prompt="Hello, world"The body becomes {"messages": [{"role": "user", "content": "Hello, world"}]}.
# templates/create-user.yaml
url: /api/users
method: POST
auth:
type: bearer
token: "{{token}}"
body:
id: "{{uuid}}"
name: ""
email: ""
created_at: "{{date}}"
fields:
- name: name
path: name
- name: email
path: email
filter:
body_fields: [id, name, email]reqcap -t create-user -v token=sk-abc123 -v name=Alice -v [email protected]Save responses and diff against them to detect regressions.
reqcap GET /api/health --snapshot baseline
reqcap GET /api/health --diff baseline
reqcap --list-snapshotsTemplates can auto-save snapshots with snapshot: {enabled: true}.
Tip
For AI agents: Snapshot a response before making changes, then --diff after to verify nothing broke. Agents get a clear pass/fail signal without eyeballing JSON.
The -f/--filter flag extracts only the fields you specify from the response body.
Tip
For AI agents: Filtered output keeps responses small and token-efficient. An agent checking a 500-field response only sees the 3 fields it asked for.
| Pattern | Meaning |
|---|---|
field |
Top-level field |
nested.field |
Nested object field |
data[].id |
Field from every array element |
data[0].id |
Field from a specific array index |
data[-1] |
Last element of an array |
data[2:5] |
Slice of array elements |
headers[Content-Type] |
Bracket notation for dict keys |
* |
No filtering (return everything) |
reqcap GET /api/users -f "total,page"
reqcap GET /api/user/1 -f "profile.name,profile.role"
reqcap GET /api/users -f "data[].id,data[].name"
reqcap GET /api/users -f "data[-1].name"
reqcap GET /api/users -f "data[0:3].id"
reqcap GET /api/users -f "total,data[].id,data[].email"Given this response:
{
"total": 150,
"page": 1,
"data": [
{"id": 1, "name": "Alice", "email": "[email protected]", "metadata": {"large": "..."}},
{"id": 2, "name": "Bob", "email": "[email protected]", "metadata": {"large": "..."}}
]
}reqcap GET /api/users -f "total,data[].id,data[].name" returns:
{
"total": 150,
"data": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
}Default output includes status, timing, and filtered body. --verbose adds response headers. --raw outputs JSON body only, with no status/time lines — useful for piping:
reqcap GET /api/users --raw | jq '.data[0]'Assert response values and exit with code 1 on failure:
reqcap GET /api/health --assert status=200
reqcap GET /api/user/1 --assert "body.role=admin"
reqcap POST /api/items --assert "status!=500" --assert "body.id!=null"Tip
For AI agents: Assertions give a clear exit code agents can branch on — no output parsing needed.
Chain requests together by exporting values from one response and using them in the next.
Define exports in a template to automatically extract and export values from the response:
# templates/login.yaml
url: /api/auth/login
method: POST
body: { email: "", password: "" }
fields:
- { name: email, path: email }
- { name: password, path: password }
exports:
token: body.access_token
user_id: body.user.idExport statements are printed to stderr as shell export commands. Capture them with eval:
eval $(reqcap -t login -v [email protected] -v password=x 2>&1 1>/dev/null)
reqcap -t get-users -v token=$reqcap_tokenExport arbitrary fields from any response:
reqcap GET /api/me --export token=body.access_token
reqcap GET /api/me --export idThe shorthand --export id is equivalent to --export id=body.id.
--exportprintsexport reqcap_<name>=<value>to stderr- Wrap with
eval $(... 2>&1 1>/dev/null)to set env vars in your shell - Pass them to the next request with
-vor-H
For declarative chaining, use depends: in templates instead (see Template dependencies).
Templates can declare depends: to run prerequisite templates automatically. Exported variables flow through the chain.
# templates/login.yaml
method: POST
url: /api/auth/login
body: { email: "", password: "" }
fields:
- { name: email, path: email }
- { name: password, path: password }
exports:
token: body.access_token# templates/get-users.yaml
depends:
- login
method: GET
url: /api/users
headers:
Authorization: "Bearer {{token}}"Running reqcap -t get-users -v email=admin -v password=secret executes login first (exporting token), then get-users with the token injected.
Dependencies execute depth-first. Circular dependencies are detected and reported.
Tip
For AI agents: A single reqcap -t get-users can handle login + auth + the actual request. Agents don't need to manage multi-step auth flows manually.
Create a .reqcap.yaml in your project root (or pass -c path/to/config.yaml). The config sets defaults — templates are separate files (see Templates).
reqcap auto-discovers config files in this order: .reqcap.yaml, .reqcap.yml, reqcap.yaml, reqcap.yml.
defaults:
base_url: http://localhost:3000
headers:
Content-Type: application/jsonWith this config, reqcap GET /api/users resolves to http://localhost:3000/api/users.
defaults:
base_url: ${API_BASE_URL}
env_file: .env
timeout: 30
templates_dir: templates
headers:
Content-Type: application/json
auth:
type: bearer
token: ${API_TOKEN}
filter:
status: true
headers: false
body_fields: []Config values can reference environment variables with ${VAR_NAME}. These are resolved from:
- A
.envfile (specified bydefaults.env_file) - The shell environment
defaults:
base_url: ${API_BASE_URL}
auth:
token: ${API_TOKEN}# .env
API_BASE_URL=http://localhost:3000
API_TOKEN=sk-abc123
In templates (URLs, bodies, headers):
| Placeholder | Value |
|---|---|
{{env.VAR_NAME}} |
Environment variable |
{{uuid}} |
Random UUID v4 |
{{timestamp}} |
Unix timestamp (seconds) |
{{timestamp_ms}} |
Unix timestamp (milliseconds) |
{{date}} |
ISO 8601 datetime |
{{my_var}} |
Variable from -v flag or dep export |
In config files (.reqcap.yaml): use ${VAR_NAME} for environment variable substitution.
# templates/create-item.yaml
url: /api/items
method: POST
body:
id: "{{uuid}}"
created_at: "{{date}}"
owner: "{{env.USER_ID}}"
name: ""
fields:
- name: name
path: nameConfigure authentication in defaults.auth or per-template auth:
auth:
type: bearer
token: ${API_TOKEN}auth:
type: api-key
token: ${API_KEY}
header: X-API-Keyauth:
type: basic
username: ${USER}
password: ${PASS}Submit form data and file uploads with --form:
reqcap POST /api/upload --form name=test --form [email protected]Parse and execute a curl command directly:
reqcap --import-curl "curl -X POST https://api.example.com/users \
-H 'Content-Type: application/json' \
-d '{\"name\": \"test\"}'"Supports -X, -H, -d, --data, --data-raw, --json, and quoted strings.
reqcap saves the last 50 requests (auth headers excluded).
reqcap --history
reqcap --replay 0
reqcap --replay 0 -f "id,name"Scaffold a new project with config and directories:
reqcap --initThis creates .reqcap.yaml, templates/, and snapshots/.
Tip
For AI agents: Run reqcap --install-skill claude to install an agent skill that teaches Claude Code how to use reqcap — no docs reading needed.
| Flag | Short | Description |
|---|---|---|
METHOD URL |
Direct request (positional args) | |
--template |
-t |
Run a template file (name or path) |
--config |
-c |
Config file path |
--templates-dir |
Override templates directory | |
--var |
-v |
Variable as key=value (repeatable) |
--body |
-b |
Request body (JSON string) |
--header |
-H |
HTTP header as Name: Value (repeatable) |
--filter |
-f |
Comma-separated body fields to extract |
--timeout |
Request timeout in seconds | |
--verbose |
Include response headers | |
--raw |
JSON body only (for piping) | |
--export |
Export response field as env var (repeatable) | |
--assert |
Assert status=200 or body.field!=val (exit 1 on fail) |
|
--snapshot |
Save response as named snapshot | |
--diff |
Diff response against saved snapshot | |
--list-snapshots |
List saved snapshots | |
--snapshots-dir |
Override snapshots directory | |
--form |
Form field KEY=VALUE or KEY=@FILE (repeatable) |
|
--import-curl |
Parse and run a curl command | |
--history |
Show request history | |
--replay |
Replay history entry by index | |
--list-templates |
List template files in templates dir | |
--init |
Scaffold project (config + directories) | |
--install-skill |
Install skill data to agent directory | |
--help |
Full help with all syntax docs |
MIT