Skip to content
Back to skills

Api Diff

ASecurity

Diff an OpenAPI spec across commits and classify each change as major/minor/patch per SemVer-for-APIs. Use before bumping an API version or releasing, or when checking whether a spec edit is breaking.

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
ai-agentsgobashtestinggitapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add bakw00ds/yakos --skill api-diff --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Api Diff?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Api Diff
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bakw00ds-api-diff/badge)](https://www.skillsdirectory.com/skills/bakw00ds-api-diff)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: api-diff
description: Diff an OpenAPI spec across commits and classify each change as major/minor/patch per SemVer-for-APIs. Use before bumping an API version or releasing, or when checking whether a spec edit is breaking.
allowed-tools: Bash Read
argument-hint: "[--base <ref>] [--head <ref>] [--spec <path>]"
mode: [report]
---

# API Diff

## Purpose

Given two refs of the same OpenAPI spec, produce a classified diff
where every change is tagged `major` (breaking), `minor` (additive),
or `patch` (doc-only). Used by the `api-designer` agent to decide
the next API version and to populate the PR description so reviewers
can see compatibility impact at a glance.

## Scope

- Reads the spec at `--spec` (default `api/openapi.yaml`) at two refs
  (`--base`, default `origin/main`; `--head`, default `HEAD`).
- Walks paths, operations, parameters, request bodies, responses,
  and component schemas. Classifies each delta.
- Emits a markdown report grouped by severity.
- Read-only — produces a report, makes no spec changes.

## When to use

- Before opening a PR that touches `api/openapi.yaml` (or whatever
  the spec path is in the project).
- During release planning, to confirm the next bump matches the
  highest-severity change in the diff.
- For PR description generation — paste the report into the
  "API impact" section.

## When NOT to use

- For runtime contract testing — that's `contract-handoff` +
  consumer-driven contract suites.
- For non-OpenAPI specs (gRPC `.proto`, GraphQL SDL). The classifier
  only understands OpenAPI 3.x. For protobuf, use `buf breaking`;
  for GraphQL, use `graphql-inspector diff`.
- As the sole gate. A human still reads the report — the classifier
  catches structural changes, not semantic ones (e.g., a field whose
  meaning changed but type didn't).

## Automated pass

1. Resolve the refs and spec path:
   ```sh
   base="${BASE:-origin/main}"
   head="${HEAD:-HEAD}"
   spec="${SPEC:-api/openapi.yaml}"
   ```

2. Extract both versions to tempfiles:
   ```sh
   tmp=$(mktemp -d -t api-diff.XXXXXX)
   git show "$base:$spec" > "$tmp/base.yaml"
   git show "$head:$spec" > "$tmp/head.yaml"
   ```

3. Run the structural diff. Prefer `oasdiff` if installed; fall back
   to a jq-based walk:
   ```sh
   if command -v oasdiff >/dev/null; then
       oasdiff breaking "$tmp/base.yaml" "$tmp/head.yaml" --format json > "$tmp/break.json"
       oasdiff diff     "$tmp/base.yaml" "$tmp/head.yaml" --format json > "$tmp/full.json"
   fi
   ```

4. Classify each delta:

   **Major (breaking — rev the major version):**
   - path removed
   - operation removed (DELETE on path that still exists, etc.)
   - required request parameter or body field added
   - existing field's type narrowed (string → enum subset, number → integer)
   - response shape narrowed (field removed; required-on-response added)
   - status code removed from a response
   - auth scheme tightened on an existing operation

   **Minor (additive — rev the minor version):**
   - new path
   - new operation on existing path
   - new optional request parameter or field
   - new response status code
   - new field in a response (additive — clients that ignore unknown fields are fine)
   - response shape widened (enum gained a value, oneOf gained a branch)

   **Patch (doc-only — rev the patch version):**
   - description / summary text change
   - example update
   - tag rename without semantic shift
   - servers[].url cosmetic update
   - reordering without structural change

5. Emit the report. Group by severity, list each delta with the
   path/operation it affects:
   ```markdown
   # API diff: <base>..<head>

   **Highest severity:** major | minor | patch
   **Recommended bump:** v<next>

   ## Major (breaking)
   - `DELETE /v1/users/{id}` — operation removed
   - `POST /v1/orders` — required field `customer_id` added to request body

   ## Minor (additive)
   - `GET /v1/orders` — new optional query param `status`

   ## Patch (doc-only)
   - `GET /v1/health` — description updated
   ```

6. Clean up tempfiles.

## Manual pass

For a quick eyeball check without the classifier:

```sh
git diff origin/main..HEAD -- api/openapi.yaml | head -200
oasdiff breaking origin/main:api/openapi.yaml HEAD:api/openapi.yaml
```

…and decide the bump by hand. Reasonable for trivial diffs (one
new optional field).

## Known gotchas

- **`$ref` chasing.** A change inside a referenced component
  (`#/components/schemas/User`) affects every operation that uses
  it. The skill expands refs before classifying so a single
  schema-level breaking change surfaces under each consumer; do
  not de-dup blindly or the report hides blast radius.
- **Required-by-default.** OpenAPI 3.x marks request body / parameter
  required-ness explicitly, but schemas default to optional unless
  listed in `required:`. Adding a field name to `required:` is
  breaking even if the field already existed.
- **Enum narrowing vs widening.** Adding an enum value is additive
  for clients that send (they may now send the new value) but
  potentially breaking for clients that switch on the response
  enum (they'll hit an unhandled case). The skill flags enum
  additions as `minor` with a footnote — reviewer decides if the
  consumer is the strict-switch kind.
- **No oasdiff.** If `oasdiff` isn't installed, the jq fallback
  catches structural changes but misses some subtle ones (e.g.,
  format change `date` → `date-time`). Skill notes this in the
  report header so reviewers know the classifier was degraded.
- **Spec path drift.** If the project rearranged its spec (split
  monolithic openapi.yaml into per-domain files), the diff against
  the old path returns "spec removed" — false major. The operator
  passes `--spec` for the new path explicitly.

## References

- `oasdiff` — https://github.com/oasdiff/oasdiff
- `lib/skills/contract-handoff/SKILL.md` — publishing the spec for
  downstream consumers.
- `lib/rules/commit-format.md` — commit type for spec changes
  (`feat(api): ...` for additive; `feat(api)!: ...` for breaking
  with the `!` marker).
- SemVer for APIs — https://semver.org/ (the spec is silent on
  APIs specifically, but the major/minor/patch discipline applies).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…