3 FPS
Nathan Atherton
Back to Blog
EngineeringAI

11 Git Hooks That Make AI Agents Safe to Run Unsupervised

Nathan Athertonยท Staff Software EngineerMarch 8, 20269 min read

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:

  1. block-env-files - non-negotiable
  2. secrets-scanner - non-negotiable
  3. post-format - keeps diffs clean
  4. block-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.