Skip to content

jamierpond/yapi

Repository files navigation

πŸ‘ yapi

CLI Playground Go Report Card GitHub stars codecov

The 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. It uses simple YAML files to define requests, meaning you can commit them, review them, and run them anywhere.

Try the Playground | View Source


⚑ Install

macOS:

curl -fsSL https://yapi.run/install/mac.sh | bash

Linux:

curl -fsSL https://yapi.run/install/linux.sh | bash

Windows (PowerShell):

irm https://yapi.run/install/windows.ps1 | iex

Alternative Installation Methods

Using Homebrew (macOS):

brew tap jamierpond/yapi
brew install --cask yapi

Using Go:

go install yapi.run/cli/cmd/yapi@latest

From Source:

git clone https://github.com/jamierpond/yapi
cd yapi
make install

πŸš€ Quick Start

  1. Create a request file (e.g., get-user.yapi.yml):

    yapi: v1
    url: https://jsonplaceholder.typicode.com/users/1
    method: GET
  2. Run it:

    yapi run get-user.yapi.yml
  3. See the magic: You get a beautifully highlighted, formatted response.

Note: The yapi: v1 version tag is required at the top of all config files. This enables future schema evolution while maintaining backwards compatibility.


πŸ“š Examples

yapi speaks many protocols. Here is how you define them.

1. Request Chaining & Workflows

Chain multiple requests together, passing data between steps. Build authentication flows, integration tests, or multi-step workflows.

yapi: v1
chain:
  # Step 1: Login and get token
  - name: login
    url: https://api.example.com/auth/login
    method: POST
    body:
      username: "dev_sheep"
      password: ${PASSWORD}  # from environment
    expect:
      status: 200
      assert:
        - .token != null

  # Step 2: Create a post using the token
  - name: create_post
    url: https://api.example.com/posts
    method: POST
    headers:
      Authorization: Bearer ${login.token}
    body:
      title: "Hello World"
      tags:
        - cli
        - testing
      author:
        id: 123
        active: true
    expect:
      status: 201
      assert:
        - .id != null
        - .title == "Hello World"

Key features:

  • Reference previous step data with ${step_name.field} syntax
  • Access nested JSON properties: ${login.data.token}
  • Assertions use JQ expressions that must evaluate to true
  • Chains stop on first failure (fail-fast)

2. Environment Configuration

Manage multiple environments (dev, staging, prod) with a single config file. Create a yapi.config.yml:

yapi: v1

default_environment: local

environments:
  local:
    url: http://localhost:3000
    vars:
      API_KEY: dev_key_123

  prod:
    url: https://api.example.com
    vars:
      API_KEY: ${PROD_API_KEY}  # from shell env
    env_file: .env.prod         # load vars from file

Then reference in your requests:

yapi: v1
url: ${url}/api/v1/users
method: GET
headers:
  Authorization: Bearer ${API_KEY}

Switch environments: yapi run my-request.yapi.yml -e prod

3. Simple HTTP Requests

No more escaping quotes in curl. Just clean YAML.

yapi: v1
url: https://api.example.com/posts
method: POST
content_type: application/json

body:
  title: "Hello World"
  tags:
    - cli
    - testing

4. Advanced Assertions

Validate complex response structures with JQ-powered assertions.

yapi: v1
url: https://api.example.com/users
method: GET
expect:
  status: 200              # or [200, 201] for multiple valid codes
  assert:
    - . | length > 0       # array has items
    - .[0].email != null   # first item has email
    - .[] | .active == true # all items are active

5. JQ Filtering (Built-in!)

Don't grep output. Filter it right in the config.

yapi: v1
url: https://jsonplaceholder.typicode.com/users
method: GET

# Only show me names and emails, sorted by name
jq_filter: "[.[] | {name, email}] | sort_by(.name)"

6. gRPC (Reflection Support)

Stop hunting for .proto files. If your server supports reflection, yapi just works.

yapi: v1
url: grpc://localhost:50051
service: helloworld.Greeter
rpc: SayHello

body:
  name: "yapi User"

7. GraphQL

First-class support for queries and variables.

yapi: v1
url: https://countries.trevorblades.com/graphql

graphql: |
  query getCountry($code: ID!) {
    country(code: $code) {
      name
      capital
    }
  }

variables:
  code: "BR"

