/yapi
CLI-first API testing for HTTP, GraphQL, gRPC, and TCP.
$ npx -y skills add jamierpond/yapi --skill yapi --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/yapi
Context preview
The summary Claude sees to decide when to auto-load this skill.
CLI-first API testing for HTTP, GraphQL, gRPC, and TCP.
SKILL.md
yapi.SKILL.mdyapi
CLI-first API testing for HTTP, GraphQL, gRPC, and TCP.
The Workflow
yapi enables test-driven API development. Write the test first, then implement until it passes:
1. **Write the test** - Create a `.yapi.yml` file with the expected behavior 2. **Run it** - `yapi run file.yapi.yml` (it will fail) 3. **Implement/fix** - Build the API endpoint 4. **Iterate** - Refine assertions, add edge cases
This loop is the core of agentic API development with yapi.
---
Environment Setup (Do This First)
Before writing any tests, set up your environments. Create `yapi.config.yml` in your project root:
yapi: v1
default_environment: local
environments:
local:
url: http://localhost:3000
vars:
API_KEY: dev_key_123
staging:
url: https://staging.example.com
vars:
API_KEY: ${STAGING_API_KEY} # from shell env
prod:
url: https://api.example.com
vars:
API_KEY: ${PROD_API_KEY}
env_files:
- .env.prod # load secrets from fileNow your tests use `${url}` and `${API_KEY}` - same test, any environment:
yapi run get-users.yapi.yml # uses local (default)
yapi run get-users.yapi.yml --env staging
yapi run get-users.yapi.yml --env prod
**Variable resolution order** (highest priority first): 1. Shell environment variables 2. Environment-specific `vars` 3. Environment-specific `env_files` 4. Default `vars` 5. Default `env_files`
---
A) Smoke Testing
Quick health checks to verify endpoints are alive.
HTTP
yapi: v1
url: ${url}/health
method: GET
expect:
status: 200GraphQL
yapi: v1
url: ${url}/graphql
graphql: |
query { __typename }
expect:
status: 200
assert:
- .data.__typename != nullgRPC
yapi: v1
url: grpc://${host}:${port}
service: grpc.health.v1.Health
rpc: Check
plaintext: true
body:
service: ""
expect:
status: 200TCP
yapi: v1
url: tcp://${host}:${port}
data: "PING\n"
encoding: text
expect:
status: 200---
B) Integration Testing
Multi-step workflows with data passing between requests. Use chains when steps depend on each other.
Authentication Flow
yapi: v1
chain:
- name: login
url: ${url}/auth/login
method: POST
body:
email: test@example.com
password: ${TEST_PASSWORD}
expect:
status: 200
assert:
- .token != null
- name: get_profile
url: ${url}/users/me
method: GET
headers:
Authorization: Bearer ${login.token}
expect:
status: 200
assert:
- .email == "test@example.com"CRUD Flow
yapi: v1
chain:
- name: create
url: ${url}/posts
method: POST
body:
title: "Test Post"
content: "Hello World"
expect:
status: 201
assert:
- .id != null
- name: read
url: ${url}/posts/${create.id}
method: GET
expect:
status: 200
assert:
- .title == "Test Post"
- name: update
url: ${url}/posts/${create.id}
method: PATCH
body:
title: "Updated Post"
expect:
status: 200
- name: delete
url: ${url}/posts/${create.id}
method: DELETE
expect:
status: 204Running Integration Tests
Name test files with `.test.yapi.yml` suffix:
tests/
auth.test.yapi.yml
posts.test.yapi.yml
users.test.yapi.yml
Run all tests:
yapi test ./tests # sequential
yapi test ./tests --parallel 4 # concurrent
yapi test ./tests --env staging # against staging
yapi test ./tests --verbose # detailed output
---
C) Uptime Monitoring
Create test suites for monitoring your services in production.
Monitor Suite Structure
monitors/
api-health.test.yapi.yml
auth-service.test.yapi.yml
database-check.test.yapi.yml
graphql-schema.test.yapi.yml
Health Check with Timeout
yapi: v1
url: ${url}/health
method: GET
timeout: 5s # fail if response takes longer
expect:
status: 200
assert:
- .status == "healthy"
- .database == "connected"Run Monitoring Suite
# Check all monitors in parallel
yapi test ./monitors --parallel 10 --env prod
# With verbose output for debugging
yapi test ./monitors --parallel 10 --env prod --verbose
CI/CD Integration (GitHub Actions)
name: API Health Check
on:
schedule:
- cron: '*/5 * * * *' # every 5 minutes
workflow_dispatch:
jobs:
monitor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install yapi
run: curl -fsSL https://yapi.run/install/linux.sh | bash
- name: Run health checks
env:
PROD_API_KEY: ${{ secrets.PROD_API_KEY }}
run: yapi test ./monitors --env prod --parallel 5Load Testing
Stress test endpoints or entire workflows:
# 1000 requests, 50 concurrent
yapi stress api-flow.yapi.yml -n 1000 -p 50
# Run for 30 seconds
yapi stress api-flow.yapi.yml -d 30s -p 25
# Against production (with confirmation)
yapi stress api-flow.yapi.yml -e prod -n 500 -p 10
---
D) Async Job Polling with `wait_for`
For endpoints that process data asynchronously, use `wait_for` to poll until conditions are met.
Fixed Period Polling
yapi: v1
url: ${url}/jobs/${job_id}
method: GET
wait_for:
until:
- .status == "completed" or .status == "failed"
period: 2s
timeout: 60s
expect:
assert:
- .status == "completed"Exponential Backoff
Better for rate-limited APIs or long-running jobs:
yapi: v1
url: ${url}/jobs/${job_id}
method: GET
wait_for:
until:
- .status == "completed"
backoff:
seed: 1s # Initial wait
multiplier: 2 # 1s -> 2s -> 4s -> 8s...
timeout: 300sAsync Workflow Chain
Complete example: create job, poll until done, download result:
yapi: v1
chain:
- name: create_job
url: ${url}/jobs
method: POST
body:
type: "data_exporRead more
yapi
CLI-first API testing for HTTP, GraphQL, gRPC, and TCP.
The Workflow
yapi enables test-driven API development. Write the test first, then implement until it passes:
1. **Write the test** - Create a `.yapi.yml` file with the expected behavior 2. **Run it** - `yapi run file.yapi.yml` (it will fail) 3. **Implement/fix** - Build the API endpoint 4. **Iterate** - Refine assertions, add edge cases
This loop is the core of agentic API development with yapi.
---
Environment Setup (Do This First)
Before writing any tests, set up your environments. Create `yapi.config.yml` in your project root:
yapi: v1
default_environment: local
environments:
local:
url: http://localhost:3000
vars:
API_KEY: dev_key_123
staging:
url: https://staging.example.com
vars:
API_KEY: ${STAGING_API_KEY} # from shell env
prod:
url: https://api.example.com
vars:
API_KEY: ${PROD_API_KEY}
env_files:
- .env.prod # load secrets from fileNow your tests use `${url}` and `${API_KEY}` - same test, any environment:
yapi run get-users.yapi.yml # uses local (default) yapi run get-users.yapi.yml --env staging yapi run get-users.yapi.yml --env prod
**Variable resolution order** (highest priority first): 1. Shell environment variables 2. Environment-specific `vars` 3. Environment-specific `env_files` 4. Default `vars` 5. Default `env_files`
---
A) Smoke Testing
Quick health checks to verify endpoints are alive.
HTTP
yapi: v1
url: ${url}/health
method: GET
expect:
status: 200GraphQL
yapi: v1
url: ${url}/graphql
graphql: |
query { __typename }
expect:
status: 200
assert:
- .data.__typename != nullgRPC
yapi: v1
url: grpc://${host}:${port}
service: grpc.health.v1.Health
rpc: Check
plaintext: true
body:
service: ""
expect:
status: 200TCP
yapi: v1
url: tcp://${host}:${port}
data: "PING\n"
encoding: text
expect:
status: 200---
B) Integration Testing
Multi-step workflows with data passing between requests. Use chains when steps depend on each other.
Authentication Flow
yapi: v1
chain:
- name: login
url: ${url}/auth/login
method: POST
body:
email: test@example.com
password: ${TEST_PASSWORD}
expect:
status: 200
assert:
- .token != null
- name: get_profile
url: ${url}/users/me
method: GET
headers:
Authorization: Bearer ${login.token}
expect:
status: 200
assert:
- .email == "test@example.com"CRUD Flow
yapi: v1
chain:
- name: create
url: ${url}/posts
method: POST
body:
title: "Test Post"
content: "Hello World"
expect:
status: 201
assert:
- .id != null
- name: read
url: ${url}/posts/${create.id}
method: GET
expect:
status: 200
assert:
- .title == "Test Post"
- name: update
url: ${url}/posts/${create.id}
method: PATCH
body:
title: "Updated Post"
expect:
status: 200
- name: delete
url: ${url}/posts/${create.id}
method: DELETE
expect:
status: 204Running Integration Tests
Name test files with `.test.yapi.yml` suffix:
tests/ auth.test.yapi.yml posts.test.yapi.yml users.test.yapi.yml
Run all tests:
yapi test ./tests # sequential yapi test ./tests --parallel 4 # concurrent yapi test ./tests --env staging # against staging yapi test ./tests --verbose # detailed output
---
C) Uptime Monitoring
Create test suites for monitoring your services in production.
Monitor Suite Structure
monitors/ api-health.test.yapi.yml auth-service.test.yapi.yml database-check.test.yapi.yml graphql-schema.test.yapi.yml
Health Check with Timeout
yapi: v1
url: ${url}/health
method: GET
timeout: 5s # fail if response takes longer
expect:
status: 200
assert:
- .status == "healthy"
- .database == "connected"Run Monitoring Suite
# Check all monitors in parallel yapi test ./monitors --parallel 10 --env prod # With verbose output for debugging yapi test ./monitors --parallel 10 --env prod --verbose
CI/CD Integration (GitHub Actions)
name: API Health Check
on:
schedule:
- cron: '*/5 * * * *' # every 5 minutes
workflow_dispatch:
jobs:
monitor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install yapi
run: curl -fsSL https://yapi.run/install/linux.sh | bash
- name: Run health checks
env:
PROD_API_KEY: ${{ secrets.PROD_API_KEY }}
run: yapi test ./monitors --env prod --parallel 5Load Testing
Stress test endpoints or entire workflows:
# 1000 requests, 50 concurrent yapi stress api-flow.yapi.yml -n 1000 -p 50 # Run for 30 seconds yapi stress api-flow.yapi.yml -d 30s -p 25 # Against production (with confirmation) yapi stress api-flow.yapi.yml -e prod -n 500 -p 10
---
D) Async Job Polling with `wait_for`
For endpoints that process data asynchronously, use `wait_for` to poll until conditions are met.
Fixed Period Polling
yapi: v1
url: ${url}/jobs/${job_id}
method: GET
wait_for:
until:
- .status == "completed" or .status == "failed"
period: 2s
timeout: 60s
expect:
assert:
- .status == "completed"Exponential Backoff
Better for rate-limited APIs or long-running jobs:
yapi: v1
url: ${url}/jobs/${job_id}
method: GET
wait_for:
until:
- .status == "completed"
backoff:
seed: 1s # Initial wait
multiplier: 2 # 1s -> 2s -> 4s -> 8s...
timeout: 300sAsync Workflow Chain
Complete example: create job, poll until done, download result:
yapi: v1
chain:
- name: create_job
url: ${url}/jobs
method: POST
body:
type: "data_exporThe API client that lives in your terminal (and your git repo). Stop clicking through heavy Electron apps just to send a JSON body. yapi is a CLI-first, offline-first, git-friendly API client for HTTP, gRPC, and TCP.

