git-hooks-automation

Master Git hooks setup with Husky, lint-staged, pre-commit framework, and commitlint. Automate code quality gates, formatting, linting, and commit message enforcement before code reaches CI.

31,392 stars
Complexity: medium

About this skill

This skill empowers an AI agent to set up robust Git hooks in your project, automating critical code quality checks directly within your development workflow. It leverages industry-standard tools like **Husky** for managing Git hooks, **lint-staged** for running linters and formatters only on staged Git files, the **pre-commit framework** for multi-language hook management, and **commitlint** for enforcing conventional commit message standards. By implementing these pre-commit and pre-push gates, the skill ensures that code is consistently formatted, linted, and adheres to project standards *before* it ever reaches your CI/CD pipeline. This significantly reduces feedback cycles, catches issues in seconds, and maintains a high-quality, standardized codebase.

Best use case

Establishing automated code quality gates within a software project. Enforcing consistent code style and formatting across a development team. Standardizing commit messages to improve changelog generation and project history readability. Reducing the workload and failure rate of CI/CD pipelines by catching common issues earlier. Integrating linters (e.g., ESLint, Stylelint), formatters (e.g., Prettier), and type checkers (e.g., TypeScript) into the Git workflow.

Master Git hooks setup with Husky, lint-staged, pre-commit framework, and commitlint. Automate code quality gates, formatting, linting, and commit message enforcement before code reaches CI.

Your project will have Git hooks (e.g., `pre-commit`, `pre-push`, `commit-msg`) configured and active. Automated checks for code quality, formatting, and commit message validity will run before code is committed or pushed. Developers will receive instant feedback on potential issues, leading to earlier problem detection and resolution. A more consistent and higher-quality codebase will be maintained, reducing CI/CD failures and manual review effort. Dependencies for Git hook management (e.g., Husky, lint-staged, commitlint) will be added and configured.

Practical example

Example input

I'm starting a new Node.js project. Can you help me set up Git hooks to enforce code quality? I'd like to use ESLint, Prettier, and ensure commit messages follow Conventional Commits standard. Use Husky and lint-staged.

Example output

Okay, I've set up Git hooks for your Node.js project!

Here's what I've done:
1.  **Installed dependencies**: `husky`, `lint-staged`, `eslint`, `prettier`, `commitlint`, `@commitlint/config-conventional`.
2.  **Configured Husky**: Initialized Husky and created a `pre-commit` hook that runs `lint-staged` and a `commit-msg` hook that runs `commitlint`.
3.  **Configured lint-staged**: Created a `.lintstagedrc.json` file to run `eslint --fix` and `prettier --write` on staged `.js`, `.jsx`, `.ts`, `.tsx`, `.json`, and `.md` files.
4.  **Configured Commitlint**: Created a `commitlint.config.js` file to extend `@commitlint/config-conventional`.
5.  **Updated package.json**: Added scripts for `lint`, `format`, and post-install script for Husky.

Now, whenever you commit, ESLint and Prettier will automatically fix issues in staged files, and your commit message will be validated against Conventional Commits rules. If any checks fail, the commit will be blocked.

To test it, try making a small change, staging it, and then committing with a malformed message (e.g., `oops: my change`).

When to use this skill

  • When a user explicitly asks to "set up Git hooks" or "add pre-commit checks" to their project.
  • To configure or integrate Husky, lint-staged, the pre-commit framework, or commitlint.
  • For automating code quality tasks like linting, formatting, or type-checking before commits or pushes.
  • When enforcing specific commit message conventions, such as Conventional Commits.

When not to use this skill

  • In projects where strict code quality enforcement is explicitly not desired (e.g., quick prototypes, throwaway scripts).
  • If the user's development environment or project type is incompatible with the underlying tools (e.g., very niche languages/frameworks not supported by general-purpose linters/formatters).
  • When the user specifically requests to disable or remove existing Git hooks.
  • If the project already has a comprehensive and satisfactory Git hook setup.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/git-hooks-automation/SKILL.md --create-dirs "https://raw.githubusercontent.com/sickn33/antigravity-awesome-skills/main/plugins/antigravity-awesome-skills-claude/skills/git-hooks-automation/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/git-hooks-automation/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How git-hooks-automation Compares

Feature / Agentgit-hooks-automationStandard Approach
Platform SupportClaudeLimited / Varies
Context Awareness High Baseline
Installation ComplexitymediumN/A

Frequently Asked Questions

What does this skill do?

