Claude Code Hooks: Automate Pre-Commit Checks, Tests & Linting (2026 Guide)

TutorialsBy Ivern AI Team12 min read

Claude Code Hooks: Automate Tests, Linting & Git Workflows (2026 Guide)

Short answer: Claude Code hooks let you run custom scripts before or after Claude executes actions -- automatically running tests before commits, enforcing linting rules, blocking secrets from being pushed, and triggering CI/CD pipelines. You configure hooks in CLAUDE.md or settings.json using shell commands that execute at specific lifecycle points. Combined with Claude Code's autonomous mode, hooks create a fully automated development pipeline: code, test, lint, commit, deploy.

Related: Claude Code Beginner Guide · Claude Code Best Practices (15 Tips) · CLAUDE.md Guide (12 Examples) · Claude Code vs Cursor · Claude Code vs GitHub Copilot · Claude Code vs Windsurf · Claude Code Subagents Guide · Claude Code Workflow Automation · MCP Servers Guide · Best Claude Code Alternatives · Best Free AI Coding Assistants · All Tutorials

What Are Claude Code Hooks?

Claude Code hooks are user-defined shell commands that run automatically at specific points in Claude Code's execution lifecycle. Think of them like git hooks (pre-commit, pre-push) but for AI-assisted development.

Hooks let you:

  • Run tests automatically before Claude commits changes
  • Enforce code style with linters (ESLint, Prettier, Ruff)
  • Block secrets from being committed (API keys, passwords)
  • Generate documentation after code changes
  • Trigger CI/CD pipelines on successful commits
  • Log all changes for audit trails
  • Notify Slack/Discord on task completion

How Hooks Work

Claude Code supports several hook lifecycle points:

Scroll to see full table

HookWhen It RunsUse Case
pre-editBefore Claude edits a fileValidate file permissions, check branch
post-editAfter Claude edits a fileAuto-format, lint fix
pre-commitBefore Claude runs git commitRun tests, block secrets
post-commitAfter Claude runs git commitTrigger CI/CD, notify team
pre-pushBefore Claude runs git pushFinal checks, code review
on-startWhen Claude Code startsEnvironment setup, load configs
on-task-completeAfter Claude finishes a taskCleanup, logging, notifications

Configuring Hooks

Hooks are configured in settings.json or CLAUDE.md:

Method 1: settings.json

{
  "hooks": {
    "pre-commit": [
      {
        "command": "npm test",
        "timeout": 60000,
        "blocking": true
      },
      {
        "command": "npm run lint",
        "timeout": 30000,
        "blocking": true
      }
    ],
    "post-commit": [
      {
        "command": "echo 'Commit successful at $(date)' >> .claude/commit-log.txt",
        "blocking": false
      }
    ]
  }
}

Method 2: CLAUDE.md

## Hooks

Before committing any changes:
1. Run `npm test` — all tests must pass
2. Run `npm run lint` — no linting errors
3. Run `npm run typecheck` — no TypeScript errors
4. Check for secrets: `! grep -r "sk-ant-" src/`
5. Check for console.log: `! grep -r "console.log" src/`

After committing:
1. Run `git log --oneline -1` to confirm
2. Log the change to CHANGELOG.md

15 Practical Hook Examples

1. Auto-Run Tests Before Commit

{
  "hooks": {
    "pre-commit": [
      {
        "command": "npm test -- --coverage",
        "timeout": 120000,
        "blocking": true
      }
    ]
  }
}

This ensures Claude Code never commits broken code. If tests fail, Claude sees the failure and automatically fixes the issue before retrying.

2. Enforce ESLint + Prettier

{
  "hooks": {
    "post-edit": [
      {
        "command": "npx eslint --fix $FILE && npx prettier --write $FILE",
        "timeout": 10000,
        "blocking": false
      }
    ]
  }
}

Every file Claude edits gets auto-formatted immediately. No more style debates.

3. Block Secrets From Being Committed

{
  "hooks": {
    "pre-commit": [
      {
        "command": "! grep -rE '(sk-ant-|sk-proj-|AKIA|ghp_)' src/ && echo 'No secrets found'",
        "timeout": 5000,
        "blocking": true
      }
    ]
  }
}

Prevents Claude from accidentally committing API keys or tokens. Critical for BYOK workflows.

4. Python: Auto-Format with Black + Ruff

{
  "hooks": {
    "post-edit": [
      {
        "command": "black $FILE && ruff check --fix $FILE",
        "timeout": 10000,
        "blocking": false
      }
    ]
  }
}

5. TypeScript Type Checking

Get AI agent tips in your inbox

Multi-agent workflows, product updates, and tips. No spam.

{
  "hooks": {
    "pre-commit": [
      {
        "command": "npx tsc --noEmit",
        "timeout": 60000,
        "blocking": true
      }
    ]
  }
}

Ensures type safety before any commit lands.

6. Auto-Generate Documentation

{
  "hooks": {
    "post-commit": [
      {
        "command": "npm run docs:generate && git add docs/ && git commit --amend --no-edit",
        "timeout": 30000,
        "blocking": false
      }
    ]
  }
}

7. Notify Slack on Task Completion

{
  "hooks": {
    "on-task-complete": [
      {
        "command": "curl -X POST $SLACK_WEBHOOK -H 'Content-Type: application/json' -d '{\"text\": \"✅ Claude Code completed task in ' + $(basename $PWD) + '\"}'",
        "timeout": 10000,
        "blocking": false
      }
    ]
  }
}

8. Database Migration Check

{
  "hooks": {
    "pre-commit": [
      {
        "command": "npx prisma migrate status --schema=prisma/schema.prisma",
        "timeout": 30000,
        "blocking": true
      }
    ]
  }
}

9. Bundle Size Check

