Skip to content

atsaplin/reqcap

Repository files navigation

reqcap

CI PyPI Python License: MIT

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.

Why reqcap?

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

Features

  • 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=200 exits 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--form for multipart uploads
  • Curl import — paste a curl command and run it through reqcap
  • History — replay recent requests
  • Project init — scaffold config and directories

Install

Requires uv.

uv tool install reqcap

Quick start

Scaffold config and directories:

reqcap --init

This 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=secret

Snapshot a response, then diff later:

reqcap GET /api/health --snapshot baseline
reqcap GET /api/health --diff baseline

See what templates are available:

reqcap --list-templates

Templates

Templates 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.

Creating a template

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]

Using templates

Run by name (resolves to templates/login.yaml):

reqcap -t login -v [email protected] -v password=secret

Run by file path:

reqcap -t templates/login.yaml -v [email protected] -v password=secret

List all available templates:

reqcap --list-templates

Template file location

Templates are resolved in this order:

  1. Exact file path (e.g. reqcap -t path/to/my-template.yaml)
  2. templates_dir from config + name (e.g. custom-templates/login.yaml)
  3. ./templates/ + name (e.g. templates/login.yaml)

Template properties

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: "..."}

Template fields

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].content
reqcap -t chat -v prompt="Hello, world"

The body becomes {"messages": [{"role": "user", "content": "Hello, world"}]}.

Template with per-request auth

# 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]

Snapshots

Save responses and diff against them to detect regressions.

reqcap GET /api/health --snapshot baseline
reqcap GET /api/health --diff baseline
reqcap --list-snapshots

Templates 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.

Response filtering

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.

Syntax

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)

Examples

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"}
  ]
}

Output modes

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]'

Assertions

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.

Request chaining

Chain requests together by exporting values from one response and using them in the next.

Template auto-exports

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.id

Export 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_token

CLI --export flag

Export arbitrary fields from any response:

reqcap GET /api/me --export token=body.access_token
reqcap GET /api/me --export id

The shorthand --export id is equivalent to --export id=body.id.

How chaining works

  1. --export prints export reqcap_<name>=<value> to stderr
  2. Wrap with eval $(... 2>&1 1>/dev/null) to set env vars in your shell
  3. Pass them to the next request with -v or -H

For declarative chaining, use depends: in templates instead (see Template dependencies).

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.

Config file

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.

Minimal config

defaults:
  base_url: http://localhost:3000
  headers:
    Content-Type: application/json

With this config, reqcap GET /api/users resolves to http://localhost:3000/api/users.

Full config structure

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: []

Environment variables

Config values can reference environment variables with ${VAR_NAME}. These are resolved from:

  1. A .env file (specified by defaults.env_file)
  2. The shell environment
defaults:
  base_url: ${API_BASE_URL}
  auth:
    token: ${API_TOKEN}
# .env
API_BASE_URL=http://localhost:3000
API_TOKEN=sk-abc123

Placeholders

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.

Example

# templates/create-item.yaml
url: /api/items
method: POST
body:
  id: "{{uuid}}"
  created_at: "{{date}}"
  owner: "{{env.USER_ID}}"
  name: ""
fields:
  - name: name
    path: name

Auth types

Configure authentication in defaults.auth or per-template auth:

Bearer token

auth:
  type: bearer
  token: ${API_TOKEN}

API key (custom header)

auth:
  type: api-key
  token: ${API_KEY}
  header: X-API-Key

Basic auth

auth:
  type: basic
  username: ${USER}
  password: ${PASS}

Form data

Submit form data and file uploads with --form:

reqcap POST /api/upload --form name=test --form [email protected]

Curl import

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.

History

reqcap saves the last 50 requests (auth headers excluded).

reqcap --history
reqcap --replay 0
reqcap --replay 0 -f "id,name"

Project init

Scaffold a new project with config and directories:

reqcap --init

This 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.

CLI flags reference

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

License

MIT

About

HTTP request/snapshot tool. Built for AI Agents

Resources

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages