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
| Hook | Catches |
|---|---|
trailing-whitespace | Trailing spaces on any line |
end-of-file-fixer | Missing newline at end of file |
check-yaml | Malformed YAML |
check-merge-conflict | Unresolved <<<<<< markers |
betterleaks | Secrets 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