Key Takeaways
- 01 prek is a Rust-based drop-in replacement for pre-commit
- 02 Speed improvement: 47s → 8s for pre-commit hooks (5-6x faster)
- 03 No configuration changes needed - existing .pre-commit-config.yaml files work
- 04 Runs hooks in parallel, shares toolchains, uses uv for Python deps
- 05 Adopted by CPython, Apache Airflow, FastAPI, Ruff, and more
I Waited Six Months Before Switching From pre-commit. That Was a Mistake.
Last Tuesday, at 2:37 PM, I hit git commit on a medium-sized repo and watched in silence as my pre-commit hooks churned for 47 seconds. Forty-seven seconds! For a commit that changed three files.
I’d been living with this for months. “It’s just the price of quality code,” I told myself. “Better slow than broken.”
Then I saw a Hacker News post about prek — a Rust-based drop-in replacement for pre-commit. The claims were bold: 3-5x faster, no Python dependency, single binary. I was skeptical. I mean, pre-commit works fine, right?
Wrong. So wrong.
After swapping to prek that evening, my pre-commit hook time dropped from 47 seconds to 8 seconds. I’m not making that up. Eight seconds. And that’s with zero configuration changes.
After swapping to prek that evening, my pre-commit hook time dropped from 47 seconds to 8 seconds. I’m not making that up. Eight seconds. And that’s with zero configuration changes.
Here’s why I’m never going back, and why you should probably switch too.
What Is prek, Anyway?
prek (pronounced like “preck”) is a complete re-implementation of the pre-commit framework, but built in Rust instead of Python. It’s designed to be a drop-in replacement — meaning your existing .pre-commit-config.yaml files work without modification.
The project is pretty new (released in late 2025), but it’s already been adopted by some heavy hitters: CPython (Python itself!), Apache Airflow, FastAPI, Ruff, and dozens more.
When Python language itself switches your tool, you know it’s good. CPython, Apache Airflow, FastAPI, Ruff, and dozens more have already adopted prek.
Why Speed Actually Matters (Beyond Annoyance)
Here’s the thing about slow pre-commit hooks: they don’t just waste time — they break flow.
When I’m in the zone, making rapid commits and iterating, waiting 40+ seconds between commits is a flow-killer. It’s like having to wait for a red light every two blocks while driving. You can still get where you’re going, but it’s frustrating and you lose momentum.
But there’s a more practical issue: the slower your hooks are, the more likely you are to skip them when you’re in a rush. I’ve definitely done git commit --no-verify more times than I’d like to admit. When your safety net is annoying, you don’t use it.
With prek? The hooks are so fast I don’t even think about them. It’s a safety net that doesn’t feel like punishment.
With prek? The hooks are so fast I don’t even think about them. It’s a safety net that doesn’t feel like punishment.
The Rust Advantage
Why is prek faster? Well, Rust, obviously — but that’s not the whole story.
Parallel execution
prek runs hooks in parallel when they have independent dependencies. pre-commit runs them sequentially.
Shared toolchains
Every hook in pre-commit gets its own isolated environment. prek shares toolchains between hooks, reducing duplication and installation time.
Native implementations
prek has built-in Rust versions of common hooks (like trailing whitespace detection, file size checks) that run significantly faster than their Python equivalents.
uv integration
prek uses Astral’s uv for Python dependency management, which is ridiculously fast. If you haven’t used uv, imagine pip but 10-100x faster.
Rust for performance, parallel execution, shared toolchains, native implementations, and uv integration — that’s why prek is so fast.
My Migration Story
I was nervous about switching. My pre-commit config was months in the making, with custom hooks, language-specific environments, and all the complexity you’d expect in a serious project.
Here’s what I did:
# Install prek (I used uv because it's already in my workflow)
uv tool install prek
# Verify it works with my existing config
prek run --all-files
That was it. Everything just worked. Same config, same hooks, just way faster.
Side note: If you use Python hooks and don’t have Python installed, prek will actually install the right Python version for you automatically. No more “which python is this using?” anxiety.
Drop-in replacement means your existing .pre-commit-config.yaml files work without modification. No config changes needed.
Features I Didn’t Know I Needed
Once I started using prek, I discovered some quality-of-life improvements that pre-commit just doesn’t have:
Directory-specific runs
prek run --directory tests/ runs hooks only on files in a specific directory. This is huge for targeted testing.
Last commit focus
prek run --last-commit runs hooks on files changed in your last commit. Perfect for when you realize you made a typo in that commit you just pushed.
Workspace mode
If you’re working in a monorepo, prek supports .pre-commit-config.yaml files in each subdirectory. Each workspace gets its own hooks but shares toolchains. pre-commit requires you to configure everything at the root.
Built-in hooks
No need to define a hook for trailing whitespace or JSON validity — just use repo: builtin and you’re done. These are offline, zero-setup hooks that don’t even need to clone external repos.
Shell completions
prek provides shell completions for hook names, so you can type prek run <TAB> and see all your hooks. I can’t believe pre-commit doesn’t have this.
Directory-specific runs, last commit focus, workspace mode, built-in hooks, and shell completions — quality-of-life improvements I didn’t know I needed.
The One Catch (Because Nothing’s Perfect)
prek is new, which means it doesn’t have 100% language parity with pre-commit yet. At the time I’m writing this, some hook languages aren’t fully supported.
prek is new, so not all hook languages are fully supported yet. Check the docs for your specific needs before switching.
The prek team maintains a language support page, and they’re moving fast. In my case, I was using Python, Node.js, and a few simple shell hooks — all of which worked perfectly. Check the docs for your specific needs before switching.
Also, if you’ve written custom hooks that rely on pre-commit’s Python API, those won’t work directly. But most people use standard hooks, so this shouldn’t be an issue.
When Should You Stick With pre-commit?
Honestly? The only reasons I can think of are:
- You’re using an unsupported language (check docs)
- You have deeply custom hooks that depend on pre-commit’s internals
- You’re in an environment where you absolutely cannot install new binaries (unlikely, since prek can run from pre-built binaries via npm or other package managers)
You’re using an unsupported language, have deeply custom hooks that depend on pre-commit’s internals, or absolutely cannot install new binaries. Otherwise? Make the switch.
Otherwise? Make the switch.
How to Switch (In 5 Minutes)
If you’re already using pre-commit, it’s literally this:
# Install prek
curl --proto '=https' --tlsv1.2 -sSf https://github.com/j178/prek/releases/download/v0.3.1/prek-installer.sh | sh
# Or via your preferred package manager
uv tool install prek # what I recommend
brew install prek # macOS
pipx install prek # also works!
That’s it. Your .pre-commit-config.yaml doesn’t change. Your hooks don’t change. Git doesn’t change. Just update your pre-commit hook script to call prek instead of pre-commit.
If you want to be extra safe, run prek run --all-files first to make sure everything passes, then update your git hooks.
What This Means for the Future
I think prek is part of a bigger trend: Python developer tools being rewritten in Rust. We’ve seen it with Ruff (replacing flake8, pylint, isort, black, and more), and now prek is doing it for git hooks.
Why Rust? Because when your tool is something developers run hundreds of times a day, every millisecond matters. Rust’s performance, combined with zero-copy data structures and fearless concurrency, makes it ideal for this use case.
I wouldn’t be surprised to see more Python tooling follow this pattern. Not because Python is bad — it’s great for many things — but because developer tools have different requirements than application code.
Python developer tools being rewritten in Rust. Ruff, prek, and more. When your tool runs hundreds of times a day, every millisecond matters.
My Verdict
After a week of using prek, I can’t imagine going back. The speed difference is transformative, and quality-of-life improvements are the kind of things that make you wonder how you lived without them.
If you’re using pre-commit and frustrated by speed (or lack thereof), give prek a shot. The migration is painless, performance gains are real, and honestly? It feels like the future.
Your future self, who doesn’t spend 40+ seconds waiting for git hooks, will thank you.
Want to try it?
- prek GitHub: https://github.com/j178/prek
- Official docs: https://prek.j178.dev
- Language support: https://prek.j178.dev/languages/