Back to Blog
8 min
technical

Claude God Tip #2: Turn Git Hooks Into AI-Powered Code Reviewers

Stop committing console.logs and TODO comments. Here's how to combine Git hooks with Claude for intelligent pre-commit checks that actually understand your code.

ClaudeGitDeveloper ProductivityCLI ToolsAutomationCode Quality

Claude God Tip #2: Turn Git Hooks Into AI-Powered Code Reviewers

Published: November 18, 2025 • 8 min read

The beautiful thing about attempting to be a Claude God is that I'm aiming for a level of mastery where no stones must be left unturned. And I mean none, nada. In that process, I am going to slowly but surely become less of a chauffeur when working with Claude and other adjoining tools that I use Claude with.

In the blog post where I launched this series, I mentioned that I'll either give one big tip or one small tip. Well today, we're looking at a big tip.

Before you attempt to follow along with this, if you haven't installed Claude in your terminal yet, you should probably check out the quickstart guide to get started.

The Problem: Repetitive Commit Instructions

As I build applications using Claude in the terminal, I often want it to commit the changes we've made. But there are a series of actions I have to specify to Claude before asking it to commit changes. Having to specify these steps every single time I need Claude to commit multiple batches of changes can be time consuming.

Look at me, complaining about guiding an AI to make commits for me when I don't even have to do the work... how did I become this lazy?

But you see, laziness does not always have to be a bad thing. When you combine selective laziness with a deep hatred of mediocrity (and therefore high standards for the work you create), you seek out ways to improve processes that most people don't even think of.

So today, we are going to be talking about combining Git Hooks with the amazing power of Claude.

What Are Git Hooks?

If you are reading this, you have probably worked with Git and know a number of Git commands, the most popular being git add, git commit, git push, git pull, etc. What if I tell you that you can create scripts that run automatically before any of these commands fully execute?

Git hooks are like bodyguards to specific actions in your Git repository. These bodyguards exist in the form of scripts which, when used to their full capacity, will allow or deny a specific Git command from executing.

You can also think about them as "If this, then that" rules for Git:

  • IF you're about to commit code → THEN run this check first
  • IF you're about to push code → THEN run tests first
  • IF you just pulled code → THEN install new dependencies

Types of Git Hooks

There are many types of hooks. Here are some of the most popular ones:

pre-commit: This hook runs before a commit is created to check code quality and run linters. It's a bodyguard of the git commit command.

prepare-commit-msg: This hook runs before a commit message editor opens to generate commit messages. It's also a bodyguard of the git commit command.

commit-msg: This hook runs after you write a commit message to validate the format of the message. It's also a bodyguard of the git commit command. When you think about it, it makes sense that this command needs multiple bodyguards.

pre-push: This hook runs before you push a repository to the remote branch to run tests and prevent one from pushing broken code. It's a bodyguard of the git push command.

post-commit: This hook runs after a commit is created to possibly send notifications and update any logs. In this instance, you can see that this specific bodyguard of the git commit command does a really good job at being a messenger as well.

Where Do Hooks Live?

Now you may be wondering, where do these hooks (which exist as scripts) live?

Good question! You know that .git folder that is created every time you initialize a Git repository in a directory? Yup, that one. That is where the hook scripts live. You create a script file for any hook you want in the .git/hooks/ directory.

For this blog post, we are going to focus on the pre-commit hook.

The Traditional Way: Pre-Commit Without AI

Now how did our ancestors use the pre-commit hook? Great question again! You've been asking a lot of good questions, keep it up!

When I refer to "our ancestors," I am talking about every single one of us programmers (myself included), but specifically about what our workflow with the pre-commit hook looked like without AI integration.

The pre-commit hook below will check for any console.log statements in our staged files. This is an important check for most developers as we do not want sensitive data that was logged to the console during testing to be pushed to production. I have been guilty of this in the past as it can be easy to forget, but when you have a bodyguard in front of the git commit command, it leaves no room for being careless.

Step 1: Create the Hook Script

Navigate to your project and create the script using this command:

nano .git/hooks/pre-commit

Step 2: Add the Script Contents

In the nano editor, add the following:

#!/bin/bash
# .git/hooks/pre-commit

echo "🔍 Checking for console.logs..."

# Get list of staged .js and .ts files
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|tsx)$')

# Check each file for console.log
if echo "$FILES" | xargs grep -n "console.log" 2>/dev/null; then
    echo ""
    echo "❌ Found console.log statements!"
    echo "Remove them before committing."
    exit 1  # Exit with failure (1) to prevent commit
fi

echo "✅ No console.logs found."
exit 0  # Exit with success (0) to allow commit

Save and exit nano by:

  1. Pressing Ctrl + X
  2. Pressing Y (yes, save)
  3. Pressing Enter (to confirm the filename)

Step 3: Make the Script Executable

Run the command:

chmod +x .git/hooks/pre-commit

This command does the following:

  • chmod = "change mode" (changes the file permissions)
  • +x = "add the execute permission"

Without this step, Git cannot run the script.

Understanding the Script

Let me break down the key parts:

#!/bin/bash: This line tells the system that this is a bash script. If you do not add this line, Git will not know how to run the file.

FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|tsx)$'): This command gets a list of staged files that end with .js, .ts, or .tsx.

Here's what each part does:

  • git diff --cached = show changes in staging area
  • --name-only = only show filenames, not content
  • --diff-filter=ACM = Added, Copied, or Modified files (not Deleted)
  • grep -E '\.(js|ts|tsx)$' = grab files that end with .js, .ts, or .tsx

The if statement: The part of the code surrounded by if and fi checks each file for any console.log() statements. If there are any, the exit 1 command will prevent the commit from happening. If there are none, the exit 0 command will allow the commit to proceed.

Now when you complete the steps above, you can run Git commands as normal using git commit -m 'Commit message' and watch the bodyguard do its thing.

The Problem with Traditional Hooks

Here's the thing. This bodyguard we just created, by relying solely on the ancient powers of grep, isn't very smart. (Sorry grep! I do not deny your usefulness, I promise.)

The script above simply checks for the text console.log. But what if the statement was in a comment? What if it's a harmless console.log statement that poses no risks? What if it's in a file you intentionally want to keep for debugging?

You see, grep does not understand context. And that is why we, the developers of today, must embrace the more enhanced version of checking intelligently with Claude.

The Claude-Powered Way: Intelligent Pre-Commit Checks

The only difference between this version and the one above is the content of the script. Replace your pre-commit hook with this:

#!/bin/bash
# .git/hooks/pre-commit

echo "🔍 Running code quality checks with Claude..."

# Get staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)

# Ask Claude to review
REVIEW_RESULT=$(claude "
Review these staged files for commit:
Files: $STAGED_FILES

Check for:
1. console.log statements that should be removed
2. TODO comments that need addressing
3. Missing TypeScript types on functions
4. Obvious code quality issues

Rules:
- Ignore files in: node_modules/, dist/, build/, .next/
- Only check staged files (files about to be committed)
- For each issue found:
  * Show filename and line number
  * Explain why it's a problem
  * Suggest how to fix it

If NO issues found, output: 'CHECKS_PASSED'
If issues found, list them clearly.
")

# Check result
if echo "$REVIEW_RESULT" | grep -q "CHECKS_PASSED"; then
    echo "✅ All checks passed!"
    exit 0
else
    echo ""
    echo "❌ Issues found:"
    echo "$REVIEW_RESULT"
    echo ""
    read -p "Fix issues now? (y=fix and stop commit, n=commit anyway) " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo "⚠️  Proceeding with commit despite issues..."
        exit 0
    else
        echo "🛠️  Please fix the issues and try committing again."
        exit 1
    fi
fi

Understanding the Claude-Powered Script

Let me break down the parts that are different from the traditional version:

REVIEW_RESULT=$(claude "..."): This runs the Claude command and captures the output in a variable:

  • $(...) = "run this command and save the output"
  • Output gets stored in the REVIEW_RESULT variable

if echo "$REVIEW_RESULT" | grep -q "CHECKS_PASSED"; then: This checks if the output returned by Claude contains "CHECKS_PASSED". See, grep is still useful here! We must never completely abandon our ancient ways.

  • echo "$REVIEW_RESULT" = print the variable
  • | = pipe (send output to next command)
  • grep -q "CHECKS_PASSED" = quietly search for this text
  • if ... then = if found, do this

read -p "Fix issues now? (y/n) " -n 1 -r: This asks the user for input to determine the next steps:

  • "..." = prompt message
  • -n 1 = read only 1 character (don't wait for Enter)
  • -r = raw input (don't interpret backslashes)

if [[ $REPLY =~ ^[Nn]$ ]]; then: This checks if the user pressed 'n' or 'N':

  • $REPLY = variable containing user's input
  • =~ = matches regex pattern
  • ^[Nn]$ = exactly 'n' or 'N', nothing else

Why This Approach Is Better

What makes this approach better? Well, a lot of things actually!

First, Claude attempts to understand the code context. It's not just reading lines, it's analyzing them. It explains the issue in natural language and can even suggest fixes. It also gives you a choice to fix the issue or proceed with the commit, allowing for more flexibility.

It's just awesome, isn't it?

And the script above is not just checking for console.log statements. It checks for:

  1. console.log statements that should be removed
  2. TODO comments that need addressing
  3. Missing TypeScript types on functions
  4. Obvious code quality issues

Expanding Your Checks

You can expand this list further by asking Claude to check for as many things as you'd like that might be relevant to your project or company. For instance, it could check for:

  • Hardcoded API keys or secrets (security vulnerability)
  • Commented-out code blocks (code cleanliness)
  • Functions longer than 50 lines (maintainability)
  • Missing error handling in async functions (reliability)
  • Unused imports (bundle size optimization)
  • Accessibility issues in JSX (a11y compliance)
  • SQL queries without parameterization (SQL injection prevention)
  • Missing unit tests for new functions (test coverage)
  • Deprecated API usage (future-proofing)
  • Non-descriptive variable names (code readability)

Just add them to the "Check for:" section of your prompt!

Bypassing the Hook (When Necessary)

One final note. If you ever need to bypass the rules you set for the pre-commit hook, you can always commit with the --no-verify flag:

git commit --no-verify -m "emergency fix"

Use this sparingly! The whole point of the hook is to catch issues before they make it into your codebase. But sometimes you need to push an emergency fix and deal with the cleanup later.


And that's all for Claude God Tip #2! This one was a big tip, but I hope it helps you level up your Git workflow with AI-powered code reviews.

As always, thanks for reading!

Share this article

Found this helpful? Share it with others who might benefit.