← Back to Payloads
Tutorial2026-06-05

Wire an LLM Code Reviewer Into Pre-Commit: 50 Lines, Zero New Tooling

You push, GitHub Actions spins, a bot takes four minutes, and half the comments are noise. Stop. A 50-line pre-commit hook reviews your staged diff with Claude before the push. Five minutes from zero to a working reviewer that blocks on real bugs and costs $0.005 per commit.
Quick Access
Install command
$ mrt install tutorial
Browse related skills
Wire an LLM Code Reviewer Into Pre-Commit: 50 Lines, Zero New Tooling

Wire an LLM Code Reviewer Into Pre-Commit: 50 Lines, Zero New Tooling

You push. GitHub Actions spins. CodeRabbit or some other bot takes four minutes, then you have nine comments, three of which are real, one of which is a typo you actually wanted to fix. Stop. A 50-line pre-commit hook reviews your staged diff with Claude before the push. Five minutes from zero to a working reviewer that blocks on real bugs and costs roughly $0.005 per commit.

The Workflow

1. git commit fires the pre-commit hook. 2. The hook captures git diff --staged and ships it to Claude. 3. Claude replies with severity-tagged issues. 4. The hook blocks the commit on HIGH severity. 5. You amend, force the commit with --no-verify, or fix it first.

That is the entire flow. No new SaaS, no GitHub App, no telemetry, no vendor lock-in.

Step 1: Install pre-commit

bash pip install pre-commit pre-commit install

pre-commit 3.x. One global install handles every repo you will ever touch.

Step 2: Write the Hook

Create .pre-commit-hooks/llm-review/llm-review.sh:

```bash #!/usr/bin/env bash set -euo pipefail

Cap diff at ~8K tokens

DIFF=$(git diff --staged | head -c 32000) [ -z "$DIFF" ] && exit 0

PROMPT="Review this git diff. Flag:

  • Bugs and logic errors (HIGH)
  • Security: secrets, injection, unsafe deserialization (HIGH)
  • Missing tests for new logic (MEDIUM)
  • Style nits (LOW, list at end)

Format: SEVERITY: file:line - description If clean, reply exactly: LGTM"

REVIEW=$(claude -p "$PROMPT" --output-format text <<< "$DIFF") echo "$REVIEW"

if echo "$REVIEW" | grep -q "^HIGH"; then echo "" echo "❌ LLM review flagged HIGH-severity issues. Fix or use --no-verify." exit 1 fi ```

chmod +x it. That is the entire engine. It shells out to the claude-code CLI in -p (non-interactive, piped) mode, which is the right primitive for hook-style automation.

Step 3: Wire It Into pre-commit-config.yaml

```yaml repos:

  • repo: local

hooks:

  • id: llm-review

name: LLM Code Review entry: .pre-commit-hooks/llm-review/llm-review.sh language: system stages: [pre-commit] pass_filenames: false ```

Commit the config. Every subsequent commit runs the review before it lands in your local history.

Cost Guardrails

The naive version sends 200KB diffs and burns $0.50 per commit. Three rules keep it cheap.

Truncate hard. head -c 32000 is roughly 8K tokens. Raise to 100K if you regularly commit 500+ line refactors; cap at 200K beyond that and split the review per file.

Skip docs-only commits. Quick gate at the top of the hook:

bash if ! git diff --staged --name-only | grep -vqE '\.(md|txt|rst)$'; then exit 0 fi

Cache by diff hash. Hash the staged diff with git diff --staged | git hash-object --stdin; if you reviewed that hash in the last 24 hours, skip. Worth adding once you commit more than 20 times a day.

What It Catches (And What It Doesn't)

Catches: null-deref, hardcoded secrets, missing error handling on file I/O, SQL string concatenation, accidental print(secret), off-by-one in pagination, leftover console.log in shipped JS, missing input validation on public functions.

Misses: business-logic bugs without a syntactic signal, multi-file race conditions, performance regressions in hot paths, anything that needs domain knowledge of your problem space.

Treat it as a strict static analyzer with better coverage of modern idioms, not a human replacement. It catches the cheap 80% a reviewer would catch on a first read, and it catches them in five seconds instead of five hours.

The Take

50 lines of bash, 5 minutes of setup, $0.005 per commit, and you will never push a credential inside a print() again. Wire it in. The first time it catches your own bug before CI does, you will not uninstall it.

Mr. Technology


*Tested with pre-commit 3.5+, claude-code CLI 1.0.18+, Anthropic Claude Sonnet 4.5. Requires ANTHROPIC_API_KEY in your env. For GPT-4.1, swap claude -p for codex -p or call the OpenAI SDK directly. Diff cap of 32K chars is conservative; raise it for repos with frequent large refactors, drop it for tightly-budgeted CI-style commits.*

Related Dispatches