Tutorials & Guides
How to Build an Automated Git Commit Guard with Claude 3.5 Sonnet and Husky
Tired of accidentally committing console logs, temporary mock data, or raw API secrets? Build a local pre-commit hook that uses Claude to block bad commits before they hit your remote.
Updated 10/13/2026
Stop Committing Your Leftover Garbage
We have all done it. You spend three hours debugging a weird race condition, finally fix it, and eagerly run git commit -am "fix: resolves race condition". Only after your pull request is opened do you realise you left three console.log() statements, a temporary hardcoded bearer token, and a comment that reads // TODO: fix this absolute mess before shipping right in the middle of your core authentication logic.
Traditional regex-based git hooks (like standard pre-commit scripts) are too dumb to save you from this. They either match too little or trigger false positives on completely valid code. We need something with context-awareness.
In this tutorial, we will build an automated Git Commit Guard using Claude 3.5 Sonnet and Husky. This guard will automatically inspect your staged git diffs, flag structural issues, warn you about potential hardcoded credentials, and block the commit if it detects anything that shouldn't make it to production.
Time to make your development workflow tick like a precision watch.
Prerequisites
Before we write any code, ensure you have the following installed and configured:
- Node.js (v18 or higher recommended)
- A git repository already initialised
- An Anthropic API Key (set as
ANTHROPIC_API_KEYin your environment variables) - The package manager of your choice (we will use
npmfor this guide)
Step 1: Initialize Husky and Install Dependencies
First, we need to install Husky, which makes setting up Git hooks painless, along with the Anthropic SDK. Run the following command in your project root:
`bash
npm install husky @anthropic-ai/sdk dotenv --save-dev
`
Now, initialise Husky in your repository. This will create a .husky directory:
`bash
npx husky init
`
By default, husky init creates a boilerplate pre-commit hook in .husky/pre-commit that runs npm test. Open that file and clear the contents. We will replace it with our custom script call shortly.
Step 2: Write the Git Diff Grabber
We need a script that grabs only the staged changes from Git. If we pass the entire repository to Claude, we will quickly burn through our API limits and context windows. Staged changes are the only things that matter right now.
Create a new file named scripts/git-guard.js and add the following code to run git diff --cached and capture the output:
`javascript
const { execSync } = require('child_process');
const { Anthropic } = require('@anthropic-ai/sdk');
require('dotenv').config();
// Capture staged diff function getStagedDiff() { try { return execSync('git diff --cached --raw-style=no-prefix').toString().trim(); } catch (error) { console.error('❌ Failed to retrieve staged git changes.'); process.exit(1); } }
const diff = getStagedDiff();
if (!diff) {
console.log('✅ No staged changes found. Skipping Git Guard.');
process.exit(0);
}
`
Step 3: Prompting Claude to Be Your Code Quality Bouncer
Now that we have the diff, we want to send it to Claude. We need a highly structured, reliable system prompt. If Claude finds blocker issues, it needs to explicitly output a failure keyword (like [REJECT]) along with the reasons. If everything looks good, it should output [PASS].
Add this configuration to your scripts/git-guard.js file:
`javascript
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const SYSTEM_PROMPT = `You are an automated Git pre-commit hook guard. Your job is to inspect incoming staged code changes and decide if they are safe, tidy, and ready for production.
You must respond with exactly one of two decisions: - If you find severe issues (hardcoded secrets, debugging statements, temporary mock bypasses, or broken structures), start your response with '[REJECT]' followed by a brief, bulleted list of issues. - If the changes are clean and production-ready, respond with exactly '[PASS]'.
Things to look out for: 1. Hardcoded API keys, secrets, private keys, or passwords. 2. Debugging artifacts left behind (e.g., console.log, console.dir, debugger statements, print statements). 3. Blatant placeholders or bypasses (e.g., const user = 'test-user-bypass', mockPaymentSuccess = true). 4. Lazy, non-descriptive TODOs that should be tracked in a ticketing system instead.
Be constructive. Do not reject code for minor stylistic preferences. Only reject if it violates the safety or clean code rules listed above.`;
`
Step 4: Building the AI Verification Runner
Next, let's write the execution function that calls Claude 3.5 Sonnet and parses the output. Append this to your script:
`javascript
async function runGitGuard() {
console.log('🤖 Git Guard is inspecting your staged changes...');
try {
const response = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 500,
temperature: 0,
system: SYSTEM_PROMPT,
messages: [
{ role: 'user', content: Please inspect the following git diff:\n\n${diff} }
]
});
const analysis = response.content[0].text.trim();
if (analysis.startsWith('[REJECT]')) { console.error('\n❌ [COMMIT BLOCKED] Claude flagged issues with your staged changes:\n'); console.error(analysis.replace('[REJECT]', '').trim()); console.error('\nFix these issues or bypass this check with: git commit --no-verify\n'); process.exit(1); } else if (analysis.startsWith('[PASS]')) { console.log('\n✅ [COMMIT APPROVED] Code changes cleared by Claude.'); process.exit(0); } else { // Fallback in case of non-standard response formatting console.warn('⚠️ Guard could not parsing the AI response clearly. Let\'s take a safe route:'); console.log(analysis); process.exit(0); } } catch (apiError) { console.warn('⚠️ Unable to connect to Anthropic API. Bypassing check to avoid blocking flow.', apiError.message); process.exit(0); // Fail-safe: don't block development if API is down } }
runGitGuard();
`
Step 5: Connecting the Guard to Husky
Now we must instruct Husky to run this Node.js script whenever you execute git commit.
Open .husky/pre-commit and paste the following line:
`bash
node scripts/git-guard.js
`
To make sure your environment variables (like ANTHROPIC_API_KEY) are read correctly when executing the pre-commit hook via your terminal/GUI, your local .env configuration should be loaded properly. The dotenv require inside our script takes care of this, but ensure your environment variables are set globally or present in a local .env file at your repository's root.
Testing the Commit Guard
Let's test if our setup actually prevents mistakes.
Create a file named src/index.js (or edit an existing one), stage a bad change, and attempt to commit it:
`javascript
// src/index.js
const API_KEY = "sk_live_51HxFy7L9Uv5391F09sF83k2Lp90"; // Mock secret
console.log("Debugging the database response:", API_KEY);
`
Stage the changes:
`bash
git add src/index.js
`
Now attempt to commit your changes:
`bash
git commit -m "feat: added base user routes"
`
If your setup is correct, Claude will scan the diff, detect the hardcoded key and the lingering console log, output the details, and exit with code 1—instantly blocking the commit from going through.
Troubleshooting and Optimisations
If you run into issues with your hook execution or authentication errors with the Anthropic API, check out our Claude troubleshooting guide for specific setup help.
For production development workflows, keep in mind:
Performance*: If you find the API call sluggish on massive changes, consider limiting the guard to only run on certain file types (like .js, .ts, .py) by pre-filtering files in your git-guard.js script.
Overriding*: If you have a legitimate reason to commit something the guard blocks, you can bypass the hook using the --no-verify flag: git commit -m "WIP check" --no-verify.
Keep going
Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.
Which AI should I use for this?
Tickd is independent and not affiliated with any AI company.