Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

diffly logo

⚡ diffly

Your PR is 4,000 lines long. Nobody wants to review it.
diffly reads it for you — files, symbols, checks, tests, blast radius —
and hands you one page and one verdict: PASS, QUARANTINE, or BLOCK.

CI Release Python 3.10+ License: MIT


Install

Pick whichever fits your setup:

curl (recommended)

curl -fsSL https://raw.githubusercontent.com/VIVAAN-DHAWAN/diffly-cli/main/install.sh | sh

pip

pip install diffly-cli

uv

uv tool install diffly-cli

Homebrew

brew install VIVAAN-DHAWAN/diffly-cli/diffly-cli

That's it. If diffly isn't found, add ~/.local/bin to your PATH (curl/pip/uv) and open a new shell.

Upgrading from pre-0.4.0

If you already have diffly installed but are on a version before 0.4.0 (which introduced the built-in update system), run the one-time upgrade script:

curl -fsSL https://raw.githubusercontent.com/VIVAAN-DHAWAN/diffly-cli/main/upgrade.sh | sh

This pulls in 0.4.0+, which has diffly update built in. From that point on, diffly will automatically check for new releases every time you run it and prompt you to update — no more manual upgrades needed.

Updating

From 0.4.0 onwards, just run:

diffly update

Or simply start diffly normally — it will check for updates on launch and ask if you'd like to install the latest version. You can also choose to enable automatic updates so future versions install silently.

Try it in 10 seconds

diffly pr https://github.com/astral-sh/ruff/pull/27808

Paste any pull-request URL — or run bare diffly for a guided flow. You'll get a keyboard-driven, one-page review: verdict, risk flags, checks, and a per-file blast-radius map. Arrow keys move, space toggles sections, Enter renders, q quits.

diffly-cli animated demonstration


What diffly actually does

Large AI-generated pull requests are hard to review because file-by-file diffs hide what matters: which symbols changed, which tests cover them, whether dependencies moved, whether a security-sensitive file was touched. diffly makes the deterministic part of that review visible before any LLM gets involved.

It fetches the PR metadata, changed files, unified diff, commits, status checks, and repository tree; parses source changes with Tree-sitter; maps the blast radius; applies fixed risk rules; and emits a one-page Markdown report with a verdict.

One-page verdictsPASS, QUARANTINE, or BLOCK from fixed, documented rules. Same PR data in, same verdict out — every time.
Blast-radius mapPer file: status, additions/deletions, touched symbols, direct callers visible in changed hunks, and related test files discovered from the repository tree.
Risk flagsAuth/secrets touches, database changes, new dependencies, missing test coverage, failed or pending checks — each with severity and evidence.
Works offlinediffly local triages git changes in any folder on disk — private, archived, or removed repositories included.
CI-nativeBundled GitHub Action posts one self-updating verdict comment on every PR. Stable JSON output for scripts.
Optional AI explainerBring your own OpenAI-compatible key for a generated narrative — sandboxed, redacted, strictly validated, and never allowed to change the verdict.

Local mode — no GitHub required

Analyze git changes on your own disk. No token, no network:

diffly local                      # uncommitted working-tree changes in the current folder
diffly local ~/code/private-repo  # any checkout — even repos deleted from GitHub
diffly local --base main          # compare your branch against main instead

Untracked files are included, so brand-new work is never silently ignored. CI checks don't exist locally, so check-derived flags are skipped; everything else behaves exactly as it does for pull requests.

GitHub Action

Add this to analyze every pull request automatically:

name: Diffly
on: pull_request
permissions:
  contents: read
  pull-requests: write
jobs:
  diffly:
    runs-on: ubuntu-latest
    steps:
      - uses: VIVAAN-DHAWAN/diffly-cli@main

To enable the optional explainer in CI, add DIFFLY_LLM_API_KEY: ${{ secrets.DIFFLY_LLM_API_KEY }} under the step's env. Without a key, the Action runs deterministic-only.

Everyday commands

