npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@didrod2539/apilint

v0.1.0

Published

Lint OpenAPI (Swagger) 3.x specs for quality & consistency: broken $refs, missing responses/descriptions/examples, duplicate operationIds, REST naming, undeclared path params, security gaps. Deterministic CLI, JSON/Markdown reports, zero-config, no networ

Downloads

25

Readme

🧩 apilint

Lint your OpenAPI specs for quality & consistency — zero-config, no browser.

npm version CI node license

A deterministic CLI that lints OpenAPI (Swagger) 3.x specs for design quality and consistency — broken $refs, missing responses/descriptions, duplicate operationIds, undeclared path params, REST naming, security gaps — with a score, A–F grade, and JSON/Markdown reports. Works on JSON and YAML, with a built-in parser (no heavyweight deps).


One-line summary

apilint reads your openapi.yaml/.json, runs 25+ opinionated quality rules, and reports issues with locations, fixes, and a score you can gate in CI — no config required, nothing uploaded.

Why this project exists

Your OpenAPI spec is the single source of truth for your API: docs, SDKs, mock servers, partner integrations and client code are all generated from it. But hand-written or code-generated specs drift into a mess:

  • A $ref points at a schema that was renamed — SDK generation breaks.
  • An endpoint has no documented response (or no error response) — consumers can't handle it.
  • Two operations share an operationIdgenerated client methods collide.
  • Paths like /getUserList/ mix verbs, casing and trailing slashes — an inconsistent API that's painful to use and impossible to standardize.

The tool everyone reaches for, Spectral, is powerful but has a real learning curve and ruleset configuration overhead. apilint is the opinionated, zero-config alternative: install, run, get a graded report. It's deterministic and static, so it drops straight into CI.

Key features

  • 🔗 Structure$ref integrity, OpenAPI version, paths present.
  • 🧱 OperationsoperationId presence/uniqueness, summaries, tags, and success and error responses.
  • 🧭 Parameters — every {templated} path segment must be declared; missing descriptions flagged.
  • 🏷️ Naming — REST conventions: no verbs in paths, kebab-case segments, no trailing slashes, operationId casing.
  • 🔐 Security — security schemes defined; operations require auth (toggle).
  • 📝 Docs quality — info metadata, response/parameter/schema descriptions.
  • 📊 Score + A–F grade per category and overall.
  • 📄 JSON & Markdown export, colored console output, CI gate exit codes.
  • 🧰 JSON + YAML input via a small built-in parser. Deterministic & offline.

Install

# run without installing
npx @didrod2539/apilint scan openapi.yaml

# or install
npm install -g @didrod2539/apilint    # global CLI (provides `apilint`)
npm install -D @didrod2539/apilint    # project dev-dependency (for CI)

Node ≥ 18. ESM + CJS + TypeScript types.

Quick start

apilint scan openapi.yaml
openapi.yaml  85/100 (B)  Messy API
  3 paths · 4 operations · 1 schemas · 0 tags
  Document structure    90
  Operations            74
  Parameters            70
  ...

  ✗ Broken $ref "#/components/schemas/MissingSchema" (paths./getUserList/.get…)
  ✗ Duplicate operationId "FetchProfile" (paths./user_profiles/{id}.post)
  ✗ Path parameter "{id}" in GET /user_profiles/{id} is not declared
  ⚠ Path "/getUserList/" has a trailing slash → Use "/getUserList".

Overall  85/100 (B)  7 error(s), 11 warning(s), 13 info

CLI usage

apilint scan [...targets]     # lint spec files or directories
apilint report <input.json>   # re-render a saved JSON report as Markdown
apilint init                  # scaffold apilint.config.json
apilint --help
apilint --version

scan options:

| Option | Description | | --- | --- | | --config <file> | Path to a config file (otherwise auto-detected) | | --json <file> | Write a JSON report | | --md <file> | Write a Markdown report | | --min-score <n> | Exit non-zero if any spec scores below this (CI gate) | | --quiet | Hide info-level issues in the console |

Pointed at a directory, scan finds files named like *openapi*/*swagger*/ *api*.{json,yaml,yml} recursively.

