Add one line. Get OpenAPI docs from real traffic.
EasyDocs watches your API traffic and uses AI to generate accurate, up-to-date OpenAPI 3.0 specs — automatically. No spec files to write, no annotations to maintain.
Route your requests through the EasyDocs proxy. Nothing to install in your project.
npx @easydocs/cli proxy --project=my-api --port=3999Then send requests through the proxy:
http://localhost:3999?target=https://api.example.com/users
npm install @easydocs/expressimport { easydocs } from "@easydocs/express";
app.use(easydocs({ project: "my-api" }));
// all your existing routes stay the samenpm install -D @easydocs/dashboard
npx easydocs dashboard
# → http://localhost:4999Or export to a file:
npx easydocs export > openapi.json
npx easydocs export --yaml > openapi.yaml- Middleware (or proxy) intercepts every request and response
- A background queue feeds the captured data to an AI model — nothing blocks your request
- The AI generates or updates an OpenAPI 3.0 Operation object for that endpoint
- Response-shape hashing skips re-processing when the structure hasn't changed
- Specs are stored in SQLite (default) or Postgres
- The dashboard reads from that database and renders live docs
| Package | Framework |
|---|---|
@easydocs/express |
Express |
@easydocs/fastify |
Fastify |
@easydocs/hono |
Hono |
@easydocs/nestjs |
NestJS |
@easydocs/nextjs |
Next.js (App Router + Pages Router) |
@easydocs/h3 |
h3 / Nitro / Nuxt |
@easydocs/elysia |
Elysia (Bun) |
@easydocs/cli |
Proxy + export (no framework needed) |
Set one environment variable:
# OpenAI (default)
OPENAI_API_KEY=sk-...
# Anthropic
ANTHROPIC_API_KEY=sk-ant-...
# DeepSeek
DEEPSEEK_API_KEY=sk-...
# Ollama (local, no key needed)
# configure in code: easydocs({ ai: { provider: 'ollama' } })EasyDocs auto-detects the provider from your environment. If no key is set, it falls back to Ollama at localhost:11434.
easydocs({
project: "my-api", // separate spec per service, default: 'default'
ai: {
provider: "openai", // 'openai' | 'anthropic' | 'ollama' | 'deepseek'
model: "gpt-4o",
apiKey: "...", // optional, falls back to env vars
},
storage: {
type: "sqlite", // 'sqlite' | 'postgres'
url: "file:./docs.sqlite",
},
capture: {
ignoreRoutes: ["/health", "/metrics"],
includePaths: ["/api"],
},
dashboard: {
autoStart: true, // spawn dashboard on first capture (dev only)
port: 4999,
},
});Scope traffic from different services to separate specs:
// service-a
app.use(easydocs({ project: "users-service" }));
// service-b
app.use(easydocs({ project: "orders-service" }));Switch between projects in the dashboard or scope the export:
npx easydocs export --project=users-service > users.jsonpackages/
core/ ← AI, storage, spec building (shared by all adapters)
express/ ← @easydocs/express
fastify/ ← @easydocs/fastify
hono/ ← @easydocs/hono
nestjs/ ← @easydocs/nestjs
nextjs/ ← @easydocs/nextjs
h3/ ← @easydocs/h3
elysia/ ← @easydocs/elysia
cli/ ← @easydocs/cli
apps/
dashboard/ ← @easydocs/dashboard (docs UI)
test-api/ ← fixture Express app for testing
evals/ ← promptfoo eval harness for AI spec quality
docs/
CICD.md
MISSION.md
ROADMAP.md
adr/ ← Architecture Decision Records
pnpm install
pnpm dev # runs all packages and dashboard in parallel
pnpm build # builds all packages
pnpm lint # lint all packages
pnpm typecheck # typecheck all packages
pnpm test # runs tests across all packages
pnpm eval # runs AI spec quality evals (requires API key)pnpm release # patch bump → tag → publish
pnpm release:minor # minor bump
pnpm release:major # major bumpMIT
