Skip to content

Latest commit

 

History

304 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ApiMesh: Code to OpenAPI Docs, Instantly

Python Version License Docker Build Discord Twitter

Open-source OpenAPI generator. Point it at a repository and it detects the web framework (one LLM call, cached), extracts REST endpoints, and produces a valid OpenAPI 3.0 swagger.json plus a self-contained HTML endpoint catalog you can open in any browser. Routes, methods, and prefixes come from static analysis of code and of the OpenAPI contracts the repo provably serves; the LLM only writes schemas and descriptions, never routes.

Built to be driven by humans or by AI agents: one non-interactive command in, one machine-readable spec out, with honest exit codes and a coverage report inside the spec.

Quick start

Docker (recommended)

cd /path/to/your/repo
docker run --pull always -it --rm -v $(pwd):/workspace \
  -e OPENAI_API_KEY=your_key \
  qodexai/apimesh:latest --api-host https://api.yourservice.com

Interactive prompts only appear on a real terminal; every value can be supplied by flag or environment variable instead. On Linux, if your repo is not owned by UID 1000, add --user "$(id -u):$(id -g)".

Shell script

cd /path/to/your/repo
mkdir -p apimesh && \
  curl -fsSL https://raw.githubusercontent.com/qodex-ai/apimesh/refs/heads/main/run.sh -o apimesh/run.sh && \
  chmod +x apimesh/run.sh && \
  apimesh/run.sh --openai-api-key your_key --api-host https://api.yourservice.com

MCP server

curl -f https://raw.githubusercontent.com/qodex-ai/apimesh/main/swagger_mcp.py -o swagger_mcp.py
{
  "mcpServers": {
    "apimesh": {
      "command": "uv",
      "args": ["run", "/absolute/path/to/swagger_mcp.py"]
    }
  }
}

The file carries inline dependency metadata, so uv run works as-is. The tool takes openai_api_key, repo_path, and an optional api_host, and raises a tool error when generation fails rather than returning a success payload.

For AI agents

Everything is settable without a TTY. A complete non-interactive run:

docker run --pull always --rm -v $(pwd):/workspace \
  -e OPENAI_API_KEY=$OPENAI_API_KEY \
  qodexai/apimesh:latest --api-host https://api.yourservice.com --no-html

Flags (docker image, run.sh, and the Python CLI all accept them):

Flag Effect
--api-host <url> servers[0].url in the spec. Without it, a placeholder is used and a warning printed.
--model <name> OpenAI model for generation. Default: gpt-5.6-terra.
--no-html Write swagger.json only, skip the HTML catalog.
--redetect-framework Forget the cached framework and detect again.
--openai-api-key <key> The key (script and docker wrappers; the env var works everywhere).

Environment variables: OPENAI_API_KEY, APIMESH_API_HOST, APIMESH_OPENAI_MODEL, APIMESH_SKIP_HTML=1, APIMESH_INGEST_SPECS=0 (disable OpenAPI spec ingestion), APIMESH_TELEMETRY=0 (opt out of usage telemetry). Flags beat environment variables beat stored config.

Exit codes:

Code Meaning
0 Spec written (and HTML, unless skipped).
1 Fatal failure, nothing written. Common causes: no endpoints found, no OpenAI key, framework detection or generation errors. The message says which.
2 Spec written, but the requested HTML catalog failed to render.

Outputs, all inside the apimesh/ folder of the scanned repo (docker) or next to it:

File What it is
swagger.json The OpenAPI 3.0 spec.
apimesh-docs.html Self-contained, offline endpoint catalog (search, filters, sort). No server needed.
api_index.json Per-endpoint state for incremental runs (dependencies, content hashes).
config.json Stored key (mode 0600, auto-gitignored), model, host, framework.
metadata_cache/ Content-addressed parse cache; makes reruns cheap. Safe to delete.
repo_profile.json The contract lane's full account: every spec found, served, excluded (with reason) or awaiting confirmation, and the state of every override. Written only when the repo carries OpenAPI documents.

