Usage
Diff current specs against the last snapshot and classify every change as breaking, non-breaking, or patch-level. Exits 1 if breaking changes are found — use this command in CI to gate merges.
Command
Section titled “Command”contractual breaking [--contract <name>] [--format <fmt>] [--base <ref>]How it works
Section titled “How it works”contractual breaking compares the current state of each registered contract against its last versioned snapshot stored in .contractual/snapshots/. For each detected change, Contractual classifies it as one of:
- breaking: requires a major version bump (for example, removing a field, changing a type, deleting an endpoint).
- non-breaking: requires a minor version bump (for example, adding an optional field, adding a new endpoint).
- patch: backward-compatible fix, requires a patch version bump.
The command exits with code 1 if any breaking changes are found, which can be used to fail a CI check and block a merge.
Options
Section titled “Options”| Flag | Description | Default |
|---|---|---|
--contract <name> | Run the diff only for the named contract. Repeat to target multiple contracts. | All contracts |
--format <fmt> | Output format. One of text, json. | text |
--base <ref> | Snapshot tag or git ref to use as the comparison base. | Latest versioned snapshot |
Examples
Section titled “Examples”Check all contracts for breaking changes
Section titled “Check all contracts for breaking changes”$ contractual breaking Comparing contracts against last snapshot... payments-api (openapi) ✖ [breaking] DELETE /v1/charges/{id} Endpoint removed ✖ [breaking] GET /v1/charges Response field `currency` removed ✔ [non-breaking] GET /v1/charges Response field `metadata` added user-schema (json-schema) ✔ No changes detected. 2 breaking change(s) found across 1 contract(s).
Check a single contract
Section titled “Check a single contract”$ contractual breaking --contract payments-api Comparing payments-api against last snapshot... ✖ [breaking] DELETE /v1/charges/{id} Endpoint removed ✖ [breaking] GET /v1/charges Response field `currency` removed ✔ [non-breaking] GET /v1/charges Response field `metadata` added 2 breaking change(s) found.
Compare against a specific base ref
Section titled “Compare against a specific base ref”$ contractual breaking --base v1.2.0 Comparing contracts against snapshot v1.2.0... payments-api (openapi) ✖ [breaking] GET /v1/charges Response field `currency` removed 1 breaking change(s) found.
JSON output for CI integration
Section titled “JSON output for CI integration”$ contractual breaking --format json
{
"contracts": [
{
"name": "payments-api",
"type": "openapi",
"changes": [
{
"classification": "breaking",
"description": "Endpoint removed",
"location": "DELETE /v1/charges/{id}"
},
{
"classification": "breaking",
"description": "Response field `currency` removed",
"location": "GET /v1/charges"
},
{
"classification": "non-breaking",
"description": "Response field `metadata` added",
"location": "GET /v1/charges"
}
]
},
{
"name": "user-schema",
"type": "json-schema",
"changes": []
}
],
"summary": { "breaking": 2, "nonBreaking": 1, "patch": 0 }
} Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | No breaking changes detected. |
1 | One or more breaking changes were found. |
2 | Configuration error, for example contractual.yaml not found, unknown contract name, or snapshot not found for the requested --base. |
3 | Tool error, the configured differ binary was not found or exited unexpectedly. |
Custom differs
Section titled “Custom differs”Contractual ships with built-in structural differs for all supported contract types. Override them when:
- Your team already uses a custom differ tool
- You have an internal tool that produces structured output
- You want to add flags or configuration the default invocation does not expose
- You want to disable breaking change detection for a specific contract
Override syntax
Section titled “Override syntax”Use the breaking field in the contract configuration. Use {old} for the snapshot path (the baseline) and {new} for the current spec path.
contracts: - name: orders-api type: openapi path: ./specs/orders.openapi.yaml breaking: "my-custom-differ breaking {old} {new} --format json"Both {old} and {new} are absolute paths. The command must exit with code 0 if no breaking changes are found, and a non-zero code if breaking changes are found.
Placeholder reference
Section titled “Placeholder reference”| Placeholder | Replaced with | Available in |
|---|---|---|
{old} | Absolute path to the snapshot (baseline) spec | breaking |
{new} | Absolute path to the current spec file | breaking |
{name} | The contract’s name value | breaking |
Disabling breaking change detection
Section titled “Disabling breaking change detection”Set breaking: false to skip the step entirely for a contract.
contracts: - name: internal-config type: json-schema path: ./config/internal.schema.json breaking: false # Internal schema, no breaking change tracking neededSetting a field to false is different from omitting it. Omitting uses the built-in default. false explicitly opts out.
Output format expectations
Section titled “Output format expectations”Contractual runs the custom command and inspects two things:
Exit code: zero means pass, non-zero means failure. This is the primary signal.
Standard output: Contractual attempts to parse the output to extract structured information for PR comments and changeset generation. For the best results, use --format json with tools that support it.
CI integration
Section titled “CI integration”GitHub Action
Section titled “GitHub Action”name: Contract Governance
on: pull_request: paths: - 'specs/**' - 'schemas/**'
jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0
- uses: contractual-dev/action@v1 with: mode: pr-check github-token: ${{ secrets.GITHUB_TOKEN }} fail-on-breaking: trueManual CI (any CI system)
Section titled “Manual CI (any CI system)”npm install -g @contractual/cli
contractual breaking --format json > breaking-report.json
# Fail the build if exit code is 1if [ $? -eq 1 ]; then echo "Breaking changes detected" exit 1fiNext steps
Section titled “Next steps”- Overview: How the structural differ works
- Classifications: Full reference table for all change types
- GitHub Action Setup: Complete CI integration guide