Catches the structural breaks that pass code review
Project description
DiffGuard
Catches the structural breaks that pass code review.
A real bug, in one line
This diff shipped in Flask (PR #5898):
-def redirect(location, code=302, ...):
+def redirect(location, code=303, ...):
One line. Looks fine. A reviewer approves it.
The real impact: 7 endpoints silently change HTTP behavior. POST-to-POST redirects become POST-to-GET. No errors. No warnings. Just broken APIs in production.
DiffGuard catches it:
$ diffguard review eca5fd1d~1..eca5fd1d
⚠ DiffGuard: 2 changes need review
DEFAULT VALUE CHANGED: redirect(location, code=302) → redirect(location, code=303)
src/flask/helpers.py:241 — 7 callers rely on the default
DEFAULT VALUE CHANGED: App.redirect(self, location, code=302) → App.redirect(self, location, code=303)
src/flask/sansio/app.py:935 — 7 callers rely on the default
Tree-sitter AST analysis. No LLM. No network calls. Runs in seconds.
What it catches
Function signature changes, removed/renamed symbols, default value changes — and shows you every caller affected.
What it doesn't catch
Logic bugs, behavioral changes beyond signatures, performance issues, security vulnerabilities. DiffGuard detects structural breaks, not all bugs.
When there's nothing structural to report, it stays silent (exit code 0, no output).
Quick Start
pip install diffguard
diffguard review main..feature
Exit codes: 0 = nothing noteworthy, 1 = findings, 2 = error.
How It Works
- Parses the diff using tree-sitter AST analysis (not regex)
- Extracts symbols — functions, classes, signatures
- Detects high-signal changes — signature changes, removed symbols, default value changes
- Scans for callers — finds every file that references changed symbols
- Outputs actionable context — or stays silent if nothing matters
Agent Integration
Works with Claude Code, Cursor, GitHub Actions, or any agent that can run a CLI command.
Add one line to your agent config — DiffGuard is silent when nothing matters.
See the full Agent Integration Guide for hooks, CI patterns, and snippets for Claude Code and Cursor.
GitHub Action
# .github/workflows/diffguard.yml
name: DiffGuard PR Review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
diffguard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: ostehost/diffguard@main
Languages
- Python (most mature — extensive real-world validation)
- TypeScript / JavaScript
- Go
- More planned (Rust, Java, C#)
Philosophy
- Silence is a feature. No findings? No output. Most diffs don't need structural analysis.
- Local-first. Your code never leaves your machine. No SaaS, no API keys, no accounts.
- Agent-native. CLI + JSON output.
pip installand go. - Precision over recall. We'd rather miss a minor issue than cry wolf on every PR.
License
BSL 1.1 — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file diffguard-0.1.3.tar.gz.
File metadata
- Download URL: diffguard-0.1.3.tar.gz
- Upload date:
- Size: 150.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
326cd5066a9d6df7b1306e5c19807ad48b20a31578513549e50a61840800e1eb
|
|
| MD5 |
bb9c669deed7b2c362ca67304484eb80
|
|
| BLAKE2b-256 |
3a90593c0e86465a6818c3f23ed40cfc5b657276df3458f5d1c0038902230e6d
|
Provenance
The following attestation bundles were made for diffguard-0.1.3.tar.gz:
Publisher:
publish-to-pypi.yml on ostehost/diffguard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diffguard-0.1.3.tar.gz -
Subject digest:
326cd5066a9d6df7b1306e5c19807ad48b20a31578513549e50a61840800e1eb - Sigstore transparency entry: 953723842
- Sigstore integration time:
-
Permalink:
ostehost/diffguard@8dceebda2fba7bd89b54e65249aa0b610a8bab7e -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/ostehost
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@8dceebda2fba7bd89b54e65249aa0b610a8bab7e -
Trigger Event:
push
-
Statement type:
File details
Details for the file diffguard-0.1.3-py3-none-any.whl.
File metadata
- Download URL: diffguard-0.1.3-py3-none-any.whl
- Upload date:
- Size: 35.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b2adddfce9dce5da47bf365c5c779dfd3f49c0a30d400b81cc94f185a52d0ef
|
|
| MD5 |
baa12413d2a7c76deb7ce2c0fd6411bc
|
|
| BLAKE2b-256 |
78c1138731c3fd216a743c0adb5799b805ff8cde4ca9281028fc5639bc362e88
|
Provenance
The following attestation bundles were made for diffguard-0.1.3-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on ostehost/diffguard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diffguard-0.1.3-py3-none-any.whl -
Subject digest:
7b2adddfce9dce5da47bf365c5c779dfd3f49c0a30d400b81cc94f185a52d0ef - Sigstore transparency entry: 953723901
- Sigstore integration time:
-
Permalink:
ostehost/diffguard@8dceebda2fba7bd89b54e65249aa0b610a8bab7e -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/ostehost
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@8dceebda2fba7bd89b54e65249aa0b610a8bab7e -
Trigger Event:
push
-
Statement type: