Docs / Programming & Development / Pre-Commit Hooks Code Quality

Pre-Commit Hooks Code Quality

By Admin · Mar 15, 2026 · Updated Apr 24, 2026 · 140 views · 4 min read

Pre-commit hooks catch code quality issues before they enter your repository, preventing broken builds and maintaining consistent standards. This guide covers setting up the pre-commit framework for multi-language projects with linting, formatting, security scanning, and custom checks.

Installing pre-commit

# Install pre-commit framework
pip install pre-commit
# Or with Homebrew
brew install pre-commit

# Verify
pre-commit --version

Basic Configuration

# .pre-commit-config.yaml
repos:
  # General hooks
  - 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-merge-conflict
      - id: check-added-large-files
        args: [--maxkb=500]
      - id: detect-private-key
      - id: check-case-conflict
      - id: mixed-line-ending

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

  # JavaScript/TypeScript
  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v9.5.0
    hooks:
      - id: eslint
        types: [javascript, typescript]
        additional_dependencies:
          - eslint@9.5.0
          - typescript

  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v4.0.0-alpha.8
    hooks:
      - id: prettier
        types_or: [javascript, typescript, json, yaml, markdown, css]

  # Security
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.5.0
    hooks:
      - id: detect-secrets

  # Docker
  - repo: https://github.com/hadolint/hadolint
    rev: v2.13.0
    hooks:
      - id: hadolint-docker

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

Installation in Repository

# Install hooks in the current repo
pre-commit install

# Also install commit-msg hooks (for conventional commits)
pre-commit install --hook-type commit-msg

# Run against all files (useful for first-time setup)
pre-commit run --all-files

# Run specific hook
pre-commit run ruff --all-files

# Update hooks to latest versions
pre-commit autoupdate

Language-Specific Configurations

Go

  - repo: https://github.com/dnephin/pre-commit-golang
    rev: v0.5.1
    hooks:
      - id: go-fmt
      - id: go-vet
      - id: go-imports
      - id: golangci-lint

Rust

  - repo: https://github.com/doublify/pre-commit-rust
    rev: v1.0
    hooks:
      - id: fmt
      - id: cargo-check
      - id: clippy

PHP

  - repo: https://github.com/digitalpulp/pre-commit-php
    rev: 1.4.0
    hooks:
      - id: php-lint
      - id: php-cs-fixer
        args: [--rules=@PSR12]

Conventional Commits

  - repo: https://github.com/compilerla/conventional-pre-commit
    rev: v3.3.0
    hooks:
      - id: conventional-pre-commit
        stages: [commit-msg]
        args: [feat, fix, docs, style, refactor, test, chore, ci]

# Enforces commit messages like:
# feat: add user registration
# fix: resolve login timeout issue
# docs: update API documentation

Custom Hooks

  - repo: local
    hooks:
      - id: no-console-log
        name: Check for console.log
        entry: bash -c "! grep -rn console.log --include=*.ts --include=*.js src/"
        language: system
        pass_filenames: false

      - id: check-env-example
        name: Verify .env.example is up to date
        entry: bash -c "diff <(grep -oP '^[A-Z_]+=' .env | sort) <(grep -oP '^[A-Z_]+=' .env.example | sort)"
        language: system
        pass_filenames: false

      - id: run-tests
        name: Run unit tests
        entry: npm test
        language: system
        pass_filenames: false
        stages: [pre-push]

CI Integration

# Run pre-commit in CI to catch anything missed locally
# .github/workflows/lint.yml
name: Lint
on: [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

Team Onboarding

# Add to project README or CONTRIBUTING.md:
# 1. Install pre-commit: pip install pre-commit
# 2. Install hooks: pre-commit install
# 3. Hooks run automatically on every commit

# To bypass hooks in emergencies (discouraged):
git commit --no-verify -m "emergency fix"

# To skip specific hooks:
SKIP=eslint git commit -m "work in progress"

Summary

Pre-commit hooks are the first line of defense for code quality, catching issues seconds after writing code rather than minutes later in CI. The pre-commit framework supports every major language and tool, from linters and formatters to security scanners and custom checks. Start with the basic hooks (trailing whitespace, large files, secret detection) and gradually add language-specific linting. The investment in setup pays back immediately through cleaner pull requests, fewer CI failures, and consistent code style across the team.

Was this article helpful?