Master Git hooks setup with Husky, lint-staged, pre-commit framework, and commitlint. Automate code quality gates, formatting, linting, and commit message enforcement before code reaches CI.

Which AI agents support this skill?

This skill is designed for Claude.

How difficult is it to install?

The installation complexity is rated as medium. You can find the installation instructions above.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Git Hooks Automation

Automate code quality enforcement at the Git level. Set up hooks that lint, format, test, and validate before commits and pushes ever reach your CI pipeline — catching issues in seconds instead of minutes.

## When to Use This Skill

- User asks to "set up git hooks" or "add pre-commit hooks"
- Configuring Husky, lint-staged, or the pre-commit framework
- Enforcing commit message conventions (Conventional Commits, commitlint)
- Automating linting, formatting, or type-checking before commits
- Setting up pre-push hooks for test runners
- Migrating from Husky v4 to v9+ or adopting hooks from scratch
- User mentions "pre-commit", "commit-msg", "pre-push", "lint-staged", or "githooks"

## Git Hooks Fundamentals

Git hooks are scripts that run automatically at specific points in the Git workflow. They live in `.git/hooks/` and are not version-controlled by default — which is why tools like Husky exist.

### Hook Types & When They Fire

| Hook | Fires When | Common Use |
|---|---|---|
| `pre-commit` | Before commit is created | Lint, format, type-check staged files |
| `prepare-commit-msg` | After default msg, before editor | Auto-populate commit templates |
| `commit-msg` | After user writes commit message | Enforce commit message format |
| `post-commit` | After commit is created | Notifications, logging |
| `pre-push` | Before push to remote | Run tests, check branch policies |
| `pre-rebase` | Before rebase starts | Prevent rebase on protected branches |
| `post-merge` | After merge completes | Install deps, run migrations |
| `post-checkout` | After checkout/switch | Install deps, rebuild assets |

### Native Git Hooks (No Framework)

```bash
# Create a pre-commit hook manually
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
set -e

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

if [ -n "$STAGED_FILES" ]; then
  echo "🔍 Linting staged files..."
  echo "$STAGED_FILES" | xargs npx eslint --fix
  echo "$STAGED_FILES" | xargs git add  # Re-stage after fixes
fi
EOF
chmod +x .git/hooks/pre-commit
```

**Problem**: `.git/hooks/` is local-only and not shared with the team. Use a framework instead.

## Husky + lint-staged (Node.js Projects)

The modern standard for JavaScript/TypeScript projects. Husky manages Git hooks; lint-staged runs commands only on staged files for speed.

### Quick Setup (Husky v9+)

```bash
# Install
npm install --save-dev husky lint-staged

# Initialize Husky (creates .husky/ directory)
npx husky init

# The init command creates a pre-commit hook — edit it:
echo "npx lint-staged" > .husky/pre-commit
```

### Configure lint-staged in `package.json`

```json
{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix --max-warnings=0",
      "prettier --write"
    ],
    "*.{css,scss}": [
      "prettier --write",
      "stylelint --fix"
    ],
    "*.{json,md,yml,yaml}": [
      "prettier --write"
    ]
  }
}
```

### Add Commit Message Linting

```bash
# Install commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional

# Create commitlint config
cat > commitlint.config.js << 'EOF'
module.exports = {
  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': [2, 'always', 100]
  }
};
EOF

# Add commit-msg hook
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
```

### Add Pre-Push Hook

```bash
# Run tests before pushing
echo "npm test" > .husky/pre-push
```

### Complete Husky Directory Structure

```
project/
├── .husky/
│   ├── pre-commit        # npx lint-staged
│   ├── commit-msg        # npx --no -- commitlint --edit $1
│   └── pre-push          # npm test
├── commitlint.config.js
├── package.json          # lint-staged config here
└── ...
```

## pre-commit Framework (Python / Polyglot)

Language-agnostic framework that works with any project. Hooks are defined in YAML and run in isolated environments.

### Setup

```bash
# Install (Python required)
pip install pre-commit

# Create config
cat > .pre-commit-config.yaml << 'EOF'
repos:
  # Built-in checks
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: check-added-large-files
        args: ['--maxkb=500']
      - id: check-merge-conflict
      - id: detect-private-key

  # Python formatting
  - repo: https://github.com/psf/black
    rev: 24.4.2
    hooks:
      - id: black

  # Python linting
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.4
    hooks:
      - id: ruff
        args: ['--fix']
      - id: ruff-format

  # Shell script linting
  - repo: https://github.com/shellcheck-py/shellcheck-py
    rev: v0.10.0.1
    hooks:
      - id: shellcheck

  # Commit message format
  - repo: https://github.com/compilerla/conventional-pre-commit
    rev: v3.2.0
    hooks:
      - id: conventional-pre-commit
        stages: [commit-msg]
EOF

# Install hooks into .git/hooks/
pre-commit install
pre-commit install --hook-type commit-msg

# Run against all files (first time)
pre-commit run --all-files
```

