⚙️ Automation

Git Hooks Configuration

Set up Git hooks for automated code quality checks and workflow enforcement

★★★ Advanced 25 min January 13, 2025

Use Case

Git hooks automate quality checks before commits and pushes. Cowork can generate customized hooks for linting, testing, commit message validation, and more.

Example Prompt

I want to set up Git hooks for my JavaScript project at ~/Projects/myapp/. Please create:

1. pre-commit hook:
   - Run ESLint on staged files
   - Run Prettier formatting check
   - Prevent commits with console.log

2. commit-msg hook:
   - Enforce conventional commit format
   - Require ticket reference (PROJ-XXX)

3. pre-push hook:
   - Run full test suite
   - Check for TODO/FIXME comments
   - Prevent push to main without PR

Save hooks to .git/hooks/ and make them executable

What Cowork Does

  1. Hook Generation: Creates shell scripts for each hook type
  2. Tool Integration: Integrates with ESLint, Prettier, Jest
  3. Pattern Matching: Sets up regex for commit validation
  4. Permission Setup: Makes hooks executable
  5. Documentation: Adds usage instructions

Sample Output

#!/bin/sh
# .git/hooks/pre-commit

echo "🔍 Running pre-commit checks..."

# Get staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|jsx|tsx)$')

if [ -z "$STAGED_FILES" ]; then
    echo "No JS/TS files to check"
    exit 0
fi

# Check for console.log
echo "Checking for console.log statements..."
if grep -n "console\.log" $STAGED_FILES; then
    echo "❌ Error: console.log found in staged files"
    echo "Remove or replace with proper logging"
    exit 1
fi

# Run ESLint
echo "Running ESLint..."
npx eslint $STAGED_FILES
if [ $? -ne 0 ]; then
    echo "❌ ESLint failed"
    exit 1
fi

# Run Prettier check
echo "Checking formatting..."
npx prettier --check $STAGED_FILES
if [ $? -ne 0 ]; then
    echo "❌ Formatting issues found"
    echo "Run: npx prettier --write <files>"
    exit 1
fi

echo "✅ Pre-commit checks passed!"
exit 0
#!/bin/sh
# .git/hooks/commit-msg

COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")

# Conventional commit pattern
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\([a-z-]+\))?: .+"

# Ticket reference pattern
TICKET_PATTERN="PROJ-[0-9]+"

if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
    echo "❌ Invalid commit message format"
    echo ""
    echo "Expected format: type(scope): description"
    echo "Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert"
    echo ""
    echo "Example: feat(auth): add OAuth2 support PROJ-123"
    exit 1
fi

if ! echo "$COMMIT_MSG" | grep -qE "$TICKET_PATTERN"; then
    echo "❌ Missing ticket reference (PROJ-XXX)"
    exit 1
fi

echo "✅ Commit message validated"
exit 0
#!/bin/sh
# .git/hooks/pre-push

BRANCH=$(git rev-parse --abbrev-ref HEAD)

# Prevent direct push to main
if [ "$BRANCH" = "main" ]; then
    echo "❌ Cannot push directly to main"
    echo "Create a PR instead"
    exit 1
fi

# Run tests
echo "🧪 Running tests..."
npm test
if [ $? -ne 0 ]; then
    echo "❌ Tests failed"
    exit 1
fi

# Check for TODO/FIXME
echo "Checking for TODO/FIXME..."
if git diff origin/main...HEAD | grep -E "TODO|FIXME"; then
    echo "⚠️  Warning: TODO/FIXME comments found"
    read -p "Continue anyway? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        exit 1
    fi
fi

echo "✅ Pre-push checks passed!"
exit 0

Tips

  • Use husky or lefthook for easier hook management
  • Include bypass instructions for emergencies
  • Keep hooks fast to avoid frustration
  • Consider team-wide hook sharing via npm