---
title: "Pre-commit checks for code written by AI agents · Cork"
description: "Pre-commit checks for AI-written code: git hooks, the pre-commit framework, secret scanning, and agent hooks in Claude Code, Codex and Cursor."
canonical: "https://corkcli.com/blog/pre-commit-checks-ai-generated-code"
last_updated: "2026-10-03"
published: "2026-10-03"
author: "Kevin Vera"
---

# Pre-commit checks for code written by AI agents

Pre-commit checks for AI-written code: git hooks, the pre-commit framework, secret scanning, and agent hooks in Claude Code, Codex and Cursor.

By Kevin Vera · October 3, 2026 · [Guides](https://corkcli.com/blog/c/guides) · 7 min read

The best pre-commit checks for code written by AI agents are the same ones you would run for humans (formatting, linting, type checks, fast tests, secret scanning), wired in at two points: a git `pre-commit` hook so nothing bad is committed, and an agent hook so the agent sees the failure right after the edit and fixes it itself. Agents commit often and can bypass a hook with `--no-verify`, so back both up with required status checks in CI. Checks catch broken code; they do not catch two agents quietly undoing each other's work, which needs coordination.

## Why AI-written code needs checks earlier, not just more of them

Agents are fast and confident. They produce more diffs per hour than a person, and a failing check found in CI an hour later means a new prompt, a reloaded context and another round of edits. The cheapest moment to catch a problem is right after the edit, while the agent still has the file in context. The second cheapest is at commit time. CI is the backstop.

There is also a parallel-agent problem. When two agents work on the same repo, each one's checks pass against its own view of the code. A rename by one agent can break the other's call site, and neither notices until the branches meet.

## Step 1: a git pre-commit hook

Git runs `.git/hooks/pre-commit` before each commit. From the git docs: "Exiting with a non-zero status from this script causes the `git commit` command to abort before creating a commit." It "can be bypassed with the `--no-verify` option."

Two details matter for teams:

- Hooks live in `$GIT_DIR/hooks` by default and are not copied when someone clones the repo. To share them, commit a folder such as `.githooks/` and point git at it with `git config core.hooksPath .githooks`.
- Keep the hook fast. If it takes a minute, people and agents will learn to skip it.

A minimal shared hook:

```bash
#!/bin/sh
# .githooks/pre-commit
set -e
npm run lint
npm run typecheck
npm test -- --onlyChanged
```

## Step 2: the pre-commit framework

For multi-language repos, the [pre-commit](https://pre-commit.com/) framework manages hooks from a single config file. Install it, add `.pre-commit-config.yaml`, and run `pre-commit install`:

```bash
pip install pre-commit
pre-commit install
pre-commit run --all-files
```

A config that suits agent-written code, with whitespace and YAML fixes, a formatter, and secret scanning:

```yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.3.0
    hooks:
      - id: check-yaml
      - id: end-of-file-fixer
      - id: trailing-whitespace
  - repo: https://github.com/psf/black
    rev: 22.10.0
    hooks:
      - id: black
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.24.2
    hooks:
      - id: gitleaks
```

Run `pre-commit autoupdate` to move each hook to its latest tagged version. The `gitleaks` hook runs `gitleaks git --pre-commit --redact --staged --verbose`, so it only scans what is about to be committed. Secret scanning deserves a place on every agent repo: an agent that reads a `.env` file to debug a connection can paste a key into a test fixture without meaning to.

## Step 3: run checks inside the agent, right after each edit

Agent hooks let a check run before the commit, at the moment the agent writes a file, and feed the result back to the agent.

**Claude Code.** A `PostToolUse` hook with matcher `Edit|Write` runs after each file edit. Per the hooks reference, exit code 2 from a `PostToolUse` hook "shows stderr to Claude; the tool already ran," so the agent sees the lint error and fixes it. A `PreToolUse` hook with exit code 2 blocks the tool call entirely. In `.claude/settings.json` (committed, shared with the team):

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/lint-changed.sh" }
        ]
      }
    ]
  }
}
```

**Codex.** Codex reads hooks from `~/.codex/hooks.json` or `<repo>/.codex/hooks.json` (or `[hooks]` tables in `config.toml`). Hooks are on by default. For file edits through `apply_patch`, the matcher can be `apply_patch`, `Edit` or `Write`. Project-local hooks load only when the project's `.codex/` layer is trusted, and Codex asks you to review a hook before it runs.

**Cursor.** Cursor reads `.cursor/hooks.json` in the project or `~/.cursor/hooks.json`. An `afterFileEdit` hook can run a formatter after each edit, and a `before...` hook can block by exiting with code 2 or returning `"permission": "deny"`:

```json
{
  "version": 1,
  "hooks": {
    "afterFileEdit": [{ "command": ".cursor/hooks/format.sh" }]
  }
}
```

Keep these hooks scoped to the changed file. Running the full suite after every edit slows the agent down for little gain.

## Step 4: make CI the backstop

Agents can and do pass `--no-verify`, and a local hook only runs on machines where it is installed. In GitHub, branch protection can require status checks: "Required status checks must have a `successful`, `skipped`, or `neutral` status" before changes land, and the strict setting means "the branch must be up to date with the base branch before merging." That last setting matters for parallel agents, because it forces each branch to be tested against everything that landed before it. A merge queue automates that ordering on a busy branch.

Also block `--no-verify` at the agent level if your team wants hooks to be mandatory: a Claude Code `PreToolUse` hook on `Bash` can refuse any `git commit` command that contains it.

## What checks do not catch

Lint, types and tests tell you the code is valid. They do not tell you:

- that another agent renamed the function you just called, in a branch that has not landed yet;
- that your agent and a teammate's agent are editing the same function right now, and the second save will overwrite the first;
- that your agent re-solved a problem another agent already solved an hour ago.

Those are coordination problems, and they need a signal that crosses sessions.

## How Cork helps

Cork is the [coordination layer](https://corkcli.com/blog/coordination-layer-ai-coding-agents) for multiplayer coding agents: it keeps Claude Code, Codex and Cursor agents, on one machine or across a team's machines, from overwriting each other on one codebase, and hands each agent what the others already learned.

Next to your pre-commit checks, Cork adds the cross-agent signals:

- **[Semantic lint](https://corkcli.com/blog/semantic-lint).** A teammate's rename or signature change becomes a lint rule your agents are checked against, so a stale call site is caught.
- **Live awareness and the [write gate](https://corkcli.com/blog/write-gate).** When another agent changes code yours depends on, your agent hears it on its next step, and an edit against code another agent is changing right now is held until your agent has their version.
- **Landing.** `git push` becomes one step that rebases onto teammates' commits, reruns the tests and pushes, so the tests run against what is actually on the branch.

Cork runs through hooks in Claude Code, Codex and Cursor with no extra model calls, and it does not replace your formatter, linter, secret scanner or CI. Install it for every repo on the machine with:

```bash
curl -fsSL https://corkcli.com/install.sh | sh
```

## Frequently asked questions

### Can an AI agent skip pre-commit hooks?

Yes. `git commit --no-verify` bypasses the `pre-commit` hook. Back hooks up with required status checks in CI, and if you want, an agent-level hook that refuses commit commands containing `--no-verify`.

### Should checks run in a git hook or an agent hook?

Both. An agent hook (Claude Code `PostToolUse`, Codex `PostToolUse`, Cursor `afterFileEdit`) gives the agent feedback right after the edit, while the file is still in its context. The git hook guards the commit, and CI guards the branch.

### How do I share git hooks with my team?

Git does not copy hooks on clone. Commit them to a folder like `.githooks/` and run `git config core.hooksPath .githooks`, or use the pre-commit framework with a committed `.pre-commit-config.yaml` and have each person run `pre-commit install`.

### Do pre-commit checks stop agents from overwriting each other?

No. They validate each commit on its own. Two agents can both pass every check and still undo each other's work. That needs coordination between agents, such as a write gate or rebasing and retesting before push.

## Sources

- <https://git-scm.com/docs/githooks>
- <https://pre-commit.com/>
- <https://github.com/gitleaks/gitleaks>
- <https://code.claude.com/docs/en/hooks>
- <https://learn.chatgpt.com/docs/hooks>
- <https://cursor.com/docs/agent/hooks>
- <https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches>

## Related reading

- [How to give AI coding agents context about recent changes](https://corkcli.com/blog/give-ai-coding-agents-context-recent-changes): Give Claude Code, Codex and Cursor context about recent changes: good commit messages, SessionStart and prompt hooks that inject git history, and live updates.
- [MCP servers for coordinating coding agents: what they are and how to use one](https://corkcli.com/blog/mcp-servers-coordinating-coding-agents): What an MCP server for coordinating coding agents does, how it differs from hooks, and how to connect one to Claude Code, Codex, Cursor and Gemini CLI.
- [How to see what all your AI coding agents are doing at once](https://corkcli.com/blog/see-what-all-ai-coding-agents-are-doing): See every AI coding agent's status in one place: Claude Code agent view, Cursor's Agents Window, git worktree checks, OpenTelemetry, and a team-wide view.
- [How to stop an agent editing a file someone else is changing](https://corkcli.com/blog/stop-agent-editing-file-someone-else-is-changing): Block an AI coding agent from editing a file another session is changing: a tested Claude Code PreToolUse lock hook, Cursor and Codex equivalents, and limits.

[All articles](https://corkcli.com/blog.md) · [Cork in Markdown](https://corkcli.com/index.md) · [llms.txt](https://corkcli.com/llms.txt)

This page in HTML: https://corkcli.com/blog/pre-commit-checks-ai-generated-code
