Loading...
Comprehensive pre-commit hook that validates code quality, runs tests, and enforces standards
{
"hookConfig": {
"hooks": {
"preToolUse": {
"script": "./.claude/hooks/git-pre-commit-validator.sh",
"matchers": [
"git"
]
}
}
},
"scriptContent": "#!/usr/bin/env bash\n\n# Read the tool input from stdin\nINPUT=$(cat)\nTOOL_NAME=$(echo \"$INPUT\" | jq -r '.tool_name')\nCOMMAND=$(echo \"$INPUT\" | jq -r '.tool_input.command // \"\"')\n\n# Only run on git commit commands\nif [[ \"$COMMAND\" != *\"git commit\"* ]]; then\n exit 0\nfi\n\necho \"🔍 Running pre-commit validations...\"\n\n# Check for staged files\nSTAGED_FILES=$(git diff --cached --name-only 2>/dev/null || echo \"\")\nif [ -z \"$STAGED_FILES\" ]; then\n echo \"No staged files to validate\"\n exit 0\nfi\n\necho \"Validating staged files: $STAGED_FILES\"\n\n# Check for forbidden files\necho \"Checking for forbidden files...\"\nif echo \"$STAGED_FILES\" | grep -E \"\\.(env|DS_Store)$|node_modules/\"; then\n echo \"❌ Forbidden files detected in staging area\" >&2\n echo \"Remove .env, .DS_Store, or node_modules files before committing\" >&2\n exit 2\nfi\n\n# Check file sizes\necho \"Checking file sizes...\"\nfor file in $STAGED_FILES; do\n if [ -f \"$file\" ]; then\n size=$(wc -c < \"$file\")\n if [ \"$size\" -gt 10485760 ]; then # 10MB limit\n echo \"⚠️ Large file detected: $file ($(($size / 1024 / 1024))MB)\" >&2\n fi\n fi\ndone\n\n# Run linting if available\nif command -v npm &> /dev/null && [ -f \"package.json\" ]; then\n echo \"Running ESLint...\"\n npm run lint 2>/dev/null || echo \"⚠️ Linting issues found\" >&2\nfi\n\n# Run formatting if available\nif command -v prettier &> /dev/null; then\n echo \"Running Prettier...\"\n prettier --check $STAGED_FILES 2>/dev/null || echo \"⚠️ Formatting issues found\" >&2\nfi\n\n# Run tests if available\nif command -v npm &> /dev/null && [ -f \"package.json\" ]; then\n echo \"Running tests...\"\n npm test 2>/dev/null || echo \"⚠️ Tests failed\" >&2\nfi\n\necho \"✅ Pre-commit validation completed\" >&2\nexit 0"
}.claude/hooks/~/.claude/hooks/{
"hooks": {
"preToolUse": {
"script": "./.claude/hooks/git-pre-commit-validator.sh",
"matchers": [
"git"
]
}
}
}#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
# Only run on git commit commands
if [[ "$COMMAND" != *"git commit"* ]]; then
exit 0
fi
echo "🔍 Running pre-commit validations..."
# Check for staged files
STAGED_FILES=$(git diff --cached --name-only 2>/dev/null || echo "")
if [ -z "$STAGED_FILES" ]; then
echo "No staged files to validate"
exit 0
fi
echo "Validating staged files: $STAGED_FILES"
# Check for forbidden files
echo "Checking for forbidden files..."
if echo "$STAGED_FILES" | grep -E "\.(env|DS_Store)$|node_modules/"; then
echo "❌ Forbidden files detected in staging area" >&2
echo "Remove .env, .DS_Store, or node_modules files before committing" >&2
exit 2
fi
# Check file sizes
echo "Checking file sizes..."
for file in $STAGED_FILES; do
if [ -f "$file" ]; then
size=$(wc -c < "$file")
if [ "$size" -gt 10485760 ]; then # 10MB limit
echo "⚠️ Large file detected: $file ($(($size / 1024 / 1024))MB)" >&2
fi
fi
done
# Run linting if available
if command -v npm &> /dev/null && [ -f "package.json" ]; then
echo "Running ESLint..."
npm run lint 2>/dev/null || echo "⚠️ Linting issues found" >&2
fi
# Run formatting if available
if command -v prettier &> /dev/null; then
echo "Running Prettier..."
prettier --check $STAGED_FILES 2>/dev/null || echo "⚠️ Formatting issues found" >&2
fi
# Run tests if available
if command -v npm &> /dev/null && [ -f "package.json" ]; then
echo "Running tests..."
npm test 2>/dev/null || echo "⚠️ Tests failed" >&2
fi
echo "✅ Pre-commit validation completed" >&2
exit 0Hook blocks all git commits even when validation passes
Ensure script exits with exit 0 on success. Check that matchers pattern ['git'] doesn't intercept non-commit git commands like status or diff which should bypass validation.
npm run lint fails with 'script not found' error
Add existence check before running: [ -f package.json ] && grep -q '"lint"' package.json before npm run lint. Provide fallback or skip linting gracefully if unavailable.
Prettier check prevents commits due to formatting differences
Auto-fix formatting instead of blocking: prettier --write $STAGED_FILES && git add $STAGED_FILES. Alternatively, set --warn-only flag to log issues without exit code.
Test suite runs entire test set causing slow commit times
Run only tests related to changed files: npm test -- --findRelatedTests $STAGED_FILES. Add timeout: npm test -- --maxWorkers=2 --bail for faster feedback.
Hook rejects large files but files are already in history
Check if file is new vs modified: git diff --cached --diff-filter=A to detect additions only. Skip size check for existing tracked files to avoid retroactive enforcement.
Loading reviews...
Join our community of Claude power users. No spam, unsubscribe anytime.
Automated accessibility testing and compliance checking for web applications following WCAG guidelines
Automatically generates or updates API documentation when endpoint files are modified
Automatically formats code files after Claude writes or edits them using Prettier, Black, or other formatters