8. Polling with wait_for

Poll an endpoint until conditions are met. Perfect for async jobs, webhooks, and eventual consistency.

Fixed Period Polling:

yapi: v1
url: ${url}/jobs/${job_id}
method: GET

wait_for:
  until:
    - .status == "completed"
  period: 2s
  timeout: 60s

Exponential Backoff:

yapi: v1
url: ${url}/jobs/${job_id}
method: GET

wait_for:
  until:
    - .status == "completed"
  backoff:
    seed: 1s
    multiplier: 2
  timeout: 60s

Backoff waits: 1s -> 2s -> 4s -> 8s... until timeout.

In Chains - Async Job Workflow:

yapi: v1
chain:
  - name: create_job
    url: ${url}/jobs
    method: POST
    body:
      type: "data_export"
    expect:
      status: 202

  - name: wait_for_job
    url: ${url}/jobs/${create_job.job_id}
    method: GET
    wait_for:
      until:
        - .status == "completed" or .status == "failed"
      period: 2s
      timeout: 300s
    expect:
      assert:
        - .status == "completed"

  - name: download
    url: ${wait_for_job.download_url}
    method: GET
    output_file: ./export.csv

πŸŽ›οΈ Interactive Mode (TUI)

Don't remember the file name? Just run yapi without arguments.

yapi

This launches the Interactive TUI. You can fuzzy-search through all your .yapi.yml files in the current directory (and subdirectories) and execute them instantly.

Shell History Integration

For a richer CLI experience, source the yapi shell helper in your .zshrc:

# Add to ~/.zshrc
YAPI_ZSH="/path/to/yapi/bin/yapi.zsh"  # or wherever you installed yapi
[ -f "$YAPI_ZSH" ] && source "$YAPI_ZSH"

# Optional: short alias
alias a="yapi"

This enables:

  • TUI commands in shell history: When you use the interactive TUI to select a file, the equivalent CLI command is added to your shell history. Press ↑ to re-run it instantly.
  • Seamless workflow: Select interactively once, then repeat with up-arrow forever.

Note: Requires jq to be installed.

πŸ‘€ Watch Mode

Tired of Alt-Tab -> Up Arrow -> Enter? Use watch mode to re-run the request every time you save the file.

yapi watch ./my-request.yapi.yml

πŸ”₯ Load Testing

Stress test entire workflows with concurrent execution. Not just individual requests - stress test multi-step chains, auth flows, and complex scenarios. Perfect for finding bottlenecks in real-world usage patterns.

# Stress test an auth flow: login -> create post -> fetch results
yapi stress auth-flow.yapi.yml -n 1000 -p 50

# Run a multi-step workflow for 30 seconds
yapi stress my-workflow.yapi.yml -d 30s -p 10

# Load test against production
yapi stress checkout-flow.yapi.yml -e prod -n 500 -p 25

Options:

  • -n, --num-requests - Total number of workflow executions (default: 100)
  • -p, --parallel - Number of concurrent workflow executions (default: 1)
  • -d, --duration - Run for a specific duration (e.g., 10s, 1m) - overrides num-requests
  • -e, --env - Target a specific environment from yapi.config.yml
  • -y, --yes - Skip confirmation prompt

Key advantage: Each parallel execution runs the entire chain - login, get token, make authenticated request, etc. This tests your API under realistic load, not just isolated endpoints.


πŸ”„ CI/CD Integration (GitHub Actions)

Run your yapi tests automatically in GitHub Actions.

name: Integration Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Yapi Integration Tests
        uses: jamierpond/yapi/integrations/github-action@main
        with:
          command: yapi test ./tests

Configure server startup and health checks in your yapi.config.yml:

yapi: v1

test:
  start: "npm run dev"
  wait_on:
    - "http://localhost:3000/health"
  timeout: 60s

environments:
  local:
    url: http://localhost:3000

The action installs yapi, starts your server, waits for health checks, runs tests, then cleans up.

See the action documentation for more options.


πŸš€ Integrated Test Server

Run tests locally with automatic server lifecycle management. Configure in yapi.config.yml:

yapi: v1

test:
  start: "npm run dev"
  wait_on:
    - "http://localhost:3000/healthz"
  timeout: 60s
  parallel: 8

environments:
  local:
    url: http://localhost:3000

Now yapi test will automatically:

  1. Start your dev server
  2. Wait for health checks to pass
  3. Run all tests
  4. Kill the server when done

Supported health check protocols:

  • http:// / https:// - HTTP health endpoints (expects 2xx)
  • grpc:// / grpcs:// - gRPC health check protocol
  • tcp:// - TCP connection check (databases, etc.)

CLI flags:

yapi test ./tests                    # Uses config from yapi.config.yml
yapi test ./tests --no-start         # Skip server startup (already running)
yapi test ./tests --start "npm start" --wait-on "http://localhost:4000/health"
yapi test ./tests --verbose          # See server output

🧠 Editor Integration (LSP)

Unlike other API clients, yapi ships with a full LSP implementation out of the box. Your editor becomes an intelligent API development environment with real-time validation, autocompletion, and inline execution.

VS Code & Cursor

Install the official extension from VS Code Marketplace or Open VSX:

Features:

  • Run with Cmd+Enter (Mac) or Ctrl+Enter (Windows/Linux) - execute requests without leaving your editor
  • Inline results panel - see responses, headers, and timing right in VS Code
  • Real-time validation - errors and warnings as you type
  • Intelligent autocompletion - context-aware suggestions for keys, methods, and variables
  • Hover info - hover over ${VAR} to see environment variable status

The extension automatically detects .yapi.yml files and activates the language server. No configuration needed.

Neovim (Native Plugin)

yapi was built with Neovim in mind. First-class support via lua/yapi_nvim:

-- lazy.nvim
{
  dir = "~/path/to/yapi/lua/yapi_nvim",
  config = function()
    require("yapi_nvim").setup({
      lsp = true,    -- Enables the yapi Language Server
      pretty = true, -- Uses the TUI renderer in the popup
    })
  end
}

Commands:

  • :YapiRun - Execute the current buffer
  • :YapiWatch - Open a split with live reload

Other Editors

The LSP communicates over stdio and works with any editor that supports the Language Server Protocol:

yapi lsp
Feature Description
Real-time Validation Errors and warnings as you type, with precise line/column positions
Intelligent Autocompletion Context-aware suggestions for keys, HTTP methods, content types
Hover Info Hover over ${VAR} to see environment variable status
Go to Definition Jump to referenced chain steps and variables

🌍 Environment Management

Create a yapi.config.yml file in your project root to manage multiple environments:

yapi: v1

default_environment: local

environments:
  local:
    url: http://localhost:8080
    vars:
      API_KEY: local_test_key
      DEBUG: "true"

  staging:
    url: https://staging.api.example.com
    vars:
      API_KEY: ${STAGING_KEY}  # From shell environment
      DEBUG: "false"

  prod:
    url: https://api.example.com
    vars:
      API_KEY: ${PROD_KEY}
      DEBUG: "false"

Then reference these variables in your request files:

yapi: v1
url: ${url}/users
method: GET
headers:
  Authorization: Bearer ${API_KEY}
  X-Debug: ${DEBUG}

Switch environments with the -e flag:

yapi run get-users.yapi.yml -e staging

Benefits:

  • Keep all environment configs in one place
  • Commit safe defaults, load secrets from shell env
  • No request file duplication across environments
  • Perfect for CI/CD pipelines with multiple deployment stages

πŸ“‚ Project Structure

  • cmd/yapi: The main CLI entry point.
  • internal/executor: The brains. HTTP, gRPC, TCP, and GraphQL logic.
  • internal/tui: The BubbleTea-powered interactive UI.
  • examples/: Look here for a ton of practical YAML examples!
  • webapp/: The Next.js code for yapi.run.

🀝 Contributing

Found a bug? Want to add WebSocket support? PRs are welcome!

  1. Fork it.
  2. make build to ensure it compiles.
  3. make test to run the suite.
  4. Ship it.

Development Branches

main - Stable releases. All stable version tags (e.g., v0.5.0) are cut from this branch.

next - Unstable/integration branch. Every push to next triggers an automatic pre-release with version format vX.Y.Z-next.<short-hash>. These releases:

  • Are marked as pre-releases on GitHub
  • Include CLI binaries for all platforms
  • Include the VS Code extension .vsix file
  • Are deployed to next.yapi.run
  • Do NOT update Homebrew or AUR

Made with β˜• and Go.