DEV Community

137Foundry
137Foundry

Posted on

How to Set Up Pre-Commit Hooks for Teams Using AI Coding Assistants

AI coding assistants write syntactically correct code most of the time. They are considerably less reliable about respecting your project's import conventions, naming patterns, or type contracts. That gap is exactly what pre-commit hooks close.

This is a step-by-step guide to setting up pre-commit hooks for a team that uses AI coding tools. The setup applies to both Python and JavaScript/TypeScript projects. The concepts transfer to any language with a linter.

terminal window showing pre-commit hook running
Photo by Nemuel Sereti on Pexels

Why Pre-Commit Hooks Matter More With AI Tools

Without AI tools, style and convention drift usually happens slowly. One developer's personal habits creep in here and there, and code review catches most of it.

With AI tools, convention drift can happen fast. A developer working with GitHub Copilot or Cursor accepts 20 suggestions in an afternoon. Each suggestion is syntactically valid and logically plausible. But several of them use import paths that differ from your project's convention, name variables using a pattern the tool learned from a different codebase, or skip error handling that your team has agreed is mandatory.

By the time this reaches code review, the reviewer has to evaluate each deviation individually: is this intentional, or is it AI drift? The answer is usually "AI drift," but confirming that takes time. Pre-commit hooks catch the detectable violations automatically, so reviewers can focus on logic rather than style.

Step 1: Install the pre-commit Framework

The pre-commit framework is the standard tool for managing Git hooks. Install it with pip:

pip install pre-commit
Enter fullscreen mode Exit fullscreen mode

Or if you are managing Python tool dependencies with a dev dependencies group:

pip install --group dev pre-commit
Enter fullscreen mode Exit fullscreen mode

For teams on Node.js projects that prefer keeping everything in package.json, Husky is the equivalent. The configuration differs slightly, but the concept is the same: a hook runs before each commit and can block the commit if checks fail.

Add a .pre-commit-config.yaml file to the root of your repository. This file defines which hooks run and in what order.

Step 2: Configure Your Linter

For Python projects, add ruff as your primary lint and format check:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.4
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format
Enter fullscreen mode Exit fullscreen mode

Ruff is a fast Python linter that combines flake8, isort, and several other tools. For teams on older setups that prefer flake8 directly:

repos:
  - repo: https://github.com/PyCQA/flake8
    rev: 7.0.0
    hooks:
      - id: flake8
Enter fullscreen mode Exit fullscreen mode

For TypeScript/JavaScript projects, add ESLint:

repos:
  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v8.57.0
    hooks:
      - id: eslint
        files: \.[jt]sx?$
        types: [file]
Enter fullscreen mode Exit fullscreen mode

ESLint is the standard linter for JavaScript and TypeScript. Configure your .eslintrc as you normally would; the pre-commit hook runs it on staged files only, which keeps it fast.

Step 3: Add a Type Checker

Type checking is where AI tools tend to introduce the most subtle errors. A suggestion might use a method that doesn't exist on the type the tool inferred, or assume a nullable field is always present.

For Python projects, add mypy:

  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.10.0
    hooks:
      - id: mypy
        additional_dependencies: [types-requests, types-PyYAML]
Enter fullscreen mode Exit fullscreen mode

Adjust additional_dependencies to include the type stubs your project uses. mypy will catch cases where AI-generated code calls methods that do not exist on a type, passes arguments in the wrong order, or skips null checks.

For TypeScript projects, tsc handles type checking as part of the normal build. You can add it to pre-commit directly:

  - repo: local
    hooks:
      - id: tsc
        name: TypeScript type check
        language: node
        entry: npx tsc --noEmit
        types: [ts, tsx]
        pass_filenames: false
Enter fullscreen mode Exit fullscreen mode

TypeScript type errors from AI suggestions are common, especially when the tool generates code that interfaces with an existing typed module it did not see in full context.

Step 4: Install the Hooks

Once .pre-commit-config.yaml is configured, install the hooks into your local Git repository:

pre-commit install
Enter fullscreen mode Exit fullscreen mode

This adds a .git/hooks/pre-commit script that runs automatically before each commit. Every developer on the team needs to run pre-commit install once after cloning the repository. Add this to your contributing guide or your repository's Makefile setup target.

To verify the hooks run correctly against the current staged files:

pre-commit run --all-files
Enter fullscreen mode Exit fullscreen mode

This runs all configured hooks against every file in the repository. Expect some failures on first run in an existing codebase; fix them or add exceptions as needed before requiring the hooks in CI.

Step 5: Add the Check to CI

Pre-commit hooks run locally by default. If a developer bypasses them (intentionally or by committing directly without the hooks installed), violations can still reach your pull request.

Adding a CI check ensures the hooks run on every PR regardless of local setup. In GitHub Actions, add a job like this:

name: pre-commit
on: [pull_request]
jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - uses: pre-commit/action@v3.0.1
Enter fullscreen mode Exit fullscreen mode

This uses the official pre-commit/action to run the same hooks your developers run locally. Failed checks block the PR. Passed checks mean the linting and type checks have been verified end to end.

Keeping Hooks Fast

One failure mode with pre-commit setups is hooks that run too slowly. If committing takes 20-30 seconds every time, developers start using git commit --no-verify to skip the hooks. That defeats the purpose entirely.

Configure hooks to check only staged files where possible (most hooks do this by default). Avoid running expensive operations like full test suites in pre-commit. Those belong in CI. Pre-commit should run in under 5 seconds on a typical commit, which means linting and type checking staged files only.

If a specific hook is slow, check whether it supports a files or types filter to narrow its scope. Running ESLint on only .ts and .tsx files is faster than running it on every file in the repository.

For a broader picture of how pre-commit hooks fit into a full Git workflow for AI-assisted teams, see How to Integrate AI Coding Tools Into Your Git Workflow Without Losing Control. The AI automation agency 137Foundry helps engineering teams set this up alongside the rest of their AI tooling integration.

developer setting up automation on a terminal
Photo by cottonbro studio on Pexels

Summary

Pre-commit hooks are a practical, low-overhead guardrail for AI-assisted codebases. The setup takes an hour and runs silently after that. The configuration described here covers the most common failure modes in AI tool output: style drift, import convention violations, and type errors.

The investment is a .pre-commit-config.yaml, a pre-commit install in your setup instructions, and a CI job. The return is a class of review comments that stops appearing because the automated check catches them first.

One last note on team adoption: pre-commit works best when it is part of your repository setup documentation rather than something developers discover on their own. Add it to your CONTRIBUTING.md, include it in your onboarding checklist, and add a make setup target that runs pre-commit install automatically. When every developer has the hooks installed from day one, the coverage is consistent and the review benefits are immediate for the entire team rather than just the developers who remembered to run the install command.

Top comments (0)