### Key Commands

```bash
pre-commit install              # Install hooks
pre-commit run --all-files      # Run on everything (CI or first setup)
pre-commit autoupdate           # Update hook versions
pre-commit run <hook-id>        # Run a specific hook
pre-commit clean                # Clear cached environments
```

## Custom Hook Scripts (Any Language)

For projects not using Node or Python, write hooks directly in shell.

### Portable Pre-Commit Hook

```bash
#!/bin/sh
# .githooks/pre-commit — Team-shared hooks directory
set -e

echo "=== Pre-Commit Checks ==="

# 1. Prevent commits to main/master
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "detached")
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
  echo "❌ Direct commits to $BRANCH are not allowed. Use a feature branch."
  exit 1
fi

# 2. Check for debugging artifacts
if git diff --cached --diff-filter=ACM | grep -nE '(console\.log|debugger|binding\.pry|import pdb)' > /dev/null 2>&1; then
  echo "⚠️  Debug statements found in staged files:"
  git diff --cached --diff-filter=ACM | grep -nE '(console\.log|debugger|binding\.pry|import pdb)'
  echo "Remove them or use git commit --no-verify to bypass."
  exit 1
fi

# 3. Check for large files (>1MB)
LARGE_FILES=$(git diff --cached --name-only --diff-filter=ACM | while read f; do
  size=$(wc -c < "$f" 2>/dev/null || echo 0)
  if [ "$size" -gt 1048576 ]; then echo "$f ($((size/1024))KB)"; fi
done)
if [ -n "$LARGE_FILES" ]; then
  echo "❌ Large files detected:"
  echo "$LARGE_FILES"
  exit 1
fi

# 4. Check for secrets patterns
if git diff --cached --diff-filter=ACM | grep -nEi '(AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{48}|ghp_[a-zA-Z0-9]{36}|password\s*=\s*["\x27][^"\x27]+["\x27])' > /dev/null 2>&1; then
  echo "🚨 Potential secrets detected in staged changes! Review before committing."
  exit 1
fi

echo "✅ All pre-commit checks passed"
```

### Share Custom Hooks via `core.hooksPath`

```bash
# In your repo, set a shared hooks directory
git config core.hooksPath .githooks

# Add to project setup docs or Makefile
# Makefile
setup:
	git config core.hooksPath .githooks
	chmod +x .githooks/*
```

## CI Integration

Hooks are a first line of defense, but CI is the source of truth.

### Run pre-commit in CI (GitHub Actions)

```yaml
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - uses: pre-commit/action@v3.0.1
```

### Run lint-staged in CI (Validation Only)

```yaml
# Validate that lint-staged would pass (catch bypassed hooks)
name: Lint Check
on: [pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx eslint . --max-warnings=0
      - run: npx prettier --check .
```

## Common Pitfalls & Fixes

### Hooks Not Running

| Symptom | Cause | Fix |
|---|---|---|
| Hooks silently skipped | Not installed in `.git/hooks/` | Run `npx husky init` or `pre-commit install` |
| "Permission denied" | Hook file not executable | `chmod +x .husky/pre-commit` |
| Hooks run but wrong ones | Stale hooks from old setup | Delete `.git/hooks/` contents, reinstall |
| Works locally, fails in CI | Different Node/Python versions | Pin versions in CI config |

### Performance Issues

```json
// ❌ Slow: runs on ALL files every commit
{
  "scripts": {
    "precommit": "eslint src/ && prettier --write src/"
  }
}

// ✅ Fast: lint-staged runs ONLY on staged files
{
  "lint-staged": {
    "*.{js,ts}": ["eslint --fix", "prettier --write"]
  }
}
```

### Bypassing Hooks (When Needed)

```bash
# Skip all hooks for a single commit
git commit --no-verify -m "wip: quick save"

# Skip pre-push only
git push --no-verify

# Skip specific pre-commit hooks
SKIP=eslint git commit -m "fix: update config"
```

> **Warning**: Bypassing hooks should be rare. If your team frequently bypasses, the hooks are too slow or too strict — fix them.

## Migration Guide

### Husky v4 → v9 Migration

