Skip to content

Lint, bundle, and ship APIs. Any spec, any pipeline.

The open-source CLI that turns API governance from a bottleneck into part of everyday work.

$ npm i -g @redocly/cli@latest
redocly lint openapi.yaml
validating openapi.yaml...
[1] openapi.yaml:27:9 struct
Property `desciption` is not expected here.
Did you mean: description ?
[2] openapi.yaml:31:7 operation-4xx-response
Operation must have at least one `4XX` response.
โœ— Validation failed with 1 error and 1 warning.
# exits 1 โ†’ the merge waits for a fix
redocly bundle openapi/openapi.yaml \
--output dist/openapi.yaml
bundling openapi/openapi.yaml...
โœ“ Created a bundle for openapi/openapi.yaml
at dist/openapi.yaml 61ms
# 48 files, 212 $refs โ†’ one file to publish
redocly lint dist/openapi.yaml
Woohoo! Your API description is valid.
# same rules as your laptop, on every pull request
npx @redocly/cli lint openapi.yaml \
--format github-actions
npx @redocly/cli bundle openapi.yaml \
--output dist/openapi.yaml
::error file=openapi.yaml,line=27,col=9::Property "desciption" is not expected here.
# exits 1 โ†’ the PR is blocked before review

Great APIs start from shared standards

Redocly CLI speaks OpenAPI, AsyncAPI, Arazzo, and more natively, so staying close to the spec just happens while you work.

cafe.yamlโœ“ valid
swagger: '2.0'info:  title: Redocly Museum API  version: 1.1.1basePath: /v1.1paths:  /museum-hours:    get:      operationId: getMuseumHours      responses:        '200':          description: Success.
openapi: 3.0.3info:  title: Redocly Cafe  version: 1.0.0paths:  /orders:    post:      operationId: createOrder      responses:        '201':          description: Created
openapi: 3.1.1info:  title: Redocly Cafe  version: 1.0.0webhooks:  orderReady:    post:      operationId: onOrderReady      responses:        '200':          description: OK
openapi: 3.2.0info:  title: Redocly Cafe  version: 1.0.0servers:  - url: https://api.cafe.redocly.compaths:  /menu:    get:      summary: List all menu items      operationId: listMenuItems
asyncapi: 2.6.0info:  title: Redocly Museum API  version: 1.1.1channels:  special-events/created:    subscribe:      operationId: onSpecialEventCreated      message:        name: SpecialEventCreated        payload:          type: object
asyncapi: 3.0.0info:  title: Redocly Cafe Order Events  version: 1.0.0channels:  orderPlaced:    address: cafe.orders.placedoperations:  publishOrderPlaced:    action: send
arazzo: 1.0.1info:  title: Redocly Cafe Orders  version: 1.0.0sourceDescriptions:  - name: cafe-api    type: openapi    url: cafe.yamlworkflows:  - workflowId: place-order
{  "openrpc": "1.3.2",  "info": { "title": "Redocly Cafe", "version": "1.0.0" },  "methods": [    {      "name": "listMenuItems",      "params": [],      "result": { "name": "menu", "schema": { "type": "array" } }    }  ]}
overlay: 1.0.0info:  title: Public Cafe API  version: 1.0.0extends: 'cafe.yaml'actions:  - target: $.paths['/revenue']    description: Hide the internal revenue endpoint    remove: true
type Query {  menu(category: MenuCategory): [MenuItem!]!}type MenuItem {  id: ID!  name: String!}

Consistent APIs, from first draft to production

Redocly CLI structures, lints, and tests your API descriptions against the standards your organization sets. The same checks run for every team and every repo.

Validate and evaluate APIs and Markdown against your standards

Pick a built-in ruleset, adjust any rule, and extend it with custom rules. The same rules run on your laptop and in CI, so problems surface in review, before they reach production. Each error points to the exact line in your file, shows it in a code frame, and suggests a fix where possible.

recheck lints the Markdown beside your API for structure and prose, and --fix repairs what it can.

