Recently, I migrated our project from Husky to Lefthook — and the difference was immediately noticeable.
🤔 Why Lefthook?
A few key reasons:
- ⚡ Written in Go → extremely fast execution
- 🔀 Parallel execution → run tasks concurrently instead of sequentially
- 🧩 Simple & powerful config → less boilerplate, easier to maintain
- 🧠 Smarter workflow control → flexible hook-level optimization
⸻
⏱️ Real impact (our case)
Before (Husky)
- Pre-commit runs everything:
- lint
- type-check
- unit tests
- ⏳ ~17 seconds per commit
After (Lefthook)
- pre-commit:
- only lint + prettier on staged files
- pre-push:
- type-check + unit tests
👉 Result:
- ⏱️ ~2s faster per commit (~10% improvement)
- 💡 Much smoother dev experience (less waiting, more flow)
⸻
🧠 Key takeaway
Don’t overload your pre-commit hook.
Split responsibilities:
- ✅ Fast checks → pre-commit
- 🔍 Heavy validation → pre-push / CI
📦 Example Lefthook config (simplified)
---
# https://lefthook.dev/configuration/glob_matcher/
glob_matcher: doublestar
# https://lefthook.dev/configuration/assert_lefthook_installed/
assert_lefthook_installed: true
pre-commit:
parallel: true
jobs:
- name: lint
glob: '**/*.{js,jsx,ts,tsx}'
run: pnpm exec eslint --quiet --fix {staged_files}
# https://lefthook.dev/examples/stage_fixed
stage_fixed: true
- name: prettier
glob: '**/*.{js,jsx,ts,tsx,json,md,yml,yaml}'
run: pnpm exec prettier --write --ignore-unknown -- {staged_files}
stage_fixed: true
pre-push:
parallel: true
jobs:
- name: type-check
run: pnpm type-check
- name: test
run: pnpm test
💬 Final thought
If your commits feel slow and interrupt your flow, it’s probably not your code — it’s your hooks.
Lefthook gives you performance + control without complexity.
⸻
Top comments (0)