{
  "hooks": {
    "pre-push": [
      {
        "command": "npm run build && SIZE=$(stat -c%s .next/static/chunks/main.js) && [ $SIZE -lt 250000 ] && echo 'Bundle OK' || (echo 'Bundle too large!' && exit 1)",
        "timeout": 120000,
        "blocking": true
      }
    ]
  }
}

10. Go: Run gofmt + go vet

{
  "hooks": {
    "post-edit": [
      {
        "command": "gofmt -w $FILE && go vet ./...",
        "timeout": 30000,
        "blocking": false
      }
    ]
  }
}

11. Security Audit on Push

{
  "hooks": {
    "pre-push": [
      {
        "command": "npm audit --audit-level=high",
        "timeout": 30000,
        "blocking": true
      }
    ]
  }
}

12. Docker Build Verification

{
  "hooks": {
    "pre-push": [
      {
        "command": "docker build -t app-test . && docker run --rm app-test npm test",
        "timeout": 300000,
        "blocking": true
      }
    ]
  }
}

13. Changelog Auto-Update

{
  "hooks": {
    "post-commit": [
      {
        "command": "echo \"- $(git log -1 --pretty=%s) ($(date +%Y-%m-%d))\" >> CHANGELOG.md && git add CHANGELOG.md && git commit --amend --no-edit",
        "timeout": 5000,
        "blocking": false
      }
    ]
  }
}

14. Branch Protection

{
  "hooks": {
    "pre-edit": [
      {
        "command": "[ \"$(git branch --show-current)\" != \"main\" ] && echo 'Safe to edit' || (echo 'Never edit main directly!' && exit 1)",
        "timeout": 5000,
        "blocking": true
      }
    ]
  }
}

Prevents Claude from making changes on the main branch.

15. Multi-Agent Coordination Hook

{
  "hooks": {
    "on-task-complete": [
      {
        "command": "echo '{\"task\": \"' + $(git log -1 --pretty=%s) + '\", \"status\": \"done\", \"timestamp\": \"' + $(date -Iseconds) + '\"}' >> .claude/task-log.jsonl",
        "timeout": 5000,
        "blocking": false
      }
    ]
  }
}

Logs all completed tasks for multi-agent coordination. Useful when running Claude Code as part of an Ivern AI agent squad.

Best Practices for Claude Code Hooks

Do: Keep Hooks Fast

Set aggressive timeouts. Hooks that take more than 30 seconds slow down Claude's iteration loop. Use blocking: false for non-critical tasks.

Do: Use Blocking Hooks for Quality Gates

Tests, type checking, and security scans should be blocking: true. If they fail, Claude will see the error and fix it automatically.

Don't: Use Blocking Hooks for Notifications

Slack pings, changelog updates, and logging should be blocking: false. A failed notification shouldn't block your commit.

Do: Chain Hooks for Complete Automation

{
  "hooks": {
    "pre-commit": [
      { "command": "npm run lint", "timeout": 30000, "blocking": true },
      { "command": "npm run typecheck", "timeout": 60000, "blocking": true },
      { "command": "npm test", "timeout": 120000, "blocking": true }
    ]
  }
}

Don't: Forget About Edge Cases

Test your hooks manually before enabling them. A buggy hook can block Claude from committing valid work.

Hooks vs Git Hooks: What's Different?

Scroll to see full table

FeatureGit HooksClaude Code Hooks
TriggerManual git commandsAI-driven actions
ContextNo code awarenessFull codebase context
Auto-fixJust blocksClaude sees error and fixes it
Multi-fileSingle operationMulti-file coordinated work
TestingExternal test runnerClaude reads test output and debugs

The key difference: when a git hook fails, you fix the problem manually. When a Claude Code hook fails, Claude sees the error output and fixes the problem automatically. This creates a self-healing development loop.

Combining Hooks with MCP Servers

Hooks become even more powerful when combined with MCP (Model Context Protocol) servers. MCP servers give Claude access to external tools (databases, APIs, file systems), while hooks ensure quality at each step:

  1. MCP server gives Claude database access
  2. Claude writes a migration
  3. Pre-commit hook runs the migration in test mode
  4. Claude sees test results and adjusts
  5. Post-commit hook deploys to staging

This creates a fully autonomous development pipeline.

Frequently Asked Questions

Can hooks slow down Claude Code?

Yes. Set timeout values carefully. A 5-minute test suite hook will block Claude for 5 minutes on every commit. Consider running long tests with blocking: false and checking results separately.

Can I use Claude Code hooks in CI/CD?

Yes. Claude Code's headless mode (claude --headless) respects hook configurations. This lets you use the same hooks locally and in GitHub Actions.

Do hooks work with all programming languages?

Yes. Hooks are shell commands, so they work with any language. Just use the appropriate linting/testing tools for your stack.

How do hooks interact with Claude Code subagents?

Each subagent can have its own hooks. A coding subagent might have test hooks, while a review subagent might have lint hooks. See our Claude Code Subagents Guide for more.

Start Using Claude Code Hooks

Claude Code hooks transform AI-assisted development from "suggest and pray" to "code, test, fix, commit" -- all autonomous. Start with a simple pre-commit test hook and build up from there.

Ready to go deeper? Read our Claude Code Beginner Guide and Claude Code Best Practices.

Want to coordinate multiple Claude Code instances? Learn how with Ivern AI agent squads or Claude Code workflow automation.

Create AI-powered presentations for free

Generate AI-powered presentations in under 90 seconds. Built-in AI, no setup needed. 15 free tasks, no credit card required.

Start Free -- 15 Tasks Included

Ivern Slides -- Free to Start

Generate complete AI presentations in 60 seconds. 3-agent pipeline, free tier included.

No spam. Unsubscribe anytime.