Skip to content

Repository files navigation

Diff Guardian

npm version license node version CI status

Impact-aware git diff engine that uses WASM Tree-Sitter AST parsing to detect breaking API changes before they ship.

Website · Documentation · Rules Reference · Quick Start · Contributing · Changelog


Why Diff Guardian?

The Problem: Silent API Breakages

Standard git diff makes merging code dangerous because it only understands added or removed text lines, not your code's actual structure. When teams collaborate on shared interfaces, standard git won't warn you if a colleague accidentally removes a required argument, changes a return type, or mutates an exported enum. The result? Silent regressions, broken CI/CD pipelines, and painful merge resolutions that easily slip past code review.

The Solution

Traditional diffs show what changed. Diff Guardian shows what breaks.

Diff Guardian acts as an automated safety net. Using WASM-compiled Tree-Sitter grammars, it parses your code into abstract syntax tree (AST) signatures, compares the before and after states across any branch, and evaluates every diff against 30 strict production rules. It then traces every call site across your ecosystem to show exactly who is affected before you merge or push.

$ npx dg compare main feature-branch

  Diff Guardian · Compare

  Base: main
  Head: feature-branch

  BREAKING  src/api/payments.ts → processPayment()
     R01: Parameter 'currency' was removed. Callers providing this argument will fail.

     3 call sites affected:
        src/checkout/handler.ts:42   processPayment("usd", 100)
        src/invoices/generator.ts:18 processPayment(curr, amount)
        tests/payments.test.ts:7     processPayment("eur", 50)

Zero config required. Install it. Run it. Ship with confidence.


Features

Capability Description
AST-Powered Analysis Tree-Sitter WASM grammars parse your code into structural signatures — not regex
30 Classification Rules Covers parameter changes, return types, generics, visibility, enums, interfaces, type aliases, and more
Blast Radius Tracing JIT import scanner and call-site tracer shows every consumer affected by a breaking change
CI/CD Native Auto-detects GitHub Actions and posts PR comments with full audit reports
Git Hook Enforcement Built-in Husky hooks block broken code at pre-push, pre-merge-commit, and post-merge
Multi-Language TypeScript, JavaScript, Python, Go, Java, and Rust
Fast WASM grammars cached to disk; lazy graph only traces what is broken
Zero Config Works out of the box with npx dg

Quick Start

Installation

# Install as a dev dependency (recommended)
npm install --save-dev @aryan28/diff-guard

# Or run directly with npx — no install needed
npx dg

Initialize Your Project

npx dg init

This scaffolds two files:

File Purpose
dg.config.json Project configuration
.github/workflows/diff-guardian.yml GitHub Actions workflow for automated PR audits

Run Your First Scan

# Smart mode — auto-detects CI vs local
npx dg

# Compare your branch against main
npx dg compare main

# Check uncommitted changes
npx dg check

# Check only staged files
npx dg check --staged

Commands

dg — Smart Default

npx dg

Auto-detects the execution context:

Context Behavior
GitHub Actions Compares PR base to head and posts a comment on the PR
Local terminal Compares default branch to HEAD and prints a terminal report

dg check — Working Tree Analysis

# Analyze all uncommitted changes
npx dg check

# Analyze only staged files
npx dg check --staged

# Scope to a specific directory
npx dg check src/payments

dg compare <base> [head] — Git Ref Comparison

# Compare current branch against main
npx dg compare main

# Compare two branches
npx dg compare main feature-branch

# Compare two tags
npx dg compare v1.0.0 v2.0.0

# Compare recent commits
npx dg compare HEAD~3 HEAD

dg trace <symbol> — Impact Tracing

npx dg trace processPayment

Shows every file that imports the given symbol and where it is used:

  processPayment — 3 importer(s) found

  src/checkout/handler.ts
    L4  processPayment  [named]

  src/invoices/generator.ts
    L2  processPayment  [named]

  tests/payments.test.ts
    L1  processPayment  [named]

dg rules — List Classification Rules

npx dg rules

Prints all 30 classification rules with their IDs, names, targets, and descriptions.

