Pre-commit Hooks for Code Quality
A Husky + lint-staged setup that runs linting, formatting, and type checking on every commit — catching issues before they reach CI.
Description
An automated pre-commit hook setup using Husky and lint-staged that runs linters, formatters, and type checkers on staged files. Only processes changed files for fast feedback.
Features
- Husky v9 for Git hook management
- lint-staged to run tools only on staged files
- ESLint for linting, Prettier for formatting
- TypeScript type checking on commit
- Conventional commit message validation
Setup Script
#!/bin/bash
# setup-hooks.sh — Initialize pre-commit hooks for a project
set -euo pipefail
echo "📦 Installing dependencies..."
npm install -D husky lint-staged @commitlint/cli @commitlint/config-conventional
echo "🐶 Initializing Husky..."
npx husky init
echo "📝 Creating pre-commit hook..."
cat > .husky/pre-commit << 'EOF'
npx lint-staged
EOF
echo "📝 Creating commit-msg hook..."
cat > .husky/commit-msg << 'EOF'
npx --no -- commitlint --edit "$1"
EOF
echo "✅ Hooks installed!"
echo " - pre-commit: lint-staged (ESLint + Prettier + types)"
echo " - commit-msg: conventional commits"
lint-staged Configuration
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
],
"*.{js,jsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
],
"*.{json,md,yml,yaml,css}": [
"prettier --write"
]
}
}
Commitlint Configuration
// commitlint.config.js
export default {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor',
'perf', 'test', 'build', 'ci', 'chore', 'revert',
]],
'subject-max-length': [2, 'always', 72],
'body-max-line-length': [1, 'always', 100],
},
};
Type Check Script
Add a pre-commit type check that only validates changed files:
#!/bin/bash
# .husky/pre-commit-typecheck.sh
# Get staged TypeScript files
STAGED_TS=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx)$' || true)
if [ -n "$STAGED_TS" ]; then
echo "🔍 Type checking staged files..."
npx tsc --noEmit --pretty
echo "✅ Types OK"
fi
Usage
# Install hooks
bash setup-hooks.sh
# Hooks run automatically on commit
git add .
git commit -m "feat: add user profile page"
# → lint-staged runs ESLint + Prettier on staged files
# → commitlint validates the message format
# Skip hooks (emergency only)
git commit --no-verify -m "hotfix: emergency patch"