$ redocly lint openapi.yaml --format=codeframe

[1] openapi.yaml:9:7 at #/paths/~1orders/get/desciption

Property `desciption` is not expected here.
Did you mean: description ?

 8 |   summary: List orders
 9 |   desciption: Returns all orders
   |   ^^^^^^^^^^
10 |   operationId: listOrders

Error was generated by the struct rule.

โŒ Validation failed with 1 error.
$ redocly lint openapi.yaml --format=json

{
  "totals": { "errors": 1, "warnings": 0, "ignored": 0 },
  "problems": [{
    "ruleId": "struct",
    "severity": "error",
    "message": "Property `desciption` is not expected here.",
    "suggest": ["description"],
    "location": [{ "pointer": "#/paths/~1orders/get/desciption",
      "start": { "line": 9, "col": 7 } }]
  }]
}
$ redocly lint openapi.yaml --format=junit

<testsuites name="redocly lint" tests="1" errors="1" failures="0">
  <testsuite name="openapi.yaml" tests="1" errors="1">
    <testcase classname="struct" file="openapi.yaml" line="9">
      <error message="Property `desciption` is not expected here.">
        Rule: struct ยท Line: 9 ยท Column: 7
      </error>
    </testcase>
  </testsuite>
</testsuites>
$ redocly lint openapi.yaml --format=github-actions

::error title=struct,file=openapi.yaml,line=9,col=7,endLine=9,endColumn=17::Property `desciption` is not expected here.%0A%0ADid you mean: description ?

# shows up as an annotation on the pull request diff
$ redocly recheck docs

๐Ÿ“‹ Found 2 issue(s):

single-h1  docs/index.md:5:1  Multiple top-level headings in the same document
no-trailing-spaces  docs/index.md:3:27  Trailing spaces [fixable]

1 of 2 fixable with --fix

โŒ Found 2 error(s).

Keep API descriptions manageable at any size

Split a large description into files people can review, then bundle them into one file to publish. join merges several APIs into one, and stats shows what is inside any API.

$ redocly split openapi.yaml --outDir openapi โœ“ 3,214 lines โ†’ 33 paths, 64 schemas
$ redocly bundle openapi.yaml -o dist/openapi.yaml โœ“ 48 files โ†’ dist/openapi.yaml 61ms
$ redocly join orders.yaml payments.yaml -o api.yaml โœ“ 2 descriptions โ†’ api.yaml
$ redocly stats openapi.yaml 57 operations ยท 64 schemas ยท 33 paths ยท 9 tags

Correctness doesn't stop at the description

Linting checks what your API says. Respect checks what it does: write or generate test workflows in Arazzo, an open standard, and run them against a live server.

drift compares recorded traffic, such as the HAR file from a respect run, with the description and flags undocumented endpoints and schema mismatches.

$ redocly generate-arazzo openapi.yaml --with-ai โœ“ generated auto-generated.arazzo.yaml
$ redocly respect auto-generated.arazzo.yaml --har-output traffic.har โœ“ GET /menu 200 ยท schema ok โœ— POST /orders 201 ยท `eta` not in docs 1 of 2 steps failed
$ redocly drift traffic.har --api openapi.yaml Exchanges: total=2 documented=2 undocumented=0 โœ– Undocumented response field "eta" in POST /orders

Generate typed clients from the description

generate-client turns one OpenAPI description into typed clients in TypeScript, Python, Go and PHP, plus a command-line client.

eject-generator copies a generator into your repo as editable source. Change the generator, not its output.

$ redocly generate-client openapi.yaml -o src/client.ts --generator typescript --generator python --docs Client successfully generated: 4 files (104882 bytes) at src/client.ts
$ redocly eject-generator python Ejected the "python" generator to generators/python/. Your agent's skills: .claude/skills/python-generator/SKILL.md

Ready for AI agents

Agents call your API on their own, guided only by its OpenAPI description.
Redoclyย CLI closes that gap, so agents and your API work together.