Example result

Full reports for the bundled sample spec are in examples/sample-report.md and examples/sample-report.json.

📸 Screenshot / demo GIF placeholder: ./docs/screenshot.png — record the terminal running npx @didrod2539/apilint scan examples/petstore-bad.yaml.

Configuration

Create apilint.config.json (or run apilint init):

{
  "requireSecurity": true,
  "requireTags": true,
  "operationIdStyle": "camelCase",
  "minScore": 80,
  "disableCategories": [],
  "disableRules": ["path-kebab-case"],
  "ruleSeverity": { "operation-tags": "warning" },
  "categoryWeights": { "structure": 1.4, "responses": 1.2 }
}

| Field | Meaning | | --- | --- | | requireSecurity | Flag operations with no security (and no global default) | | requireTags | Flag untagged operations | | operationIdStyle | camelCase, snake_case, or any | | minScore | CI gate threshold (overridable with --min-score) | | disableCategories | Skip whole categories | | disableRules | Skip individual rules by id | | ruleSeverity | Override severity per rule id | | categoryWeights | Re-weight categories in the overall score |

Categories: structure, info, paths, operations, parameters, responses, schemas, security, naming. See src/types.ts for the full rule-id list.

Real-world use cases

  1. Gate API quality in CI. Add apilint scan openapi.yaml --min-score 85. A PR that introduces a broken $ref or a duplicate operationId fails before it breaks SDK generation downstream.
  2. Standardize a team's API style. Set operationIdStyle and naming rules in apilint.config.json, commit it, and every new endpoint is held to the same conventions automatically.
  3. Audit an inherited or generated spec. Run apilint scan ./spec --md api-audit.md for a graded, per-category report of what's missing or inconsistent before you publish docs or a client SDK.

Programmatic API

import { analyze, toMarkdown } from "@didrod2539/apilint";

const report = analyze(yamlOrJsonText, config, { source: "openapi.yaml" });
console.log(report.score, report.grade, report.issues);
await fs.writeFile("api.md", toMarkdown(report));

Roadmap

  • More rules: example/requestBody coverage, response media types, enum/format hygiene, unused components, consistent error schema.
  • Resolve external $refs (other files / URLs, opt-in).
  • SARIF output for code-scanning integration.
  • A GitHub Action with PR annotations on changed operations.
  • Custom rule plugins and shareable config presets.
  • OpenAPI 3.1 / JSON Schema 2020-12 specific checks.

FAQ

Is this a Spectral replacement? For most teams' needs, yes — apilint ships an opinionated default ruleset with no configuration. Spectral is more extensible (custom DSL rules); apilint trades that for zero-config simplicity, a score/grade, and a tiny dependency footprint.

Does it need a network or a browser? No. It parses JSON/YAML with a built-in parser and runs entirely locally — no API key, no uploads.

Does it validate against the full OpenAPI JSON Schema? It focuses on high-value design-quality rules (the things that actually break SDKs, docs and consumers), not exhaustive schema validation. Use it alongside a strict validator if you need byte-level conformance.

Why a hand-written YAML parser? To stay dependency-light and deterministic. It supports the YAML subset OpenAPI specs use (block mappings/sequences, scalars, quotes, flow collections, block scalars). If your spec uses exotic YAML, convert to JSON.

My spec scored lower/higher than expected — can I tune it? Yes. disableRules, ruleSeverity, categoryWeights, and the require* toggles all change what's flagged; --min-score decides what fails CI.

Contributing

Contributions welcome! Each check is a small, self-contained rule in src/rules/. See CONTRIBUTING.md and the Code of Conduct.

git clone https://github.com/didrod205/apilint.git
cd apilint
npm install
npm test
npm run build
node dist/cli.js scan examples/petstore-bad.yaml

License

MIT © apilint contributors

💖 Sponsor

apilint is free, MIT-licensed, and built in spare time. If it caught a spec bug before it broke your SDK build, please consider supporting it:

Where your support goes: more rules, external $ref resolution, SARIF output, a PR-annotating GitHub Action, custom rule plugins, and fast issue responses.