For detailed examples and remediation guidance, see the full rules documentation.

dg init — Project Scaffolding

npx dg init

Creates dg.config.json and the GitHub Actions workflow. Skips files that already exist.

Versioning: Semver Recommendation + Changelog Draft

Diff Guardian already classifies every change into breaking / warning / safe. Add --recommend-version and/or --draft-changelog to check or compare to turn that classification into the two things a maintainer needs before releasing:

# Get a semver bump recommendation, with justification
npx dg compare main --recommend-version

# Get a Keep-a-Changelog-style draft, ready to paste into CHANGELOG.md
npx dg compare main --draft-changelog

# Both together, and write the changelog draft to a file
npx dg compare main --recommend-version --draft-changelog --changelog-output CHANGELOG.draft.md

Semver recommendation logic (standard semver by default):

Condition Recommended bump
Any breaking change present major
Any warning change present, no breaking minor
Only safe changes patch

The recommendation always includes justification referencing the specific rule(s) that drove the decision — e.g. R01: Parameter 'currency' was removed. (processPayment in src/api/payments.ts) — not just the bump level alone.

Changelog draft groups changes under Keep-a-Changelog-style headers — ### Breaking Changes, ### Deprecated, ### Added, ### Fixed — using human-readable descriptions rather than raw rule codes as the headline text (rule IDs are still included, parenthetically, for traceability).

In CI, both the recommended version bump and the changelog draft are shown prominently at the top of the GitHub PR comment — the version bump is the single most actionable piece of information for a reviewer deciding whether to approve as-is or request a bigger bump.

Global Options

Option Description
--help, -h Show help message
--staged Limit check to staged files only
--report-file <path> Write JSON report to a file
--recommend-version Output a semver bump recommendation (see above)
--draft-changelog Emit a Keep-a-Changelog-style draft (see above)
--changelog-output <path> Write the changelog draft to a file instead of only showing it inline (requires --draft-changelog)

Configuration

Diff Guardian looks for a dg.config.json file in your project root.

{
  "baseBranch": "main",
  "failOnWarnings": false,
  "enableTracer": true,
  "maxGrepResults": 500,
  "maxBarrelDepth": 10,
  "maxTracerFiles": 100,
  "versioningOverrides": {
    "R23": "major"
  }
}
Key Type Default Description
baseBranch string "main" Default branch to compare against
failOnWarnings boolean false Exit with code 1 on warnings (not just breaking changes)
enableTracer boolean true Enable or disable call-site tracing
maxGrepResults number 500 Max files returned by git grep per symbol
maxBarrelDepth number 10 Max recursive barrel file depth
maxTracerFiles number 100 Max files to AST-parse for call sites per symbol
versioningOverrides Record<string, 'major' | 'minor' | 'patch'> {} Per-rule ID overrides of the default severity → semver mapping (e.g. force a specific deprecation rule to require a major bump instead of the default minor)

Fields with the wrong type, or unrecognized top-level keys, are reported as [dg] dg.config.json: ... warnings on load and ignored (their default is used instead) — the file itself is never rejected wholesale. Individual versioningOverrides entries are validated the same way: an entry with an unrecognized rule ID or an invalid bump value is dropped (with a warning) without discarding the rest of the map.


CI/CD Integration

GitHub Actions

Run npx dg init to generate the workflow file, or add this to your pipeline manually:

name: "Diff Guardian"

on:
  pull_request:
    branches: [ "main", "master" ]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

permissions:
  contents: read
  pull-requests: write

jobs:
  analyze:
    name: API Contract Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - run: npm ci

      - name: Cache WASM Grammars
        id: grammar-cache
        uses: actions/cache@v4
        with:
          path: grammars/
          key: wasm-grammars-${{ hashFiles('package-lock.json') }}
          restore-keys: |
            wasm-grammars-

      - name: Build WASM Grammars
        if: steps.grammar-cache.outputs.cache-hit != 'true'
        run: npm run build:grammars

      - run: npm run build

      - name: Run Diff Guardian
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GITHUB_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
        run: npx dg