diffly                                          # guided wizard
diffly pr astral-sh/ruff 27808                  # owner/repo + number
diffly pr https://github.com/astral-sh/ruff/pull/27808   # just paste the URL
diffly pr astral-sh/ruff 27808 --interactive    # keyboard-driven review
diffly pr astral-sh/ruff 27808 --output triage.md
diffly pr astral-sh/ruff 27808 --json           # stable JSON for scripts
diffly setup                                    # guided tutorial
diffly doctor                                   # environment diagnostics
diffly update                                   # check for and install the latest release

For automation prefer --json: successful triage exits 0 regardless of verdict — enforce policy by reading the verdict field. Operational errors exit 2.

Optional AI explanation

Every opted-in explanation is shown in the review. With an AI key, Diffly produces a bounded, redacted AI narrative; without one—or if the provider is unavailable—it creates a clearly labelled local explanation from deterministic review facts instead. Neither path can alter the verdict.

export DIFFLY_LLM_API_KEY="your-key"
export DIFFLY_LLM_BASE_URL="https://api.openai.com/v1"  # omit for the default endpoint
diffly pr OWNER/REPO NUMBER --explain

Default model is gpt-5-mini; override with DIFFLY_LLM_MODEL or --llm-model. The explainer sends bounded, redacted context, requires strict JSON output, rejects citations to files outside the changed-file set, and fails safely back to deterministic triage when anything is off.

The verdict policy

Verdict Rule
BLOCK A required check failed, or production code appears to add a credential-like value.
QUARANTINE Security-sensitive code, database schema/migrations, or newly added dependencies need focused review. Credential-like values limited to tests, fixtures, or docs also quarantine rather than block.
PASS Healthy changes, ready to merge. Pending or unavailable checks, version-bump-only manifest edits, and missing obvious tests stay visible as review notes, not gates. SHIP remains accepted as a legacy alias.

PASS is the normal healthy outcome. A verdict is a review signal, not a claim that a PR is correct or safe in every context.

Real examples

Captured from live terminal sessions against public pull requests:

Pull request Files Lines Verdict Why
microsoft/vscode#330848 25 +2,557 / -251 QUARANTINE production files without obvious test coverage
kubernetes/kubernetes#141413 41 +708 / -740 QUARANTINE missing coverage + pending tide check
astral-sh/ruff#27808 53 +1,845 / -274 BLOCK CodSpeed Performance Analysis check failed

Standalone screenshots: vscode · kubernetes · ruff

Live AI-explainer reports (deterministic verdict preserved): ruff phase 2 · kubernetes phase 2

Current limitations

Tree-sitter parsing covers symbols and direct calls visible in changed hunks, not a full repository-wide call graph. Test-coverage detection is heuristic (filenames + repository tree), so it is presented as a review note rather than a verdict gate. AI model context is bounded and may truncate on very large PRs. A local explanation is used when AI generation is not available.

Roadmap

  • repository-wide symbol resolution and import-aware blast radius;
  • configurable policy files for org-specific risk rules and thresholds;
  • GitHub annotations and check-run output alongside the PR comment;
  • baseline mode reporting only risks introduced vs the target branch;
  • coverage-artifact-based test mapping;
  • SARIF output for code-scanning integrations.

Details: docs/phase-2-contract.md · docs/benchmarks.md

Development

git clone https://github.com/VIVAAN-DHAWAN/diffly-cli.git
cd diffly-cli
python -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
pytest -q

Keep changes focused, include regression tests, and record user-facing changes in CHANGELOG.md. See CONTRIBUTING.md.

Security & privacy

Diffly talks to the GitHub API only for the repo and PR you point it at. Deterministic mode sends no code to any LLM. With --explain, bounded redacted context goes to your configured endpoint — read docs/phase-2-contract.md before enabling it on sensitive repositories. Prefer environment variables over command-line tokens.

Report vulnerabilities privately via GitHub security advisories.

License

Released under the MIT License.

About

Deterministic triage for large GitHub pull requests

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages