Skip to content

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.


The only required section is contracts. Each entry needs three fields: name, type, and path.

contractual.yaml
# yaml-language-server: $schema=https://contractual.dev/schema.json

contracts:

  • name: orders-api type: openapi path: ./specs/orders.openapi.yaml

  • name: order-schema type: json-schema path: ./schemas/order.schema.json


contractual.yaml
# yaml-language-server: $schema=https://contractual.dev/schema.json

contracts:

  • 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


Type: array Required: Yes

The list of contracts Contractual manages. Every command operates on all contracts unless filtered with --contract.

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.

Type: 'openapi' | 'json-schema' Required: Yes

The format of the spec file. Determines the default linter and differ.

ValueDefault linterDefault differ
openapiSpectralBuilt-in structural differ
json-schemaBuilt-in validatorBuilt-in structural differ

Type: string Required: Yes

Path to the spec file, relative to the location of contractual.yaml.

contracts:
- name: orders-api
path: ./specs/orders.openapi.yaml

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 entirely
lint: false

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 detection
breaking: false

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}


Type: object Required: No

Controls what happens when contractual version runs.

FieldTypeDefaultDescription
commitbooleantrueCommit the version bump and changelog
tagbooleantrueCreate a git tag v{version}
releasebooleanfalseRun releaseCommand after tagging
releaseCommandstringShell 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.

FieldTypeDefaultDescription
changelogbooleanfalseAI-written changelog entries
explainbooleanfalseAI explanation in PR comments
enhancebooleanfalseSpec improvement suggestions
ai:
changelog: true
explain: true
enhance: false

All AI features degrade gracefully. If the API key is absent, Contractual skips AI steps without failing.


Type: object Required: No

Controls how contract versions are managed.

FieldTypeDefaultDescription
mode'independent' | 'fixed'independentVersioning mode
versioning:
mode: independent # Each contract versioned separately

Or for monorepo-style fixed versioning:

versioning:
mode: fixed # All contracts share same version

Type: object Required: No

Controls changeset behavior.

FieldTypeDefaultDescription
autoDetectbooleantrueAuto-detect changes when creating changesets
requireOnPRbooleantrueRequire changeset for PRs with contract changes
changeset:
autoDetect: true
requireOnPR: true

FieldDefault
contracts[].lintDefault linter for the contract type
contracts[].breakingDefault differ for the contract type
contracts[].outputs[] (no generation)
publish.committrue
publish.tagtrue
publish.releasefalse
ai.changelogfalse
ai.explainfalse
ai.enhancefalse

The published JSON Schema is available at https://contractual.dev/schema.json.

Register it in VS Code settings:

.vscode/settings.json

{ “yaml.schemas”: { https://contractual.dev/schema.json: “contractual.yaml” } }


Contractual stores version history and pre-release state in the .contractual/ directory.

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" }
]
}
}

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"
}
}
FieldDescription
tagPre-release identifier (alpha, beta, rc, etc.)
modeCurrent mode: pre (active) or exit (pending finalization)
enteredAtWhen pre-release mode was entered
initialVersionsVersions when pre-release started

See Pre-release Versioning for usage.


VariableDescription
CISet to true to force non-interactive mode
CONTRACTUAL_CONFIGPath to contractual.yaml
ANTHROPIC_API_KEYEnable AI features
GITHUB_TOKENGitHub API access for releases
NO_COLORDisable colored output