Swagger CLI: Validate, Lint, and Test Your API Spec From the Terminal

Use the Swagger CLI to validate and bundle your OpenAPI spec from the terminal, lint it with Redocly CLI, and run real API tests in CI with apidog-cli.

INEZA Felin-Michel

INEZA Felin-Michel

16 June 2026

Swagger CLI: Validate, Lint, and Test Your API Spec From the Terminal

Apidog for Enterprise

On-Premises Deploy

SSO & RBAC

SOC 2 Compliant

Explore Apidog Enterprise

You opened a pull request, the docs built fine, and three days later a teammate pings you: the staging server rejects every request because the OpenAPI file has a dangling $ref that points at a path you renamed. The spec looked correct in the editor. It rendered in Swagger UI. It just was not actually valid, and nothing in your pipeline caught it before it shipped.

That is the exact job a Swagger command-line tool is built for: catch broken specs before a human does. The phrase “swagger cli” usually points at @apidevtools/swagger-cli, a small npm package whose two commands, validate and bundle, check an OpenAPI document and stitch multi-file specs into one. It is a genuinely useful tool, and this guide shows you how to use it properly. It also shows you where it stops, because validating a spec is only the first half of trusting an API; the second half is sending real requests and asserting on what comes back, and that is where a runner like the Apidog CLI takes over.

button

So this is really two terminals’ worth of work. First, lint and bundle the spec with swagger-cli (or its successor) so the contract is sound. Then run actual tests against the running API from the command line so you know the implementation matches the contract. We will cover both, be honest about which tool owns which job, and give you copy-paste commands for each.

What “swagger cli” actually refers to

There is no single official binary called “swagger.” The name maps to a few different tools, and knowing which one you mean saves a lot of confusion.

This guide is about the command-line work: validating, bundling, linting, and then testing. If you want a broader survey of design-and-test platforms instead, the Swagger alternatives roundup covers the GUI side.

Installing swagger-cli

The tool ships as an npm package. Install it globally:

npm install -g @apidevtools/swagger-cli

Confirm it resolved:

swagger-cli --version
swagger-cli --help

Node.js is the only system dependency. Any machine or CI image with Node already installed can run it. If you would rather not install it globally, you can call it on demand with npx @apidevtools/swagger-cli ..., which is handy on ephemeral build runners.

One thing to know before you lean on it: the maintainers have marked swagger-cli as deprecated. The README says it plainly, citing the maintenance burden of a large userbase with few contributors. It still works, and plenty of pipelines run it today, but new projects are pointed at Redocly CLI as the actively maintained successor. We cover that migration in its own section below, so you can decide with eyes open.

Validating a spec with swagger-cli

The headline command is validate. Point it at your spec file:

swagger-cli validate openapi.yaml

If the document is sound, you get a one-line confirmation and an exit code of 0. If something is wrong, you get an error describing the problem and a non-zero exit code, which is exactly what you want in a pipeline.

validate runs two checks under the hood, and you can switch either off:

swagger-cli validate --no-schema openapi.yaml
swagger-cli validate --no-spec openapi.yaml

--no-schema skips validation against the OpenAPI JSON Schema, the structural check that confirms your document has the right shape. --no-spec skips validation against the specification rules themselves, the semantic check that catches things like duplicate operation IDs or a $ref that points nowhere. Most of the time you want both on, which is the default. The flags exist for the rare case where one layer is flagging something you have a deliberate reason to allow.

What validate catches well: malformed YAML, missing required fields, broken $ref pointers, and structural mistakes that make a spec unparseable. What it does not do is enforce your team’s style. It will happily pass a spec with no descriptions, inconsistent naming, and no examples, because none of that breaks the OpenAPI rules. For that kind of opinionated check you need a linter, which is the next section.

If validation is the only thing you came for, the deeper walkthrough on how to validate OpenAPI specs compares several tools and edge cases worth knowing.

Bundling a multi-file spec

Real specs rarely live in one file. You split schemas into a components/ directory, reference them with $ref, and keep the root file readable. That is good hygiene, but a lot of downstream tools want a single self-contained document. The bundle command flattens the tree:

swagger-cli bundle openapi.yaml -o dist/openapi.bundled.yaml -t yaml

The flags worth knowing:

The distinction between plain bundle and --dereference matters. A normal bundle keeps internal $ref pointers but pulls all the separate files into one, so the document is portable. --dereference resolves every reference into inline objects, which blows up the file size but guarantees no consumer ever has to resolve a pointer. Use the plain bundle for distribution and the dereferenced form only when a specific tool demands it.

A common pattern is to validate and bundle in one step as part of a build:

swagger-cli validate openapi.yaml && swagger-cli bundle openapi.yaml -o dist/openapi.json

The && means the bundle only runs if validation passes, so a broken spec never produces a build artifact.

Wiring swagger-cli into CI

Validation is most valuable when it runs on every change, not when someone remembers. Drop it into your pipeline as a fast gate. Here is a GitHub Actions step that fails the build on an invalid spec:

name: Validate OpenAPI spec

on:
  pull_request:
    paths:
      - 'openapi.yaml'
      - 'components/**'

jobs:
  validate-spec:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - name: Validate spec
        run: npx @apidevtools/swagger-cli validate openapi.yaml

Because swagger-cli validate exits non-zero on a bad spec, the step turns red and the pull request shows a failing check. No extra configuration. The paths filter keeps the job from running when the spec did not change, which keeps your CI minutes down.

This is the cheapest quality gate you can add to an API repo. It costs seconds and it stops a whole class of “the docs lied” bugs from reaching anyone downstream.