In CI mode, Diff Guardian automatically:

  • Resolves GITHUB_BASE_REF and GITHUB_HEAD_SHA for accurate comparison
  • Posts a formatted comment on the PR with the full audit report
  • Caches WASM grammars for faster subsequent runs
  • Returns exit code 0 (advisory mode — classifications never block the merge)

Git Hook Enforcement

Diff Guardian ships with Husky hooks for local enforcement:

Hook Behavior
pre-push Blocks push if breaking changes are detected (exit 1)
pre-merge-commit Blocks merge if breaking changes are detected (exit 1)
post-merge Advisory scan after merge — generates .dg-report.json

Supported Languages

Language Grammar Extensions
TypeScript tree-sitter-typescript .ts, .tsx
JavaScript tree-sitter-javascript .js, .jsx
Python tree-sitter-python .py
Go tree-sitter-go .go
Java tree-sitter-java .java
Rust tree-sitter-rust .rs

Programmatic API

Diff Guardian can be used as a library in your own tooling:

import { runPipeline, ClassifierEngine, ASTMapper } from '@aryan28/diff-guard';

// Run the full pipeline
const exitCode = await runPipeline({
  baseSha: 'main',
  headSha: 'HEAD',
  repoRoot: process.cwd(),
  config: {
    mode: 'strict',
    format: 'json',
  },
});

// Or use individual components
const mapper = new ASTMapper();
await mapper.init();
const diffs = await mapper.buildSignatureCache(/* ... */);

const engine = new ClassifierEngine();
const changes = engine.compare(diff);

Exported Types

import type {
  PipelineOptions,
  ReporterConfig,
  AnalysisResult,
  FunctionChange,
  FileDiff,
  ParseResult,
  FunctionSignature,
  InterfaceSignature,
  EnumSignature,
} from '@aryan28/diff-guard';

Architecture

┌──────────────────────────────────────────────────────────────────┐
│                           CLI Layer                              │
│         npx dg check | compare | trace | rules | init            │
├──────────────────────────────────────────────────────────────────┤
│                         Pipeline                                 │
│           Orchestrates the full analysis flow                    │
├──────────────┬──────────────┬──────────────┬─────────────────────┤
│  Git Diff    │  AST Mapper  │  Classifier  │  Reporter           │
│  Parser      │  (WASM TS)   │  Engine      │  (Terminal/GitHub)  │
├──────────────┴──────────────┼──────────────┴─────────────────────┤
│     Language Translators    │    Tracer (Scanner + Call Sites)   │
│     TS · JS · Python · Go   │    JIT import resolution           │
│     Java · Rust             │    Lazy blast-radius graph         │
└─────────────────────────────┴────────────────────────────────────┘

Exit Codes

Code Meaning
0 Clean — no breaking changes detected
1 Breaking changes detected (or warnings, if failOnWarnings is enabled)
2 Infrastructure error (missing grammar, parse failure, etc.)

Requirements

  • Node.js >= 18
  • Git — must be run inside a git repository

Documentation

Visit the official website at diffguardian.vercel.app for an overview of the project, and diffguardian.vercel.app/docs for full documentation, guides, and examples.

The docs site covers:

  • Detailed installation guides
  • Rule-by-rule reference with examples
  • Configuration deep dives
  • CI/CD recipes for GitHub Actions
  • Architecture and internals

Contributing

Contributions are welcome. Please see the Contributing Guide for details on setting up your development environment, project architecture, writing classification rules, and submitting pull requests.

Please review our Code of Conduct before participating.


Changelog

See CHANGELOG.md for a full history of releases and changes.


License

MIT © Aryan Gupta

About

Impact-aware git diff engine that uses WASM Tree-Sitter AST parsing to detect breaking API changes before they ship.Parses both sides of a git diff into ASTs, classifies every structural change, and traces call sites to show you exactly what breaks. TypeScript, Go, Python, Java, Rust — zero config.

Resources

Code of conduct

Contributing

Security policy

Stars

16 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages