DEV Community

brian austin
brian austin

Posted on

Claude Code git hooks: automate code review before every commit

Claude Code git hooks: automate code review before every commit

One of the most underused Claude Code patterns I've found: combining Claude with git hooks to get automated code review on every commit. Here's the exact setup I use.

The problem

You're using Claude Code to write code, but you're still committing slop. Unreviewed edge cases, missing error handling, test coverage gaps — all landing in your repo because you forgot to ask Claude to check.

The solution: pre-commit hook + Claude

Create .git/hooks/pre-commit:

#!/bin/bash

# Get staged changes
DIFF=$(git diff --cached --unified=3)

if [ -z "$DIFF" ]; then
  exit 0
fi

# Send to Claude for review
REVIEW=$(curl -s https://api.anthropic.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d "{
    \"model\": \"claude-opus-4-5\",
    \"max_tokens\": 500,
    \"messages\": [{
      \"role\": \"user\",
      \"content\": \"Review this git diff for critical issues only (bugs, security, data loss). If clean, respond with LGTM. If issues found, list them briefly.\\n\\n$DIFF\"
    }]
  }" | jq -r '.content[0].text' 2>/dev/null)

echo "Claude review: $REVIEW"

# Block commit if serious issues found
if echo "$REVIEW" | grep -qi "CRITICAL\|security\|data loss\|SQL injection\|XSS"; then
  echo "❌ Commit blocked by Claude review"
  exit 1
fi

echo "✅ Claude review passed"
exit 0
Enter fullscreen mode Exit fullscreen mode

Make it executable:

chmod +x .git/hooks/pre-commit
Enter fullscreen mode Exit fullscreen mode

The cost problem with this approach

Here's the catch: if you're using the Anthropic API directly, each pre-commit review costs ~$0.003-0.015 depending on diff size. At 20+ commits/day, that's $2-9/month just for pre-commit hooks.

I solved this by routing through SimplyLouie — a flat-rate Claude API proxy at $2/month. Same claude-opus-4-5 model, same API format, just set ANTHROPIC_BASE_URL:

export ANTHROPIC_BASE_URL=https://simplylouie.com/api
export ANTHROPIC_API_KEY=your_simplylouie_key
Enter fullscreen mode Exit fullscreen mode

Now the hook uses the proxy and you're not watching the meter.

Better version: reviewdog integration

If you're using reviewdog for CI, you can pipe Claude output:

#!/bin/bash
DIFF=$(git diff --cached)

curl -s https://api.anthropic.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d "{
    \"model\": \"claude-opus-4-5\",
    \"max_tokens\": 1000,
    \"messages\": [{
      \"role\": \"user\",
      \"content\": \"Review this diff. For each issue, output in format: FILE:LINE: SEVERITY: MESSAGE. Severities: ERROR, WARNING, INFO.\\n\\n$DIFF\"
    }]
  }" | jq -r '.content[0].text' | reviewdog -f=golint -reporter=local
Enter fullscreen mode Exit fullscreen mode

CLAUDE.md config to match

Add to your CLAUDE.md to make Claude Code aware of the hook policy:

## Git Policy
- All commits reviewed by pre-commit hook
- Hook blocks on CRITICAL/security/data loss keywords
- Run `git commit --no-verify` only for WIP commits
- Hook uses claude-opus-4-5 via ANTHROPIC_BASE_URL proxy
Enter fullscreen mode Exit fullscreen mode

What Claude catches that linters miss

Linters catch syntax and style. Claude catches:

  • Logic errors: "this loop will exit on the first iteration because of the break"
  • Race conditions: "this isn't thread-safe if called concurrently"
  • Edge cases: "what happens when the array is empty?"
  • API misuse: "this Stripe charge isn't idempotent"

The pre-commit hook won't replace a full code review. But it catches the embarrassing stuff before it lands.

Complete setup script

#!/bin/bash
# setup-claude-hooks.sh

# Install dependencies
npm install -g jq 2>/dev/null || true

# Create hooks directory if needed  
mkdir -p .git/hooks

# Write pre-commit hook
cat > .git/hooks/pre-commit << 'HOOK'
#!/bin/bash
DIFF=$(git diff --cached --unified=3)
[ -z "$DIFF" ] && exit 0

REVIEW=$(curl -s https://api.anthropic.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d "{\"model\":\"claude-opus-4-5\",\"max_tokens\":500,\"messages\":[{\"role\":\"user\",\"content\":\"Review diff for critical issues. LGTM if clean.\\n\\n$DIFF\"}]}" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['content'][0]['text'])" 2>/dev/null)

echo "Claude: $REVIEW"
[[ "$REVIEW" =~ (CRITICAL|security|data.loss) ]] && { echo "❌ Blocked"; exit 1; }
echo "✅ Passed"; exit 0
HOOK

chmod +x .git/hooks/pre-commit
echo "Claude pre-commit hook installed!"
Enter fullscreen mode Exit fullscreen mode

Run it:

chmod +x setup-claude-hooks.sh && ./setup-claude-hooks.sh
Enter fullscreen mode Exit fullscreen mode

The flat-rate angle

This only makes sense cost-wise at flat-rate. Pay-per-token for pre-commit hooks is a bad deal. SimplyLouie at $2/month makes this economically rational — unlimited reviews, same model.


What's your current pre-commit stack? I'm curious what people are catching with automated review that linters miss.

Top comments (0)