| name | pre-commit-hooks |
| description | MANDATORY setup for all projects. Automated code quality enforcement before commits. Prevents bad code from entering repository. |
Pre-Commit Hooks
Core Principle
Automate quality gates - humans forget, machines don't.
When to Use This Skill
- Setting up new projects (MANDATORY)
- Onboarding team members
- Improving code quality
- Preventing bad commits
- Enforcing standards
The Iron Law
NO PROJECT WITHOUT PRE-COMMIT HOOKS.
Every repository MUST have automated quality checks before commits are allowed.
Why Pre-Commit Hooks Are Mandatory
Without hooks:
- ❌ Unformatted code enters repository
- ❌ Type errors slip through
- ❌ Tests broken by commits
- ❌ Secrets/credentials committed
- ❌ Linting errors ignored
With hooks:
- ✅ Automatic code formatting
- ✅ Type checking enforced
- ✅ Tests run before commit
- ✅ No secrets committed
- ✅ Consistent code quality
Authority: 95% of professional teams use pre-commit hooks. Not using them is unprofessional.
Setup by Language
JavaScript/TypeScript Projects
Install pre-commit framework:
npm install --save-dev husky lint-staged
npx husky install
npm set-script prepare "husky install"
Create .husky/pre-commit:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
Configure package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"npm run test:related --bail"
],
"*.{json,md,yml,yaml}": [
"prettier --write"
]
},
"scripts": {
"prepare": "husky install",
"test:related": "jest --bail --findRelatedTests"
}
}
Minimum hooks:
- ✅ ESLint (linting + auto-fix)
- ✅ Prettier (formatting)
- ✅ TypeScript check (tsc --noEmit)
- ✅ Jest (related tests)
- ✅ No secrets check
Python Projects
Install pre-commit:
pip install pre-commit
Create .pre-commit-config.yaml:
repos:
- repo: https://github.com/psf/black
rev: 23.12.1
hooks:
- id: black
language_version: python3.11
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.1.9
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [types-requests]
- repo: https://github.com/PyCQA/bandit
rev: 1.7.6
hooks:
- id: bandit
args: ["-c", "pyproject.toml"]
- repo: local
hooks:
- id: pytest
name: pytest
entry: pytest
language: system
pass_filenames: false
always_run: true
Install hooks:
pre-commit install
Minimum hooks:
- ✅ Black (formatting)
- ✅ isort (import sorting)
- ✅ Ruff (linting)
- ✅ mypy (type checking)
- ✅ pytest (tests)
- ✅ bandit (security)
PHP/Laravel Projects
Install pre-commit tools:
composer require --dev friendsofphp/php-cs-fixer phpstan/phpstan
Create .husky/pre-commit (using Husky):
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep '\.php$')
if [ -n "$FILES" ]; then
vendor/bin/php-cs-fixer fix $FILES --config=.php-cs-fixer.php
vendor/bin/phpstan analyse $FILES
vendor/bin/paratest --filter=$(echo $FILES | tr '\n' '|')
git add $FILES
fi
Or use PHP pre-commit library:
composer require --dev brainmaestro/composer-git-hooks
Configure in composer.json:
{
"extra": {
"hooks": {
"pre-commit": [
"vendor/bin/php-cs-fixer fix --dry-run --diff",
"vendor/bin/phpstan analyse",
"vendor/bin/paratest"
]
}
}
}
Minimum hooks:
- ✅ PHP CS Fixer (formatting)
- ✅ PHPStan (static analysis)
- ✅ Psalm (type checking)
- ✅ Paratest (tests)
- ✅ No secrets check
Universal Hooks (All Projects)
Add these to every project:
1. No Secrets Check
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.1
hooks:
- id: gitleaks
2. Trailing Whitespace
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-added-large-files
3. Commit Message Validation
. "$(dirname "$0")/_/husky.sh"
npx --no -- commitlint --edit "$1"
Install commitlint:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
Configure commitlint.config.js:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor',
'perf', 'test', 'build', 'ci', 'chore'
]]
}
};
Frontend + Backend Test Requirements
For projects with both frontend and backend:
. "$(dirname "$0")/_/husky.sh"
echo "🧪 Running pre-commit checks..."
BACKEND_CHANGED=$(git diff --cached --name-only | grep -E '\.(php|py|go|java)$')
FRONTEND_CHANGED=$(git diff --cached --name-only | grep -E '\.(js|jsx|ts|tsx|vue)$')
if [ -n "$BACKEND_CHANGED" ]; then
echo "🔧 Backend files changed - running backend tests..."
npm run test:backend || exit 1
fi
if [ -n "$FRONTEND_CHANGED" ]; then
echo "🎨 Frontend files changed - running frontend tests..."
npm run test:frontend || exit 1
echo "🌐 Running e2e tests..."
npm run test:e2e || exit 1
fi
if [ -n "$BACKEND_CHANGED" ] && [ -n "$FRONTEND_CHANGED" ]; then
echo "🔄 Full stack changes detected - running complete test suite..."
npm run test:all || exit 1
fi
echo "✅ All pre-commit checks passed!"
Bypassing Hooks (Emergency Only)
Never bypass hooks casually:
git commit --no-verify
If you bypass hooks:
- Add TODO comment explaining why
- Create follow-up task to fix properly
- Inform team in commit message
- Never bypass for "speed" or "convenience"
Verification
After setup, verify hooks work:
echo "const x = 1" > test.js
git add test.js
git commit -m "test"
Team Onboarding
When new developer joins:
git clone <repo>
cd <repo>
npm install
ls .git/hooks/pre-commit
Common Issues
Issue: Hooks not running
Solution:
npm run prepare
pre-commit install
Issue: Hooks too slow
Solution:
Issue: Hooks block legitimate commits
Solution:
Integration with Skills
Pre-commit hooks enforce:
- verification-before-completion - Tests must pass
- git-workflow - Commit message format
- database-backup - Prevent commits without backup (if DB changed)
- code-review - Linting/formatting standards
Commitment Required
Before proceeding, acknowledge:
The Iron Law (Repeated): NO PROJECT WITHOUT PRE-COMMIT HOOKS. This is not optional. This is professional software development.