```bash
# 1. Remove old Husky
npm uninstall husky
rm -rf .husky

# 2. Remove old config from package.json
# Delete "husky": { "hooks": { ... } } section

# 3. Install fresh
npm install --save-dev husky
npx husky init

# 4. Recreate hooks
echo "npx lint-staged" > .husky/pre-commit
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg

# 5. Clean up — old Husky used package.json config,
#    new Husky uses .husky/ directory with plain scripts
```

### Adopting Hooks on an Existing Project

```bash
# Step 1: Start with formatting only (low friction)
# lint-staged config:
{ "*.{js,ts}": ["prettier --write"] }

# Step 2: Add linting after team adjusts (1-2 weeks later)
{ "*.{js,ts}": ["eslint --fix", "prettier --write"] }

# Step 3: Add commit message linting
# Step 4: Add pre-push test runner

# Gradual adoption prevents team resistance
```

## Key Principles

- **Staged files only** — Never lint the entire codebase on every commit
- **Auto-fix when possible** — `--fix` flags reduce developer friction
- **Fast hooks** — Pre-commit should complete in < 5 seconds
- **Fail loud** — Clear error messages with actionable fixes
- **Team-shared** — Use Husky or `core.hooksPath` so hooks are version-controlled
- **CI as backup** — Hooks are convenience; CI is the enforcer
- **Gradual adoption** — Start with formatting, add linting, then testing

## Related Skills

- `@codebase-audit-pre-push` - Deep audit before GitHub push
- `@verification-before-completion` - Verification before claiming work is done
- `@bash-pro` - Advanced shell scripting for custom hooks
- `@github-actions-templates` - CI/CD workflow templates

Related Skills

changelog-automation

31392
from sickn33/antigravity-awesome-skills

Automate changelog generation from commits, PRs, and releases following Keep a Changelog format. Use when setting up release workflows, generating release notes, or standardizing commit conventions.

Developer ToolsClaude

n8n-expression-syntax

31392
from sickn33/antigravity-awesome-skills

Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node variables, troubleshooting expression errors, or working with webhook data in workflows.

Developer ToolsClaude

mermaid-expert

31392
from sickn33/antigravity-awesome-skills

Create Mermaid diagrams for flowcharts, sequences, ERDs, and architectures. Masters syntax for all diagram types and styling.

Developer ToolsClaude

mcp-builder-ms

31392
from sickn33/antigravity-awesome-skills

Use this skill when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

Developer ToolsClaude

makepad-deployment

31392
from sickn33/antigravity-awesome-skills

CRITICAL: Use for Makepad packaging and deployment. Triggers on: deploy, package, APK, IPA, 打包, 部署, cargo-packager, cargo-makepad, WASM, Android, iOS, distribution, installer, .deb, .dmg, .nsis, GitHub Actions, CI, action, marketplace

Developer ToolsClaude

macos-menubar-tuist-app

31392
from sickn33/antigravity-awesome-skills

Build, refactor, or review SwiftUI macOS menubar apps that use Tuist.

Developer ToolsClaude

kaizen

31392
from sickn33/antigravity-awesome-skills

Guide for continuous improvement, error proofing, and standardization. Use this skill when the user wants to improve code quality, refactor, or discuss process improvements.

Developer ToolsClaude

issues

31392
from sickn33/antigravity-awesome-skills

Interact with GitHub issues - create, list, and view issues.

Developer ToolsClaude

hugging-face-tool-builder

31392
from sickn33/antigravity-awesome-skills

Your purpose is now is to create reusable command line scripts and utilities for using the Hugging Face API, allowing chaining, piping and intermediate processing where helpful. You can access the API directly, as well as use the hf command line tool.

Developer ToolsClaude

git-pushing

31392
from sickn33/antigravity-awesome-skills

Stage all changes, create a conventional commit, and push to the remote branch. Use when explicitly asks to push changes ("push this", "commit and push"), mentions saving work to remote ("save to github", "push to remote"), or completes a feature and wants to share it.

Developer ToolsClaude

gh-review-requests

31392
from sickn33/antigravity-awesome-skills

Fetch unread GitHub notifications for open PRs where review is requested from a specified team or opened by a team member. Use when asked to "find PRs I need to review", "show my review requests", "what needs my review", "fetch GitHub review requests", or "check team review queue".

Developer ToolsClaude

fp-types-ref

31392
from sickn33/antigravity-awesome-skills

Quick reference for fp-ts types. Use when user asks which type to use, needs Option/Either/Task decision help, or wants fp-ts imports.

Developer ToolsClaude