Git Pre Commit Validator - Hooks
Comprehensive pre-commit hook that validates code quality, runs tests, and enforces standards.
Open the source and read safety notes before installing.
Schema details
- Install type
- cli
- Reading time
- 1 min
- Difficulty score
- 0
- Troubleshooting
- Yes
- Breaking changes
- No
- Trigger
- PreToolUse
- Script language
- bash
Script body
#!/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 0Full copyable content
{
"hooks": {
"preToolUse": {
"script": "./.claude/hooks/git-pre-commit-validator.sh",
"matchers": [
"git"
]
}
}
}About this resource
Features
- Code quality validation with linting and formatting using ESLint for JavaScript/TypeScript, Prettier for code formatting, RuboCop for Ruby, Black for Python, and language-specific linters with configurable rules and auto-fix capabilities
- Security scanning for secrets and vulnerabilities with pattern matching for API keys, passwords, tokens, certificates, and sensitive data detection including .env files, private keys, and credential patterns with actionable warnings
- Automated test execution before commits with support for multiple test frameworks (Jest, Mocha, pytest, RSpec, Go test) including test discovery, related test execution for changed files, and test timeout configuration
- File validation and size limits with configurable file size thresholds (default 10MB), forbidden file detection (.env, .DS_Store, node_modules), binary file detection, and file type validation with customizable rules
- Commit message format enforcement with conventional commit message validation (feat:, fix:, docs:, etc.), pattern matching for commit message formats, and commit message length validation with actionable error messages
- Support for multiple programming languages (JavaScript, TypeScript, Python, Ruby, Go, Rust) with language-specific validation tools, automatic language detection based on file extensions, and multi-language project support
- Integration with popular pre-commit frameworks (pre-commit, husky, lint-staged) with configuration file support (.pre-commit-config.yaml, package.json scripts), framework detection, and seamless integration with existing workflows
- Configurable validation rules with environment variable overrides (SKIP_VALIDATION, SKIP_TESTS, SKIP_LINT), project-specific configuration files, and selective validation based on file types and project structure
Use Cases
- Enforce code quality standards before commits automatically running linting and formatting checks to ensure consistent code style and quality across the team with actionable error messages
- Automated testing in git workflows automatically executing tests before commits to catch bugs early and prevent broken code from entering the repository with test failure prevention
- Prevent commits with security vulnerabilities automatically scanning for secrets, API keys, passwords, and sensitive data before commits to prevent accidental exposure of credentials
- Maintain consistent code formatting across team automatically checking and optionally fixing code formatting issues before commits to ensure consistent style and reduce code review time
- Validate commit message conventions automatically enforcing conventional commit message formats and commit message standards to maintain clear commit history and enable automated changelog generation
- Development workflow integration seamlessly integrating pre-commit validation into development workflows without manual validation steps or separate quality checking tools
Installation
- Create hooks directory: mkdir -p .claude/hooks
- Create hook file: touch .claude/hooks/git-pre-commit-validator.sh
- Make executable: chmod +x .claude/hooks/git-pre-commit-validator.sh
- Add configuration from Hook Configuration section above to .claude/settings.json or ~/.claude/settings.json
- Alternative: Use the interactive /hooks command in Claude Code
Config paths
- Local (not committed):
.claude/settings.local.json - User settings (global):
~/.claude/settings.json - Project-wide (committed):
.claude/settings.json
Requirements
- Claude Code CLI installed
- Project directory initialized
- Git repository initialized
- Bash shell available
- npm/node (optional, for JavaScript/TypeScript projects)
- Python (optional, for Python projects)
- Ruby (optional, for Ruby projects)
Hook Configuration
{
"hooks": {
"preToolUse": {
"script": "./.claude/hooks/git-pre-commit-validator.sh",
"matchers": ["git"]
}
}
}
Hook Script
#!/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 0
Examples
Git Pre Commit Validator Hook Script
Complete hook script that performs pre-commit validation before Git commits
#!/usr/bin/env bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
if [[ "$COMMAND" != *"git commit"* ]]; then
exit 0
fi
STAGED_FILES=$(git diff --cached --name-only 2>/dev/null || echo "")
if [ -z "$STAGED_FILES" ]; then
exit 0
fi
echo "🔍 Running pre-commit validations..." >&2
if echo "$STAGED_FILES" | grep -E "\.(env|DS_Store)$|node_modules/"; then
echo "❌ Forbidden files detected in staging area" >&2
exit 1
fi
if command -v npm &> /dev/null && [ -f "package.json" ]; then
if grep -q '"lint"' package.json; then
npm run lint 2>/dev/null || exit 1
fi
fi
echo "✅ Pre-commit validation completed" >&2
exit 0
Hook Configuration
Complete hook configuration for .claude/settings.json to enable pre-commit validation
{
"hooks": {
"preToolUse": {
"script": "./.claude/hooks/git-pre-commit-validator.sh",
"matchers": ["git"]
}
}
}
Security Scanning for Sensitive Files
Enhanced hook script for security scanning and sensitive file detection
#!/usr/bin/env bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
if [[ "$COMMAND" != *"git commit"* ]]; then
exit 0
fi
STAGED_FILES=$(git diff --cached --name-only 2>/dev/null || echo "")
if [ -z "$STAGED_FILES" ]; then
exit 0
fi
SENSITIVE_PATTERNS=(".env" "*secret*" "*password*" "*key*" "id_rsa" "id_ed25519" "*.pem")
SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if echo "$STAGED_FILES" | grep -q "$pattern"; then
SENSITIVE_FOUND=true
echo "⚠️ Potentially sensitive file detected: $pattern" >&2
fi
done
if [ "$SENSITIVE_FOUND" = true ]; then
echo "❌ Security: Sensitive files detected in staging area" >&2
exit 1
fi
exit 0
File Size Validation
Enhanced hook script for file size validation with Git LFS recommendations
#!/usr/bin/env bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
if [[ "$COMMAND" != *"git commit"* ]]; then
exit 0
fi
STAGED_FILES=$(git diff --cached --name-only 2>/dev/null || echo "")
if [ -z "$STAGED_FILES" ]; then
exit 0
fi
MAX_SIZE=10485760
for file in $STAGED_FILES; do
if [ -f "$file" ]; then
size=$(wc -c < "$file" 2>/dev/null || echo "0")
if [ "$size" -gt "$MAX_SIZE" ]; then
size_mb=$((size / 1024 / 1024))
echo "⚠️ Large file detected: $file (${size_mb}MB)" >&2
if [ "$size" -gt 52428800 ]; then
echo "❌ File exceeds 50MB limit - consider using Git LFS" >&2
exit 1
fi
fi
fi
done
exit 0
Commit Message Format Validation
Enhanced hook script for commit message format validation with conventional commits
#!/usr/bin/env bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
if [[ "$COMMAND" != *"git commit"* ]]; then
exit 0
fi
COMMIT_MSG=$(git log -1 --pretty=%B 2>/dev/null || echo "")
if [ -n "$COMMIT_MSG" ]; then
if ! echo "$COMMIT_MSG" | grep -qE "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?:"; then
echo "⚠️ Commit message doesn't follow conventional format" >&2
echo "Expected format: type(scope): description" >&2
echo "Types: feat, fix, docs, style, refactor, test, chore" >&2
fi
fi
exit 0
Troubleshooting
Hook 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. Verify command detection logic: 'if [["$COMMAND" != "git commit"]]; then exit 0; fi'. Test with different git commands to ensure only commits are validated.
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. Check package.json for lint script: 'grep -q '"lint"' package.json'. Use conditional execution: 'if command -v npm &> /dev/null && [ -f package.json ] && grep -q '"lint"' package.json; then npm run lint; fi'.
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. Use prettier --check for validation only. Consider using lint-staged for automatic formatting. Add SKIP_FORMAT environment variable for emergency overrides.
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. Use test filtering: 'npm test -- --testPathPattern=$(echo $STAGED_FILES | tr ' ' '|')'. Consider using SKIP_TESTS environment variable for local development. Add test timeout limits.
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. Use 'git ls-files --cached' to check if file is already tracked. Add logic to skip size validation for modified files: 'if git ls-files --error-unmatch "$file" &> /dev/null; then continue; fi'.
Security scanning false positives for legitimate files
Refine sensitive file patterns to avoid false positives. Use whitelist for known safe files: 'if echo "$file" | grep -qE "(test|spec|example|sample)"; then continue; fi'. Add configuration file for custom patterns. Use git-secrets or similar tools for more accurate detection. Consider using SKIP_SECURITY environment variable for development.
Commit message validation too strict for project conventions
Customize commit message patterns based on project requirements. Use environment variable for custom patterns: 'COMMIT_MSG_PATTERN'. Add project-specific configuration file. Make validation optional with SKIP_COMMIT_MSG environment variable. Support multiple commit message formats. Use case-insensitive matching for flexibility.
Validation fails in CI/CD environments with different tool versions
Use version pinning for validation tools. Check tool versions before running: 'eslint --version'. Add version compatibility checks. Use Docker containers for consistent environments. Consider using pre-commit framework for tool management. Add SKIP_VALIDATION environment variable for CI/CD overrides. Document required tool versions.
- Features
- Use Cases
- Installation
- Config paths
- Requirements
- Hook Configuration
- Hook Script
- Examples
- Git Pre Commit Validator Hook Script
- Hook Configuration
- Security Scanning for Sensitive Files
- File Size Validation
- Commit Message Format Validation
- Troubleshooting
- Hook blocks all git commits even when validation passes
- npm run lint fails with 'script not found' error
Source citations
Signals
Loading live community signals…
A short, calm digest of reviewed Claude resources. Unsubscribe any time.