Trust, but verify: every spec carries info.x-apimesh-coverage with endpoints_extracted, generated, skipped_unchanged, and failed counts, plus a contract subblock (specs found/served/excluded, operations, conflicts, whether the sweep was truncated). If failed is nonzero, treat the spec as incomplete: new endpoints that failed are absent, and a changed endpoint that failed may still show its previous operation until a rerun succeeds; rerunning retries just the failed endpoints. Routes are never invented: an operation is present only when a parser proved it in code or a spec this repo provably serves declares it, and each one names its origin in x-apimesh-source. Custom metadata lives in x- extension fields (x-authorization-tag, x-module-tag, x-sensitive-information), so strict OpenAPI validators accept the output.

Supported frameworks

Language Frameworks How
Python Flask, FastAPI, Django (URLconf), Django REST Framework, connexion (spec-first, see below) AST analysis + spec ingestion
Node.js / TypeScript Express (incl. mounted routers), NestJS tree-sitter
Ruby on Rails resources/resource, namespaces, scopes, member/collection, concerns, shallow nesting, engines, split route files tree-sitter
Go gin, echo, chi, fiber, gorilla/mux, net/http (incl. Go 1.22 patterns), oapi-codegen (spec-first, see below) tree-sitter + spec ingestion
Java Spring annotation-based controllers (@RestController, @RequestMapping, verb mappings) and OpenAPI-first codebases (see below) tree-sitter + spec ingestion

Anything else yields an honest zero (exit 1, nothing written). ApiMesh never asks an LLM to guess routes: a guessed route set can include third-party client calls and paths nobody serves, which poisons every consumer of the spec.

OpenAPI-first repositories

Many codebases keep their API in OpenAPI YAML/JSON files and generate or register the serving code from them, so the routing never appears in committed handlers. ApiMesh reads those spec files directly, but only after proving this repo serves them. The accepted proofs: a live Maven, Gradle or Bazel build step naming the spec as input to a server-mode generator (spring, kotlin-spring, delegate pattern included); a //go:generate oapi-codegen directive with a server flavor whose generated output is committed; or a connexion app.add_api("spec.yaml") registration in application code. Profile-gated plugins and go:generate directives without committed output are provisional: the spec is listed as a candidate for confirmation, never served on a hint. Vendored specs of third-party APIs (client generation, gateway upstreams, stale documentation files) are excluded, each with its reason in repo_profile.json. Spec content (schemas, parameters, descriptions) passes through as authored, at zero LLM cost, with references rewritten onto per-spec namespaced components.

A spec ApiMesh cannot prove either way is listed as a candidate with an eligibility_hash. To confirm one, commit .apimesh-overrides.json at the repo root:

{
  "specs": [
    {"path": "specs/internal-api.yaml", "action": "include", "eligibility_hash": "<from repo_profile.json>", "prefix": "/api"},
    {"path": "vendor/partner.yaml", "action": "exclude", "reason": "partner's API, not ours"}
  ]
}

exclude always applies. include activates only while the hash matches the current spec, build files and implementing controllers, and goes dormant (reported) the moment that evidence changes.

How it works

  1. Detect the framework (cached after the first run).
  2. Extract endpoints: deterministic parsers own routes, methods, and prefixes; the contract lane ingests OpenAPI specs the repo provably serves; overlapping routes are documented from the spec, not generated twice.
  3. Generate schemas and descriptions with the LLM for code-proven endpoints only, batched per source file under a hard token budget, with per-endpoint failure isolation.
  4. Rerun cheaply: unchanged endpoints are skipped via content hashes, edits to shared helpers invalidate their dependents, failed endpoints retry automatically, and the spec-sourced portion is rebuilt deterministically every run.

Only two things leave your machine: source context sent to the OpenAI API for schema generation, and anonymous usage telemetry (an install UUID and run timings, disable with APIMESH_TELEMETRY=0). Nothing is created inside your repository except the apimesh/ output folder.

Contributing

See CONTRIBUTING.md for the dev setup, test suite, and PR checklist. Issues and PRs welcome, especially framework coverage.

About

Auto-generate OpenAPI 3.0 specs + interactive HTML API UI from your codebase — in seconds.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

324 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages