apigrip
v0.15.0
Published
A spec-first, read-only OpenAPI client for developers
Downloads
2,321
Maintainers
Readme
Apigrip
A spec-first, read-only OpenAPI client for developers who generate their API specs from code.
The spec file on disk is the only source of truth. It is never imported, copied, or converted. When it changes (because you regenerated it, switched branches, or pulled), the tool reflects the changes immediately.

Quick start
# Install globally
npm install -g apigrip
# Bookmark a project and start the UI
apigrip projects add /path/to/your/api
apigrip serveOr run from inside a project directory (auto-detects the spec):
cd /path/to/your/api
apigrip serveOpen http://127.0.0.1:3000 in your browser.
Requirements
- Node.js 20+
- curl 7.70+ (for
--write-outJSON format)
Features
- Browse endpoints from any OpenAPI 2.0, 3.0.x, or 3.1.x spec
- Send requests via curl subprocess with full
curl -vlevel detail - Live reload on spec changes, git branch switches, and
$refdependency updates (web UI and MCP) - Parameter persistence across restarts (auto-saved per project, per endpoint)
- Named environments with
{{ variable }}syntax resolved at send time .apigrip.jsonproject config for team-shared environment seeding and spec path override- Git status bar showing branch, commit, and dirty/clean state
Ctrl+Pcommand palette with fuzzy search across projects and endpoints- Response schema validation against the spec
- Dracula dark theme by default, light mode available
- MCP server for AI coding assistants
- Electron desktop app (standalone window, no browser needed)
CLI
# Start the web UI
apigrip serve # loads last bookmarked project
apigrip serve --port 8080 --open # custom port, open browser
apigrip serve --project /path/to/api # explicit project
# Send requests from the terminal
apigrip send GET /users # basic request
apigrip send POST /users -d '{"name": "John"}' # with body
apigrip send GET /users/{id} --pathParam id=42 # path param
apigrip send GET /users -e Staging --verbose # use named environment
apigrip send GET /users --dry-run # print without sending
apigrip send GET /users --curl # print curl command only
# Generate curl command (shorthand for send --curl)
apigrip curl GET /users -e Production
# List endpoints
apigrip list # grouped by tag
apigrip list --search "auth" --json # fuzzy search, JSON output
# Show endpoint details
apigrip show GET /users # parameters, schemas, responses
apigrip show POST /users --json # full JSON output
# Print parsed spec
apigrip spec # dereferenced JSON
apigrip spec --raw # original file as-is
# Manage projects
apigrip projects # list bookmarks
apigrip projects add ./my-api # bookmark a directory
apigrip projects remove my-api # remove bookmark
# Manage environments
apigrip env # list environments
apigrip env show Staging # show variables
apigrip env set Staging api_key "sk-123" # set a variable
apigrip env delete Staging api_key # delete a variable
apigrip env import envs.json # import from JSON file
apigrip env import staging.json --import-name Staging # into named env
# View last cached response
apigrip last # list all cached endpoints
apigrip last GET /users # show last response body
apigrip last GET /users --json # full JSON output
# MCP server (for AI assistants)
apigrip mcp --project /path/to/apiShell completion
# Bash — add to ~/.bashrc
eval "$(apigrip completion --shell bash)"
# Zsh — add to ~/.zshrc
eval "$(apigrip completion --shell zsh)"
# Auto-detects shell if --shell is omitted
eval "$(apigrip completion)"Exit codes
| Code | Meaning | |------|---------| | 0 | Success (HTTP 4xx/5xx responses are still exit 0) | | 1 | Network error (DNS, connection refused, timeout) | | 2 | Spec parse error | | 3 | Endpoint not found |
Project context
CLI commands auto-detect the project from the current working directory:
- If
--projector--specis passed, use that - If cwd is inside a bookmarked project, use it
- If cwd contains an OpenAPI spec file, use it directly
- Otherwise, error
The serve command has additional fallbacks: if cwd is a git repo with a spec, it uses that. Otherwise it loads the first bookmarked project. Opening a project in the web UI automatically bookmarks it.
Web UI
Two-panel layout: request on the left, response on the right.
Left panel -- endpoint browser (tag view or path tree view), server selector, parameter inputs, request body editor, send button.
Right panel -- status badge, timing, response body (pretty-printed), headers, verbose curl -v output, copyable curl command.
Keyboard shortcuts: Ctrl+P (command palette), Ctrl+O (open project), Ctrl+E (environment editor), Ctrl+Enter (send request), Ctrl+Shift+L (toggle theme).
Desktop app (Electron)
npm run electron:dev # launch in development
npm run electron:build # package distributableThe Electron wrapper runs the Express server in-process and opens the UI in a native window. Same features as the web UI, no browser required.
Project config (.apigrip.json)
Optional checked-in file at your project root that seeds environments for the team:
{
"spec": "docs/openapi.yaml",
"active_environment": "staging",
"environments": {
"base": { "base_url": "https://api.example.com" },
"staging": { "base_url": "https://staging.example.com" },
"production": { "base_url": "https://prod.example.com" }
}
}All fields are optional. The seed algorithm is non-destructive: it only adds environments that don't already exist in the user's config and never overwrites existing values. The spec field overrides automatic spec discovery.
Environments
Environments are named sets of key-value pairs stored per project in the config directory (never in your project).
Base Environment -> base_url=http://localhost:8080, api_version=v1
+ Staging -> base_url=https://staging.example.com, auth_token=sk-...
+ Production -> base_url=https://api.example.com, auth_token=pk-...Reference variables anywhere: server URL, parameters, headers, request body. They resolve at send time.
Reserved keys: timeout (integer, seconds -- default 30), insecure (boolean -- passes --insecure to curl).
Library API
Use apigrip programmatically in your own scripts and tools:
// ESM
import { loadSpec, send, validateBody } from 'apigrip';
// CommonJS
const { loadSpec, send } = await require('apigrip');Quick examples
// Load and inspect a spec
const { spec, endpoints } = await loadSpec('./my-api/');
console.log(`${endpoints.length} endpoints found`);
// Send a request with full validation
const res = await send('./my-api/', 'GET', '/users', {
params: { query: { limit: '10' } },
env: 'staging',
projectDir: './my-api/',
});
console.log(res.status, res.validation);
// Retrieve last cached response
import { loadLastResponse } from 'apigrip';
const cached = loadLastResponse('./my-api/', 'GET', '/users');All exports
| Category | Functions |
|----------|-----------|
| Spec | discoverSpec, parseSpec, extractEndpoints, getEndpointDetails, getRefDeps |
| Request | buildUrl, buildCurlArgs, executeCurl, cancelRequest, checkCurl, shellQuote |
| Environment | loadEnvironments, saveEnvironments, resolveEnvironment, resolveVariables, resolveAllParams, getConfigDir, getProjectHash |
| Validation | validateBody, validateResponse |
| Storage | loadParams, saveParams, saveLastResponse, loadLastResponse, loadProjects, addProject, removeProject, loadPreferences, savePreferences, getGitInfo |
| Project config | loadProjectConfig, applyProjectConfig, getSpecOverride |
| Convenience | loadSpec, send |
Direct core module access is also available: import { parseSpec } from 'apigrip/core/spec-parser.js'
MCP server
Expose the spec to AI coding assistants via the Model Context Protocol:
{
"mcpServers": {
"api": {
"command": "apigrip",
"args": ["mcp", "--project", "/path/to/api"]
}
}
}Tools: list_endpoints, get_endpoint, get_schema, validate_request_body, send_request, get_last_response, list_environments, get_environment, get_project_path, get_spec_path
Resources: spec://parsed, project://info
The MCP server watches the spec file and auto-reloads when it changes, so tools always return current data.
Project structure
apigrip/
├── cli/ CLI entry point and commands
│ ├── index.js Yargs command registration
│ ├── output.js CLI formatting (table, JSON, color)
│ ├── resolve-project.js Shared project context resolution
│ └── commands/ serve, send, curl, list, show, spec, projects, env, last, mcp
├── core/ Shared logic (spec parsing, curl, environments, persistence)
│ ├── spec-discovery.js Find OpenAPI spec in a directory
│ ├── spec-parser.js Parse/dereference specs (2.0, 3.0, 3.1)
│ ├── curl-builder.js Build curl args array
│ ├── curl-executor.js Execute curl subprocess
│ ├── env-resolver.js Load/merge environments, resolve {{ variables }}
│ ├── git-info.js Git status via CLI
│ ├── params-store.js Per-endpoint parameter persistence
│ ├── response-store.js Per-endpoint response caching
│ ├── projects-store.js Project bookmark CRUD
│ ├── preferences-store.js Global + per-project preferences
│ ├── project-config.js .apigrip.json loader and environment seeder
│ └── schema-validator.js JSON Schema validation (ajv)
├── electron/ Electron desktop wrapper
│ └── main.js Main process (Express + BrowserWindow)
├── lib/ Programmatic library API
│ ├── index.js ESM entrypoint (re-exports + loadSpec, send)
│ └── index.cjs CJS compatibility wrapper
├── mcp/ MCP server wiring
│ └── server.js Tools + resources -> core modules
├── server/ Express server, routes, SSE, file watcher
│ ├── index.js Server factory, route mounting
│ ├── spec-watcher.js Chokidar watchers (spec, $ref deps, .git/, .apigrip.json)
│ └── routes/ REST endpoint handlers
├── client/ React frontend (Vite build)
│ ├── components/ TopBar, EndpointList, RequestPanel, ResponsePanel, ...
│ ├── lib/ api.js (HTTP client), sse.js (SSE client)
│ └── styles/ CSS variables (Dracula palette), layout, components
└── test/ Node.js built-in test runner
├── core/ Unit tests for all core modules
├── cli/ CLI command tests
├── server/ Route + SSE integration tests
├── mcp/ MCP server tests
└── fixtures/ Test specs (apigrip-openapi.yaml, petstore-2.0.json)Config is stored at $XDG_CONFIG_HOME/apigrip/ (or ~/.config/apigrip/). Project directories are never written to.
Testing
npm testRuns 814 tests using Node's built-in test runner (node --test). The test suite uses the tool's own OpenAPI spec as a fixture (self-referential testing).
License
ISC
