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.5

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.5
File Size Uploaded
diff_contract-0.1.5.tar.gz 34.9 kB Details

Built distribution (wheel)

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

Total release size: 48.3 kB

Release files / diff_contract-0.1.5.tar.gz

Download URL diff_contract-0.1.5.tar.gz
Size 34.9 kB
Tags Source
SHA-256 checksum
How to use checksums
ddd6e12d9d5d37cf1792cabbbf3d7d8147aa5171bc76991851a8aab70c67e9bb
BLAKE2b-256 checksum
How to use checksums
522326e2a05e558391efc23ec01670a0b6927331393804cb3a67ed802c413156
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.5-py3-none-any.whl

Download URL diff_contract-0.1.5-py3-none-any.whl
Size 13.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
62ee1829a0ba24f44c71c37738baa57e952627ec266444172524cfe7bc599453
BLAKE2b-256 checksum
How to use checksums
2004e4e8d5ca9981f2f3acd28b3f321a30244d449d3e069513bde1efcb3a3a61
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

This release

0.1.5 This release

2 release files

0.1.4

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