Skip to main content

diff-contract

CI Docs PyPI Downloads Python License Release Stars

Deterministic guardrails for AI-generated diffs — define what files can change, block violations.

Full documentation: yunaremaia.github.io/diff-contract

pip install diff-contract
diff-contract check --contract .diffcontract.yml

The Problem

AI coding tools (Cursor, Claude Code, Codex) sometimes modify unrelated files, introduce changes outside the intended scope, or drift from the original structure. diff-contract sits between AI-generated code and your repo, enforcing deterministic constraints — not relying on another AI pass to review.

"Most tools either help generate code or review it after the fact, but there's no real control layer in between." — HN discussion, 2026

Quick Start

1. Install

pip install diff-contract

2. Define your contract

# .diffcontract.yml
version: 1
rules:
  - name: "Block core changes"
    deny:
      - "src/core/**"
      - "*.env"
    on_violation: block

  - name: "Allow feature X"
    allow:
      - "src/features/X/**"
      - "tests/features/X/**"
    on_violation: block

3. Check your diff

# Check current branch vs main
diff-contract check

# Check specific files
diff-contract check --files src/app.py src/utils.py

# JSON output (for CI)
diff-contract check --output json

4. GitHub Action

# .github/workflows/diff-contract.yml
name: diff-contract
on: pull_request

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: yunaremaia/diff-contract@main

Validate files (no git required)

Validate specific files against your contract without a git diff — ideal for pre-commit hooks:

diff-contract validate --files src/app.py tests/test_app.py
echo "src/foo.py" | diff-contract validate --from-stdin

Initialize a contract

Create a starter .diffcontract.yml:

diff-contract init                    # default Python project contract
diff-contract init --template react   # React/Next.js
diff-contract init --template django  # Django
diff-contract init --template rust    # Rust workspace
diff-contract init --template docs    # documentation-only

Ready-to-use templates for React, Django, Rust, and documentation-only projects are available in the examples/ directory.

Pre-commit hook

diff-contract ships a pre-commit hook. Add to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/yunaremaia/diff-contract
    rev: v0.1.0
    hooks:
      - id: diff-contract
        args: ["--contract", ".diffcontract.yml"]

SARIF Output (GitHub Code Scanning)

Generate SARIF 2.1.0 output for GitHub Code Scanning integration:

diff-contract check --sarif > diff-contract.sarif
diff-contract validate --files src/foo.py --sarif

GitHub Actions workflow:

- uses: yunaremaia/diff-contract@main
  with:
    format: sarif
    sarif-output: diff-contract.sarif

- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: diff-contract.sarif

SARIF output includes one rule per violation type. Block violations emit at error level, warnings at warning.

Exit Codes

Code Meaning
0 Clean — no violations
1 Block violation — file denied, outside allowed scope, or an aggregate limit exceeded with on_violation: block
2 Warning — non-blocking violation (e.g., large diff with on_violation: warn)

Rules

  • allow: File globs that are permitted (all others blocked)
  • deny: File globs that are denied (takes priority)
  • on_violation: block (exit 1) or warn (exit 2)
  • max_files / max_lines: optional aggregate size limits (see below)

Aggregate Limits

Path allow/deny rules constrain which files may change. max_files and max_lines constrain how large a change set may be. They are evaluated against the whole diff after per-file rules run.

Field Meaning
max_files Maximum number of changed files in the diff
max_lines Maximum total changed lines (added + deleted from git diff --numstat)

A rule may set either field, both, or neither. Limits are omitted by default (no size budget). When a limit is exceeded, the engine records an aggregate violation on the synthetic path <aggregate> and applies that rule's on_violation:

  • on_violation: block — fail the check (exit code 1). Use this to stop AI agents or CI from landing oversized diffs.
  • on_violation: warn — report the overshoot but continue (exit code 2 if there are no block violations). Use this as a PR-size nudge.

Typical uses:

  • Cap feature work so an agent cannot rewrite half the tree while implementing one ticket.
  • Keep documentation or bugfix rules tight even when the path globs are broad.
  • Warn on large diffs without blocking hotfixes.

Limits are compared against the entire change list, not only files that match that rule's allow/deny globs. A rule that only sets max_files / max_lines (no path patterns) is a global size guard.

Example

# .diffcontract.yml
version: 1
rules:
  - name: "Block core changes"
    deny:
      - "src/core/**"
      - "*.env"
    on_violation: block

  - name: "Feature development"
    allow:
      - "src/features/**"
      - "tests/features/**"
    max_files: 15
    max_lines: 400
    on_violation: block

  - name: "Large diff warning"
    max_files: 20
    max_lines: 600
    on_violation: warn

In this contract:

  • Changes under src/core/** or *.env are blocked.
  • Feature-area diffs may proceed only if they stay within 15 files and 400 lines; exceeding either budget is a block (exit 1).
  • Any diff larger than 20 files or 600 lines also produces a warning (exit 2 when nothing is blocked).

See examples/strict.yml for a fuller contract that combines deny rules with per-rule size budgets.

If this tool is useful to you, a star helps other people find it.

  • ci-test-gate — block PRs until the required tests actually run
  • driftcheck — detect version drift between docs and toolchain files
  • agent-guard — enforce guardrails on AI agent tool calls
  • mcp-guard — audit MCP servers for unsafe permissions

Part of a family of focused, single-purpose developer tools — each one does one thing and does it well.

License

MIT

Metadata

Release files for diff-contract 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for diff-contract 0.1.4
File Size Uploaded
diff_contract-0.1.4.tar.gz 34.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for diff-contract 0.1.4
File Interpreter ABI Platform
diff_contract-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 47.6 kB

Release files / diff_contract-0.1.4.tar.gz

Download URL diff_contract-0.1.4.tar.gz
Size 34.2 kB
Tags Source
SHA-256 checksum
How to use checksums
27e40ea502550ba6fff6e5da0087f8ab47a3470b718f1c1b4db3a5f65895f7c6
BLAKE2b-256 checksum
How to use checksums
b296a11e5b71ff8342f6f7840b3895bddeef469e0fcbcfbdbd6528c454da2e38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / diff_contract-0.1.4-py3-none-any.whl

Download URL diff_contract-0.1.4-py3-none-any.whl
Size 13.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
102bfabdf8ca1959c78d41c27436585c462414c9772f3e9d133911450f96319c
BLAKE2b-256 checksum
How to use checksums
1c5c890c760bd29131aaac8ac163efc4d2fccf1533f72a889f885d1925ee7cb5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page