Find what makes agents fail. score rates an OpenAPI 3.x description from 0 to 100 for how easily AI agents and LLM-based tools can call the API. Ten subscores and a ranked list of hotspot operations show where it breaks, such as missing examples or anyOf without a discriminator. Use --format=json as a CI gate.

Write down what your MCP server can do. Agents find its tools at runtime, people can't. introspect-mcp asks the running server and records its tools, prompts and resources in the x-mcp extension of your OpenAPI description. --check fails CI when the description falls behind.

npx skills add

Teach your coding assistant the CLI. Agent skills are instruction files that AI coding assistants such as Claude Code read before they work. redocly-cli covers everyday use and redocly-lint-rules helps you write your rules. Two more skills set up and run recheck on your Markdown. Add them with npx skills add https://redocly.com.

Draft a description from traffic. generate-spec infers an OpenAPI description from recorded HTTP traffic. With --with-ai, it hands the draft to the Claude, Codex or Cursor CLI on your machine to refine.

Install Redocly CLI

Install it globally, or try it once with npx.

  • Node.js 22.12+ or 20.19+
  • Works on macOS, Linux, Windows
  • No account required for open source features
$ npm i -g @redocly/cli@latest$ redocly lint openapi.yamlโœ“ Your API description is valid.
$ pnpm add -g @redocly/cli@latest$ redocly lint openapi.yamlโœ“ Your API description is valid.
$ npx @redocly/cli@latest lint openapi.yamlโœ“ Your API description is valid.

Runs once without a global install.

$ brew install redocly-cli$ redocly lint openapi.yamlโœ“ Your API description is valid.

The Homebrew formula is maintained by the community.

$ docker pull redocly/cli$ docker run --rm -v $PWD:/spec redocly/cli lint openapi.yamlโœ“ Your API description is valid.

Built into the workflow
you already have

Redocly CLI runs in your terminal, in CI, and in Docker, and it behaves the same way in each.

One config, everywhere

Rulesets, rule overrides, and API definitions live in one redocly.yaml. The Redocly VS Code extension reads that file too, so you see the same errors inline as you type.

No bundling step

Point it at your entry file and it lints the whole multi-file description. Quick enough to run on every commit.

$ redocly lint openapi.yaml
# 48 files, 212 $refs, no bundle step
openapi.yaml: validated in 61ms
โœ“ Your API description is valid.

Fits your existing CI/CD

Add one line to the pipeline you already have. The rules you run locally now gate every pull request, with no new service to set up.

.github/workflows/api.yml
steps:
- uses: actions/checkout@v4
- run: npx @redocly/cli lint openapi.yaml --format=github-actions

Docs-as-code

API descriptions and config live in Git next to your code. Every change goes through a pull request, gets reviewed, and can be rolled back.

my-service/
โ”œโ”€ src/
โ”œโ”€ openapi/
โ”‚ โ””โ”€ openapi.yaml
โ””โ”€ redocly.yaml
# every change goes through a pull request

See it as you build it

Preview your docs locally with live reload. Build a standalone HTML file with Redoc CE, our open-source renderer, and host it anywhere. No account needed.

Publish to Reunite

Push validated descriptions to Reunite for a preview on every branch and a production deploy on merge. Scorecards check each API's compliance level before it goes live.

Built in the open,
running in pipelines

MIT LicenseOpenAPI Initiative

Redocly CLI is MIT-licensed and developed in public on GitHub. The rules behind your API governance are code you can read and run anywhere, from one repo to many.

90+built-in rules
2.5M+weekly npm downloads
6API spec formats
1.5KOpen source on GitHub

API teams shipping with Redocly

  • GitHub
  • GitLab
  • Adobe
  • Intercom
  • Brex

Start with one API.
Scale to every team.

Open source and MIT-licensed. Run your first lint today, then roll the same rules out to every team when you're ready.

  1. $ npm i -g @redocly/cli@latestRedocly CLI install guide
  2. Take it to every team with Reunite

    Preview every branch and check each API's compliance level before it goes live.