Configuration
contractual.yaml is the single file that tells Contractual which contracts to manage, how to govern them, what to generate, and how to publish.
Minimal config
Section titled “Minimal config”The only required section is contracts. Each entry needs three fields: name, type, and path.
# yaml-language-server: $schema=https://contractual.dev/schema.jsoncontracts:
-
name: orders-api type: openapi path: ./specs/orders.openapi.yaml
-
name: order-schema type: json-schema path: ./schemas/order.schema.json
Full annotated example
Section titled “Full annotated example”# yaml-language-server: $schema=https://contractual.dev/schema.jsoncontracts:
-
name: orders-api type: openapi path: ./specs/orders.openapi.yaml lint: “spectral lint {spec} —format json” breaking: “my-custom-differ breaking {old} {new} —format json” outputs:
- name: typescript-client command: “orval —input {spec} —output ./src/generated/orders-client.ts”
-
name: order-schema type: json-schema path: ./schemas/order.schema.json lint: false
publish: commit: true tag: true release: false
ai: changelog: true explain: true enhance: false
contracts
Section titled “contracts”Type: array
Required: Yes
The list of contracts Contractual manages. Every command operates on all contracts unless filtered with --contract.
contracts[].name
Section titled “contracts[].name”Type: string
Required: Yes
Unique identifier for this contract. Used in changeset frontmatter, version history, snapshot filenames, and CLI output.
Must be a valid slug: lowercase letters, numbers, and hyphens. No spaces.
contracts[].type
Section titled “contracts[].type”Type: 'openapi' | 'json-schema'
Required: Yes
The format of the spec file. Determines the default linter and differ.
| Value | Default linter | Default differ |
|---|---|---|
openapi | Spectral | Built-in structural differ |
json-schema | Built-in validator | Built-in structural differ |
contracts[].path
Section titled “contracts[].path”Type: string
Required: Yes
Path to the spec file, relative to the location of contractual.yaml.
contracts: - name: orders-api path: ./specs/orders.openapi.yamlcontracts[].lint
Section titled “contracts[].lint”Type: string | false
Default: The default linter for the contract type
Override the linter command. Use {spec} as a placeholder for the spec file path.
lint: "spectral lint {spec} --format json"
# Or disable linting entirelylint: falsecontracts[].breaking
Section titled “contracts[].breaking”Type: string | false
Default: The default differ for the contract type
Override the breaking change detection command. Use {old} and {new} as placeholders.
breaking: "./scripts/diff.sh {old} {new}"
# Or disable breaking change detectionbreaking: falsecontracts[].outputs
Section titled “contracts[].outputs”Type: array
Default: []
Commands to run after lint passes. Each entry takes name and command.
outputs: - name: typescript-client command: "orval --input {spec} --output ./src/generated/orders-client.ts"Placeholders: {spec}, {name}, {version}
publish
Section titled “publish”Type: object
Required: No
Controls what happens when contractual version runs.
| Field | Type | Default | Description |
|---|---|---|---|
commit | boolean | true | Commit the version bump and changelog |
tag | boolean | true | Create a git tag v{version} |
release | boolean | false | Run releaseCommand after tagging |
releaseCommand | string | Shell command for publishing |
publish: commit: true tag: true release: true releaseCommand: "gh release create v{version} --notes-file CHANGELOG.md"Type: object
Required: No
AI features are optional. When ANTHROPIC_API_KEY is set, Contractual uses Claude to enrich changelogs, explain changes, and suggest improvements.
| Field | Type | Default | Description |
|---|---|---|---|
changelog | boolean | false | AI-written changelog entries |
explain | boolean | false | AI explanation in PR comments |
enhance | boolean | false | Spec improvement suggestions |
ai: changelog: true explain: true enhance: falseAll AI features degrade gracefully. If the API key is absent, Contractual skips AI steps without failing.
versioning
Section titled “versioning”Type: object
Required: No
Controls how contract versions are managed.
| Field | Type | Default | Description |
|---|---|---|---|
mode | 'independent' | 'fixed' | independent | Versioning mode |
versioning: mode: independent # Each contract versioned separatelyOr for monorepo-style fixed versioning:
versioning: mode: fixed # All contracts share same versionchangeset
Section titled “changeset”Type: object
Required: No
Controls changeset behavior.
| Field | Type | Default | Description |
|---|---|---|---|
autoDetect | boolean | true | Auto-detect changes when creating changesets |
requireOnPR | boolean | true | Require changeset for PRs with contract changes |
changeset: autoDetect: true requireOnPR: trueDefaults table
Section titled “Defaults table”| Field | Default |
|---|---|
contracts[].lint | Default linter for the contract type |
contracts[].breaking | Default differ for the contract type |
contracts[].outputs | [] (no generation) |
publish.commit | true |
publish.tag | true |
publish.release | false |
ai.changelog | false |
ai.explain | false |
ai.enhance | false |
JSON Schema
Section titled “JSON Schema”The published JSON Schema is available at https://contractual.dev/schema.json.
Register it in VS Code settings:
{ “yaml.schemas”: { “https://contractual.dev/schema.json”: “contractual.yaml” } }
Internal files
Section titled “Internal files”Contractual stores version history and pre-release state in the .contractual/ directory.
versions.json
Section titled “versions.json”Tracks version history for all contracts:
{ "orders-api": { "current": "1.2.0", "history": [ { "version": "0.0.0", "date": "2026-01-01T00:00:00Z" }, { "version": "1.0.0", "date": "2026-02-01T00:00:00Z" }, { "version": "1.2.0", "date": "2026-03-01T00:00:00Z" } ] }, "order-schema": { "current": "1.0.0", "history": [ { "version": "0.0.0", "date": "2026-01-01T00:00:00Z" }, { "version": "1.0.0", "date": "2026-02-15T00:00:00Z" } ] }}pre.json
Section titled “pre.json”When in pre-release mode, this file tracks the pre-release state:
{ "tag": "beta", "mode": "pre", "enteredAt": "2026-03-10T10:00:00Z", "initialVersions": { "orders-api": "1.2.0", "order-schema": "1.0.0" }}| Field | Description |
|---|---|
tag | Pre-release identifier (alpha, beta, rc, etc.) |
mode | Current mode: pre (active) or exit (pending finalization) |
enteredAt | When pre-release mode was entered |
initialVersions | Versions when pre-release started |
See Pre-release Versioning for usage.
Environment variables
Section titled “Environment variables”| Variable | Description |
|---|---|
CI | Set to true to force non-interactive mode |
CONTRACTUAL_CONFIG | Path to contractual.yaml |
ANTHROPIC_API_KEY | Enable AI features |
GITHUB_TOKEN | GitHub API access for releases |
NO_COLOR | Disable colored output |