When you need linting, not just validation

Validation answers one question: is this a legal OpenAPI document? Linting answers a harder one: is this a good OpenAPI document by our team’s standards? Those are not the same, and swagger-cli only does the first.

Say your style guide requires every operation to have a summary, every property to have a description, and every path to use kebab-case. A spec can violate all three and still pass swagger-cli validate, because none of those rules are part of the OpenAPI specification. A linter lets you encode and enforce them.

This is the main reason teams move to Redocly CLI, the maintained successor that swagger-cli itself points you toward. It covers the same validation and bundling, then adds a real linting engine on top.

Migrating to Redocly CLI

The migration is small because the command names are close. Install the successor:

npm install -g @redocly/cli

The validate equivalent is lint. To match the old behavior closely, extend the minimal ruleset:

redocly lint --extends=minimal openapi.yaml

Run it with the default ruleset instead and it enforces a stronger set of recommended rules, which is where the linting value shows up. You configure rules in a redocly.yaml file, set each one to error or warn, and even write custom plugins for organization-specific checks.

Bundling maps almost one for one:

redocly bundle openapi.yaml -o dist/openapi.yaml

The flag names shift slightly. swagger-cli’s -o/--outfile becomes --output, -t/--type becomes --ext, and -r/--dereference becomes -d/--dereferenced. If your old scripts used the short flags, a quick find-and-replace gets you there. For a wider comparison of spec-checking tools, the best OpenAPI validator tools breakdown puts Redocly next to the alternatives.

The short version: if you are starting fresh, reach for Redocly CLI. If you have an existing swagger-cli step that works, there is no fire, but the path forward is clear and the rename is mechanical.

The half a spec tool cannot cover

Here is the limit of every tool we have discussed so far. swagger-cli validate confirms your spec is well-formed. redocly lint confirms it follows your style. Neither one sends a single request to your running API. A spec can be perfect on paper while the implementation returns a 500, omits a field it promised, or ignores a query parameter entirely.

Closing that gap means functional testing: send a real request to a real endpoint, then assert on the status code, the response body, and the values inside it. That is a different category of tool, and it is where Apidog fits the workflow.

Apidog is an all-in-one API platform. You import your OpenAPI spec, and from that one definition you get interactive docs, a mock server, and test scenarios you can chain together with assertions, all without leaving the workspace. Importing is direct; the guide on importing Swagger or OpenAPI and generating runnable requests walks through it, and you can generate full test collections straight from the spec instead of hand-building them.

The piece that matters for the terminal is the command-line runner, published as the apidog-cli npm package. You install it and run a saved scenario headlessly:

npm install -g apidog-cli
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r cli

The -t flag is the test scenario ID, -e is the environment ID, and -r chooses report formats such as cli, html, json, or junit. Like swagger-cli, it exits with a clean status code, so a failing assertion turns the pipeline red. Unlike swagger-cli, what it is checking is the live behavior of your API, not just the shape of the file that describes it. For the complete flag reference and CI examples, see the Apidog CLI complete guide, or run apidog run --help for the current options. If you want to set up that first scenario, download Apidog, import your spec, and the runner command is one copy from the scenario’s CI/CD tab.

A complete terminal workflow

Put the two halves together and you get a pipeline that checks the contract and the implementation in sequence:

# 1. Is the spec well-formed and on-style?
redocly lint --extends=minimal openapi.yaml

# 2. Produce a single distributable document.
redocly bundle openapi.yaml -o dist/openapi.yaml

# 3. Does the running API actually match the contract?
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r junit

Step one fails fast on a malformed or off-style spec. Step two produces the artifact your docs and SDK generators consume. Step three sends real traffic and asserts on the responses, so a green build means both the contract and the code behind it are sound. Each step exits non-zero on failure, so the whole chain is a single gate you can drop into any CI runner that has Node.

If your testing today relies on a spec-conformance tool that has gone quiet, the write-up on validating an API against its spec without Dredd covers the same contract-versus-implementation idea from a different angle.

A note on swagger-codegen

People searching for a “swagger cli” sometimes actually want swagger-codegen, which is a different tool with a different job. It reads an OpenAPI spec and generates client SDKs, server stubs, and documentation in dozens of languages. It is genuinely useful for bootstrapping a typed client from a published spec, and it is fair to call it the most capable code-generation option in the Swagger family.

It does not validate, lint, or test in the sense this article covers. Generation assumes you already have a sound spec; if the input is broken, the output is broken in matching ways. So even in a codegen workflow, you still want a validate or lint step in front of it. The tools complement each other rather than replacing one another.

button

Explore more

How to Run API Tests Without Tavern's YAML Boilerplate

How to Run API Tests Without Tavern's YAML Boilerplate

Tavern writes API tests as pytest YAML. See a fair comparison and a no-YAML alternative: build tests against your spec and run them headlessly with the Apidog CLI.

16 June 2026

How to Use the Apidog CLI in Cursor

How to Use the Apidog CLI in Cursor

Teach Cursor your API testing workflow with a .cursor/rules file, then have its Agent run apidog run and read the result. Plus the optional Apidog MCP server.

16 June 2026

The Best OpenAPI Linter Setup for Consistent API Design in 2026

The Best OpenAPI Linter Setup for Consistent API Design in 2026

Compare OpenAPI linter options (Spectral, Redocly, Vacuum) and wire up a setup across editor, pre-commit, and CI for consistent, contract-tested API design.

16 June 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs

Swagger CLI: Validate, Lint, and Test Your API Spec From the Terminal