specdrift-cli
v0.1.0
Published
Check a live API against its own OpenAPI spec and report drift: undocumented status codes, missing required fields, and type mismatches.
Maintainers
Readme
specdrift
Point it at a live API and its own OpenAPI spec. It tells you where they've drifted apart. Free, zero-dependency, MIT-licensed, GET-only.
What it does
For every GET operation in your OpenAPI 3.x spec, specdrift:
- builds a real request from the spec's own declared parameter examples/defaults (path and query params — it never guesses a value that isn't in the spec),
- calls your live API,
- compares the actual response against the spec: status code declared?
required fields present? field types matching (
string/number/integer/boolean/array/object)? any undeclared extra fields?
...and prints a plain-text report. Nothing is mutated, nothing is stored, nothing is sent anywhere except your own API.
Safety note: specdrift only ever sends GET requests. It will not call
POST/PUT/PATCH/DELETE on your API, even if your spec declares them —
running an unattended tool against arbitrary mutating endpoints on someone's
live system is a real risk, not a hypothetical one, so v1 deliberately
doesn't do it.
Usage
Not yet published to npm, so for now, clone and run directly:
git clone https://github.com/MattBridges/specdrift.git
cd specdrift/cli # if running from this monorepo path, otherwise cli/ is the root
node bin/specdrift.js path/to/openapi.json https://api.example.comspecdrift <spec.json> <baseUrl> [--path <regex>] [--timeout <ms>]<spec.json>— a local path or URL to an OpenAPI 3.x JSON document (YAML is a known v1 gap — see below, it fails loudly rather than silently misparsing).<baseUrl>— the live API to check.--path <regex>— only check paths matching this regex.--timeout <ms>— per-request timeout, default 10000.
Exit codes: 0 = no drift found, 1 = drift found in at least one
endpoint, 2 = specdrift itself couldn't run (bad spec, no checkable
endpoints, etc.) — matches the convention used across United Front Labs'
other free CLIs (see
d1-migration-guard) so
CI usage (specdrift ... || exit 1) is predictable across tools.
Requires Node.js >= 18 (uses the built-in fetch). Zero npm dependencies.
Example
$ specdrift openapi.json https://api.example.com
specdrift: checking 3 GET endpoint(s) against https://api.example.com
OK GET /widgets -- 200 matches spec (declared: 200)
DRIFT GET /widgets/{id} -- 200 (matched "200")
$.price: type mismatch -- spec declares "number", actual response has "string"
info $.sku: field present in actual response but not declared in spec
SKIP GET /orders/{id} -- path parameter "id" has no example/default value to substitute
specdrift: 2 checked, 1 with drift, 1 skipped, 0 request error(s).Status: v0.1, verified against real behavior
Verified end-to-end with a local fixture HTTP server (test/fixtures/) run
under a real Node process, in two modes: a spec-conformant server (expect
exit 0, zero findings) and a deliberately drifted one (missing required
field, extra undeclared field, wrong field type, and an undeclared status
code — all four correctly detected with the right exit code). Not tested
against every real-world OpenAPI dialect quirk (e.g. oneOf/anyOf/
allOf, nullable, deep array recursion beyond the first item) — those are
either skipped safely (no false "drift") or a documented gap, not silently
mishandled.
Known v1 limitations (documented, not hidden)
- OpenAPI JSON only — no YAML parsing (adding a real YAML parser without a dependency is nontrivial; a "known gap" beats a buggy hand-rolled parser).
- GET-only — no coverage of mutating operations, by design (see Safety note above).
- Path/query parameters need an
example,schema.example,schema.default, orschema.enumin the spec to be tested; parameters with none of those are skipped and reported asSKIP, not silently dropped or guessed. - Object/array schema comparison recurses up to 3 levels deep and checks only the first item of an array — enough to catch the drift that actually happens in practice (renamed/removed/retyped fields), not a full JSON Schema validator.
oneOf/anyOf/allOf/nullableand other advanced JSON Schema keywords are not evaluated (no false positives — those fields are simply not checked, and this is expected v1 behavior, not a hidden bug).
Why this exists
This CLI is a free companion to SpecDrift, a hosted contract-drift monitor concept (continuous checks + AI-written plain-language change summaries posted to Slack/PR comments). The free CLI gives you a real, usable one-shot check today with zero signup; the hosted version (still pre-launch, waitlist here) would run this continuously and explain why drift matters, not just that it happened.
License
MIT
