Skip to main content

Classify PR diffs by reviewer attention: review, skim, or skip

Project description

garbelour

Classify every hunk in a git diff (or a GitHub pull request) by how much reviewer attention it deserves: review, skim, or skip.

What it does

Garbelour walks the diff between two git refs, runs each hunk through a pipeline of deterministic classifiers, and (optionally) sends whatever the heuristics didn't classify to an LLM for enrichment. The output is a single report in one of three formats:

  • human (terminal): grouped by level, color-coded, with file:line pointers to the lines that matter.
  • markdown (GitHub sticky comment): collapsible Skim/Skip sections and deep links to the exact lines of each Review item.
  • json (machine-readable): one record per classified hunk plus a summary; suitable for piping into other tools.

The format defaults to auto: markdown when posting to GitHub, human in a TTY, json otherwise.

Built-in classifiers

Classifier Level What it catches
generated Skip Files matching globs (*.lock, dist/**, *.min.js, …) or .gitattributes linguist-generated
lockfile Skip Cargo.lock, package-lock.json, yarn.lock, pnpm-lock.yaml, go.sum, …
comment_only Skip Hunks where every changed line is inside a comment / docstring node
import_reorder Skip Same set of imports, different order
public_api Review pub items in Rust, export in TS/JS, module-level def/class in Python
control_flow Review Added / removed / modified if, match/switch, for, while, loop, return
numerical_calc Review Non-trivial arithmetic (≥ 2 operators) or calls into Math.* / np.* / f64::* / …
error_handling Review Removed ?, try/except, try/catch, except clauses

AST-based classifiers use tree-sitter for Rust, Python, TypeScript, and JavaScript. Files in unsupported languages still go through the path-based classifiers (generated, lockfile).

Large hunks aren't auto-elevated. Size alone is a weak signal; instead, big hunks that no other heuristic claims flow through --llm for a content-aware verdict, or fall back to review when the LLM is off.

Install

To install the CLI via Python pip:

pip install garbelour

To instsall the CLI via Rust cargo:

cargo install garbelour

Usage

Locally, against any two refs

garbelour review --base main

Pretty terminal output by default. Pipe to jq to get JSON instead:

garbelour review --base main | jq '.summary'

Force a specific format:

garbelour review --base main --format markdown
garbelour review --base main --format json

Force color on through a pager:

garbelour review --base main --color always | less -R

In a GitHub Action

Garbelour reads the PR event payload from GITHUB_EVENT_PATH and posts a single sticky comment, updating it on each push.

# .github/workflows/garbelour.yml
on:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: read
  pull-requests: write
jobs:
  review-map:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-python@v5
        with:
          python-version: '3.14'
      - run: pip install garbelour
      - run: garbelour review --post-comment --llm
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

fetch-depth: 0 matters: git diff needs both base and head refs in the local repo.

LLM triage (optional)

--llm sends hunks no heuristic claimed to an LLM, which assigns each a level (review/skim/skip), a focus line range, and a one-line rationale.

The provider is auto-detected from whichever API-key env var is present:

Env var Provider Default model
ANTHROPIC_API_KEY Anthropic claude-haiku-4-5
OPENAI_API_KEY OpenAI gpt-4o-mini
OLLAMA_API_KEY Ollama llama3.2

Override with --llm-provider, --llm-model, or --llm-base-url.

Without --llm, hunks no heuristic claimed default to review: the safe option, since the tool hasn't actually evaluated them.

Configuration

garbelour.toml at the repository root is loaded automatically. All fields are optional.

[classify]
generated_globs = ["generated/**", "*.auto.ts"]   # merged with defaults
lockfile_names = ["shrinkwrap.json"]              # merged with defaults

[llm]
provider = "anthropic"
model = "claude-haiku-4-5"

[github]
base_url = "https://github.example.com/api/v3"     # GitHub Enterprise

CLI flags override config; config overrides built-in defaults.

.gitattributes is also consulted: any path marked linguist-generated (or linguist-generated=true) is treated as generated. Glob patterns in .gitattributes are not interpreted; fall back to [classify].generated_globs for those.

Output examples

Human:

garbelour: 3 of 47 hunks need review, 5 worth skimming, 39 mechanical
  Review (3)
    src/engine.rs:145–148    public fn signature changed
    src/engine.rs:201–208    new branch in retry loop
    src/store.rs:88–95 (old) removed try/except block
  Skim (5)
    …
  Skip (39)
    generated (15)        proto/*.pb.go, dist/bundle.js, ...
    lockfile (1)          Cargo.lock
    comment-only (3)      src/engine.rs, src/store.rs, README.md
    import-reorder (8)    src/engine.rs, src/store.rs, ...
    test-fixture (12)     tests/fixtures/*.snap

JSON:

{
  "base_sha": "...",
  "head_sha": "...",
  "hunks": [
    {
      "hunk_id": "src/engine.rs:142",
      "file": "src/engine.rs",
      "line": 142,
      "level": "review",
      "category": "public_api_change",
      "rationale": "public fn signature changed at lines 145–148",
      "focus_lines": { "start": 145, "end": 148, "side": "new" },
      "source": { "heuristic": { "name": "public_api" } }
    }
  ],
  "summary": { "total": 47, "review": 3, "skim": 5, "skip": 39 }
}

Library use

Garbelour is dual-target: a garbelour binary and a garbelour library crate. The pipeline, classifiers, and renderers are public API.

use garbelour::{diff, classify::{Pipeline, PipelineConfig}};

let mut d = diff::extract(std::path::Path::new("."), "main", "HEAD")?;
let pipeline = Pipeline::standard(&PipelineConfig::default())?;
let (classified, unclassified) = pipeline.run(&mut d);

What is New in Garbelour

0.4.0

Refactored to support multiple findings per hunk.

0.3.0

Improved classifier prompt.

Added new classifier for numerical calculations.

0.2.0

Extensions to the public interface.

0.1.0

Initial release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

garbelour-0.4.0.tar.gz (21.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

garbelour-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.3 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

garbelour-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl (3.2 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ s390x

garbelour-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (3.7 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ppc64le

garbelour-0.4.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl (3.3 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ i686

garbelour-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (3.0 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARMv7l

garbelour-0.4.0-cp39-abi3-macosx_11_0_arm64.whl (2.9 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

garbelour-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file garbelour-0.4.0.tar.gz.

File metadata

  • Download URL: garbelour-0.4.0.tar.gz
  • Upload date:
  • Size: 21.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.13.3

File hashes

Hashes for garbelour-0.4.0.tar.gz
Algorithm Hash digest
SHA256 83fa9e02e706b374c942b6e199bdddc0a102199b87213481c7d19dccd3ca97de
MD5 d29d0c2b3274d3c36e3d49790b9984eb
BLAKE2b-256 76629b51cffc8d6e83e1001376a207836c44f7da6507f24109c514a62b781f50

See more details on using hashes here.

File details

Details for the file garbelour-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for garbelour-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 75091a5abe95171e5a24791f90cf27788427deb90f77172d691788388c69cb3a
MD5 f5bbfb9c4226594f82877ea36830c11d
BLAKE2b-256 7e633bc3faafa975a0cdfa94ba1379344b0b3538e2022e07ce5acd1791b2237b

See more details on using hashes here.

File details

Details for the file garbelour-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for garbelour-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 16cbddf01f834236171c604bd5c50803fe91d6fdec9800ef25b291480a330b22
MD5 7e297094f77cc986320cea3d23effabe
BLAKE2b-256 d37072fd1acabf68b83eb2430f4bd9bf179ed7e3d74bcd2a531c87a9ebe46d57

See more details on using hashes here.

File details

Details for the file garbelour-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for garbelour-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 1b155cf2e7e6980551f50d58d6f827b2a7ef356061064994a285db86dc93b73a
MD5 26610d6210157dcc0852a07215266a11
BLAKE2b-256 06da64b411ca5f80849e2ae5d8cc7704e8daddd9f0343afd5270f9a05a0add68

See more details on using hashes here.

File details

Details for the file garbelour-0.4.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for garbelour-0.4.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 75a4a42dadc392eb979d0630a5fa8394fb21ebb5575ab91f6aaa929e0ff49642
MD5 016c4ec468a3c44dbfb118fe990bb136
BLAKE2b-256 690c395acaa0f4aba38b1fc7acba906761e40a57538c867cc604f8c04feb691a

See more details on using hashes here.

File details

Details for the file garbelour-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for garbelour-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 ead165b5eded0502301716b946428d235434d6a8d73a52c915fbf8a644aa5601
MD5 b2327b516c493062abb16829aa2e59de
BLAKE2b-256 d337ef898e6e53472c3b1c76173d44093e215f2c22a7f13a030e16c2a53e3705

See more details on using hashes here.

File details

Details for the file garbelour-0.4.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for garbelour-0.4.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c509935cba05a602f939220973ed65c3471f8973954eccbd061e6339d1b45559
MD5 5c4e894f904a1bef5c2ab622e0f0a8f4
BLAKE2b-256 92c7eaa79bb02010f352361625eb0dcad269ce4ac87e8d6bf36f2fe5e1c1537b

See more details on using hashes here.

File details

Details for the file garbelour-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for garbelour-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 13e0134061630da0ac422205c1b525d11b3b51b08802349539890506edc64892
MD5 d26830f8146a67d939e02836eebb178b
BLAKE2b-256 d7ccb68828d21bb8dcedb7095af31781c9a45929f9259418fbee7de21a233fdf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page