11 Git Hooks That Make AI Agents Safe to Run Unsupervised
When you have AI agents writing code and making commits, you need automated guardrails. Not suggestions, not guidelines - actual enforcement that physically prevents bad things from happening. That's what hooks give you.
I run 11 custom hooks in my Claude Code setup. Each one exists because something went wrong (or almost went wrong) at least once. Here's every hook, what it does, and why it matters.
1. block-env-files
This is the most critical hook. It prevents any .env, .env.local, or credentials file from being committed.
# Blocks commits that include environment files
# Matches: .env, .env.local, .env.production, credentials.json, etc.
# Why: AI agents don't understand that these contain secrets
AI agents are helpful and eager. If you ask one to "set up the database connection," it might create a .env file with your database URL and helpfully commit it. This hook makes that physically impossible.
2. block-console-log-commits
Prevents commits that add new console.log statements to production code.
# Scans staged files for new console.log additions
# Ignores: test files, config files, debug utilities
# Why: Agents add debug logging during development and forget to remove it
When an agent is debugging an issue, it'll often add console.log statements to trace the problem. That's fine - but those shouldn't make it into the commit. This hook catches them.
3. post-format (Auto Prettier)
Automatically runs Prettier on any file after it's edited.
# Runs after every file edit
# Applies: prettier --write on the edited file
# Why: Agents don't always match your formatting config exactly
This is a "post-edit" hook rather than a pre-commit hook. Every time an agent edits a file, Prettier runs immediately. This means the diff you review is always clean - no formatting noise mixed in with real changes.
4. secrets-scanner
Scans committed content for patterns that look like secrets: API keys, tokens, passwords, private keys.
# Regex patterns for common secret formats:
# - AWS access keys (AKIA...)
# - Private keys (-----BEGIN)
# - High-entropy strings near keywords like "password", "secret", "token"
# Why: Defence in depth - even if .env is blocked, secrets can appear elsewhere
This is the second line of defence after block-env-files. Secrets don't only live in .env files. They can end up in config files, test fixtures, or even comments. This hook uses pattern matching to catch them wherever they appear.
5. session-context-loader
Loads relevant context at the start of each session - recent git history, open PRs, project state.
# Runs on session start
# Loads: recent commits, branch state, open PRs, CI status
# Why: Agents work better with context about what's been happening
This isn't a safety hook - it's a quality hook. When an agent starts working, it should know what branch it's on, what the recent changes were, and whether CI is passing. This hook provides that automatically.
6. task-completed-gate
Prevents marking a task as "done" until verification checks pass.
# Runs when an agent reports task completion
# Checks: typecheck passes, lint passes, tests pass
# Why: "It works on my machine" is even more dangerous with AI agents
An agent might think it's done after writing the code. But "code written" and "code working" are very different things. This hook runs the full verification suite before allowing a task to close.
7. teammate-idle-lint
When an agent is idle (waiting for input or between tasks), it runs lint on recently changed files.
# Triggers during agent idle periods
# Runs: lint + prettier on files changed in current branch
# Why: Catches formatting/lint issues early, before they compound
This is a "use idle time productively" hook. Rather than having agents sit idle between tasks, they do housekeeping. It's a small thing, but it means the codebase stays clean throughout a feature build, not just at commit time.
8. block-i18n-files
Prevents direct editing of internationalisation files.
# Blocks edits to: locales/*.json, translations/*, i18n/*
# Why: i18n files are often auto-generated or managed by a translation service
In projects with internationalisation, the translation files are typically managed by a service like Crowdin or Lokalise. An AI agent doesn't know that and might helpfully "fix" a translation, overwriting the canonical version. This hook prevents that.
9. block-generated-files
Prevents editing of auto-generated files like GraphQL types, Prisma clients, or OpenAPI schemas.
# Blocks edits to files matching generated-file patterns:
# - **/generated/**, *.generated.ts, prisma/client/**, graphql.ts
# Why: Editing generated files is always wrong - the source of truth is elsewhere
This one saves hours of debugging. If an agent modifies a generated type file, the next code generation run will overwrite the change. But in the meantime, the modified types might have caused other code to be written against the wrong interface. It's a cascading problem that's best prevented entirely.
10. block-ui-kit-imports
Enforces that UI components come from the project's design system, not directly from third-party libraries.
# Blocks: import { Button } from '@mui/material'
# Allows: import { Button } from '@/ui-kit'
# Why: Agents don't know your team wraps third-party components
Most mature projects wrap their UI library (Material UI, Chakra, etc.) in a custom UI kit. An AI agent won't know this unless you tell it. Rather than telling every agent in every prompt, this hook enforces it automatically.
11. block-bare-background-agents
Prevents spawning background agents without a team context.
# Blocks: Task with run_in_background but no team_name
# Why: Untracked background agents are invisible and unmanageable
This is a meta-hook - it governs how the AI system itself behaves. Background agents that aren't part of a team are invisible: you can't see their progress, can't coordinate their work, and can't stop them cleanly. This hook ensures every background agent belongs to a named team.
Building Your Own Hook System
You don't need all 11 on day one. Start with the safety-critical ones:
block-env-files- non-negotiablesecrets-scanner- non-negotiablepost-format- keeps diffs cleanblock-console-log-commits- keeps production clean
Then add the rest as you encounter the problems they solve. Every hook in my system exists because of a real incident. Yours will evolve the same way.
The full hook configuration is in my Claude Code Power Setup gist. Each hook includes the complete implementation, not just the concept.