Catch provider-incompatible schemas before OpenAI or Anthropic reject them at runtime.
OpenAI and Anthropic structured-output APIs accept only a strict subset of JSON Schema. Ship a schema with an unsupported keyword, a missing required entry, or the wrong additionalProperties, and the API rejects it — in production, at request time, as a 400.
schemalint catches those errors at build time, checked against the exact provider rules, so a bad schema fails your CI instead of your users' requests.
# npm / bun — adds the `schemalint` command to your project
npm install -D @1nder-labs/schemalint
# Rust
cargo install schemalint
# Python
pip install schemalintCheck a schema against OpenAI's structured-output rules:
schemalint check --profile openai.so.2026-04-30 schema.jsonerror[OAI-K-allOf]: keyword 'allOf' is not supported by openai.so.2026-04-30
--> schema.json
1 issue found (1 error, 0 warnings) across 1 schema
Check a whole directory, for both providers at once:
schemalint check \
--profile openai.so.2026-04-30 \
--profile anthropic.so.2026-04-30 \
schemas/Schemas live in your code, not in .json files? schemalint reads them straight from your Zod or Pydantic definitions — no manual JSON Schema export, no second package to install.
npm run lint:schemas # Zod → check-node
schemalint check-python # Pydantic → check-pythonExit 0 is a completeness guarantee: every discovered in-scope target was
evaluated and checked, and no error diagnostic was produced. Import
failures, schema-conversion failures, and
partially checked batches exit 1. A run that discovers nothing (no matches)
exits 3 and its human output starts with checked 0 schemas: nothing was discovered; --continue-on-discovery-error keeps
collecting results but never converts partial coverage into success.
Machine-readable output uses schema version 1.1. Its additive report object
contains coverage.status (complete, empty, partial, or failed), target
counts, failures, and non-fatal warnings. Existing 1.0 fields retain their
meaning.
| Boundary | Supported contract |
|---|---|
| Node.js | 18, 20, and 22 |
| Zod | >=3.20, including v3, v4 from 4.0.1 through current 4.4.3, and zod/mini |
| Python | 3.9+ |
| Pydantic | 1.10 and 2.x |
The JSON-RPC server and ingestion caches are bounded and process-local. schemalint does not persist schemas or normalized schema data to disk.
- Unsupported keywords (
allOf,oneOf,not, unsupportedformats, …) per provider - Missing
requiredentries andadditionalProperties: falsemistakes - Invalid root shapes, unsupported
$refpatterns, and enum / nesting limits - Size and depth limits that otherwise only surface as a runtime
400
| Provider | Profile |
|---|---|
| OpenAI Structured Outputs | openai.so.2026-04-30 |
| Anthropic Structured Outputs | anthropic.so.2026-04-30 |
schemalint exits non-zero on errors, so it fails the build before a broken schema ever ships:
- run: npx schemalint check --profile openai.so.2026-04-30 schemas/Pick the output format that fits your pipeline:
schemalint check --format json --profile openai.so.2026-04-30 schema.json # machine-readable
schemalint check --format sarif --profile openai.so.2026-04-30 schema.json # code scanning
schemalint check --format gha --profile openai.so.2026-04-30 schema.json # GitHub Actions annotations| Exit code | Meaning |
|---|---|
0 |
Complete coverage and no errors |
1 |
Error diagnostic, or partial or failed coverage |
2 |
Could not write the output file |
3 |
Empty coverage: nothing was discovered, so nothing was checked |
Coding agents (Claude Code, Codex, Cursor, ...) should start with the usage guide that ships inside the binary, so it always matches the installed version:
schemalint skills get core # workflow, monorepo usage, exit codes, common fixes
schemalint skills get core --full # plus the full command referenceBug reports, new rules, and provider profiles are all welcome — see CONTRIBUTING.md and CODE_OF_CONDUCT.md.
Found a vulnerability? Please report it privately — see SECURITY.md.
Dual-licensed under MIT or Apache-2.0, at your option.

