Skip to main content

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.

Metadata

Release files for garbelour 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for garbelour 0.4.0
File Size Uploaded Provenance Actions
garbelour-0.4.0.tar.gz 21.1 kB Without provenance Details for garbelour-0.4.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for garbelour 0.4.0
File Actions
garbelour-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details for garbelour-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
garbelour-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl CPython 3.9 abi3 Linux glibc 2.17+ IBM System/390x Details for garbelour-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl
garbelour-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl CPython 3.9 abi3 Linux glibc 2.17+ PowerPC 64-le Details for garbelour-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
garbelour-0.4.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-32 Details for garbelour-0.4.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl
garbelour-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl CPython 3.9 abi3 Linux glibc 2.17+ ARMv7l Details for garbelour-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
garbelour-0.4.0-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details for garbelour-0.4.0-cp39-abi3-macosx_11_0_arm64.whl
garbelour-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details for garbelour-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl

Total release size: 22.5 MB

Release files / garbelour-0.4.0.tar.gz

Download URL garbelour-0.4.0.tar.gz
Size 21.1 kB
Tags Source
SHA-256 checksum
How to use checksums
83fa9e02e706b374c942b6e199bdddc0a102199b87213481c7d19dccd3ca97de
BLAKE2b-256 checksum
How to use checksums
76629b51cffc8d6e83e1001376a207836c44f7da6507f24109c514a62b781f50
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Release files / garbelour-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL garbelour-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.3 MB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
75091a5abe95171e5a24791f90cf27788427deb90f77172d691788388c69cb3a
BLAKE2b-256 checksum
How to use checksums
7e633bc3faafa975a0cdfa94ba1379344b0b3538e2022e07ce5acd1791b2237b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Release files / garbelour-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl

Download URL garbelour-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl
Size 3.2 MB
Tags CPython 3.9 Linux glibc 2.17+ IBM System/390x abi3
SHA-256 checksum
How to use checksums
16cbddf01f834236171c604bd5c50803fe91d6fdec9800ef25b291480a330b22
BLAKE2b-256 checksum
How to use checksums
d37072fd1acabf68b83eb2430f4bd9bf179ed7e3d74bcd2a531c87a9ebe46d57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Release files / garbelour-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl

Download URL garbelour-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Size 3.7 MB
Tags CPython 3.9 Linux glibc 2.17+ PowerPC 64-le abi3
SHA-256 checksum
How to use checksums
1b155cf2e7e6980551f50d58d6f827b2a7ef356061064994a285db86dc93b73a
BLAKE2b-256 checksum
How to use checksums
06da64b411ca5f80849e2ae5d8cc7704e8daddd9f0343afd5270f9a05a0add68
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Release files / garbelour-0.4.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl

Download URL garbelour-0.4.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl
Size 3.3 MB
Tags CPython 3.9 Linux glibc 2.17+ x86-32 abi3
SHA-256 checksum
How to use checksums
75a4a42dadc392eb979d0630a5fa8394fb21ebb5575ab91f6aaa929e0ff49642
BLAKE2b-256 checksum
How to use checksums
690c395acaa0f4aba38b1fc7acba906761e40a57538c867cc604f8c04feb691a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Release files / garbelour-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl

Download URL garbelour-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Size 3.0 MB
Tags CPython 3.9 Linux glibc 2.17+ ARMv7l abi3
SHA-256 checksum
How to use checksums
ead165b5eded0502301716b946428d235434d6a8d73a52c915fbf8a644aa5601
BLAKE2b-256 checksum
How to use checksums
d337ef898e6e53472c3b1c76173d44093e215f2c22a7f13a030e16c2a53e3705
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Release files / garbelour-0.4.0-cp39-abi3-macosx_11_0_arm64.whl

Download URL garbelour-0.4.0-cp39-abi3-macosx_11_0_arm64.whl
Size 2.9 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
c509935cba05a602f939220973ed65c3471f8973954eccbd061e6339d1b45559
BLAKE2b-256 checksum
How to use checksums
92c7eaa79bb02010f352361625eb0dcad269ce4ac87e8d6bf36f2fe5e1c1537b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Release files / garbelour-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl

Download URL garbelour-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl
Size 3.0 MB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
13e0134061630da0ac422205c1b525d11b3b51b08802349539890506edc64892
BLAKE2b-256 checksum
How to use checksums
d7ccb68828d21bb8dcedb7095af31781c9a45929f9259418fbee7de21a233fdf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.13.3

Security for garbelour 0.4.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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