Pre-commit hooks catch problems before they reach CI: bad formatting, broken builds, leaked secrets. All of it, in under a second, before you’ve even pushed.

I recently checked across my team. Ninety-five percent had no pre-commit hooks set up. Not because anyone disagreed with the idea — few made it a five-minute priority, so it stayed undone.

Here’s the five minutes.

But wait, I’m not sure I care enough Link to heading

Pipelines are quality gate by nature. But a lint failure caught in CI costs you a push, a wait, and a context switch back to code you thought was finished. The same check as a pre-commit hook costs a fraction of a second, and will likely fix the problem before you return to the keyboard.

That gap matters more now than it used to. AI-assisted coding doesn’t just speed up writing code, it speeds up committing code — more changes, same review bandwidth. Pre-commit hooks are the reviewer that never gets tired, never skips the boring checks, and catches things before a human ever has to.

They’re also the best answer I’ve found to a question every AI-assisted team runs into: how do you make “done” something a machine can check? A .pre-commit-config.yaml is exactly that. When an agent’s change fails a hook, it gets specific feedback it can act on without you in the loop.

The tool I set these up with is prek: a Rust rewrite of the original Python pre-commit framework, meaningfully faster, and a single binary with nothing else to install. It reads the exact same .pre-commit-config.yaml format, so every hook below works unchanged whichever one you run.

And there’s one hook worth adopting on its own merits: secret scanning. Committing a credential has never been easier, or more costly — by some estimates, well over half of cloud breaches trace back to a leaked secret. It’s the one check on this list I never skip.

Set it up Link to heading

1. Install the framework (once per machine):

brew install prek
# or
pip install prek

2. Wire it into a repo (once per repo):

prek install

This writes a small wrapper into .git/hooks/pre-commit. From now on, every commit runs your configured checks automatically.

3. Add a config. Create .pre-commit-config.yaml at the repo root, paste this in, and commit it:

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-merge-conflict

  - repo: local
    hooks:
      - id: betterleaks
        name: betterleaks secret scan
        entry: bash -c 'GL=$(command -v betterleaks) || { echo "betterleaks not found, skipping"; exit 0; }; "$GL" git --redact=80 --no-banner --pre-commit --staged'
        language: system
        pass_filenames: false

That’s it. It’s committed to the repo, so it’s not just configured on your machine — anyone who clones the repo and runs prek install gets the exact same checks.

Already have the original pre-commit set up somewhere? Swapping over doesn’t touch your config: install prek, run prek install again in the repo, and you’re done.

What you just got Link to heading

HookCatches
trailing-whitespaceTrailing spaces on any line
end-of-file-fixerMissing newline at end of file
check-yamlMalformed YAML
check-merge-conflictUnresolved <<<<<< markers
betterleaksSecrets about to be committed

The first four are milliseconds of insurance against embarrassing review comments. The last one is the important one — it scans only your staged changes, so it stays fast, and it fails safe: if the betterleaks binary isn’t installed on a machine, the hook skips with a message rather than blocking every commit for everyone. (Install it in CI too, so that fallback never becomes your actual safety net — see below.)

When a hook is in your way Link to heading

Skip one hook, for one commit, without turning it off for good:

SKIP=betterleaks git commit -m "chore: add draft post"

git commit --no-verify skips everything. Use it deliberately, not habitually — if --no-verify starts showing up often in your log, that’s a sign the hooks are too slow or too strict, not that the team’s undisciplined. Fix the hook.

Don’t forget CI Link to heading

Hooks only protect commits made on a machine where someone ran prek install. A fresh clone that skips that step commits with no checks at all — so CI runs the same suite as a backstop, on every pull request. prek’s maintainers publish an official action that installs it and runs the full suite in two lines:

# .github/workflows/quality.yml
name: Quality
on: [pull_request]

jobs:
  prek:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: j178/prek-action@v3

Install betterleaks as a step before this job runs, and the graceful local fallback stops applying — a missing binary in CI should fail the build, not quietly skip the scan.

Further reading Link to heading

  • prek — source, docs, and the full hook registry
  • pre-commit.com — the original framework prek is compatible with; useful for the config format reference
  • betterleaks.com — the secret scanner used above