Files
holocron/plugins/git/docs/research/docs/pre-commit/configuration.md

6.9 KiB

topic, source_keys
topic source_keys
configuration
context7-pre-commit-com
pre-commit-com

.pre-commit-config.yaml structure

Top-level keys

Key Type Default Purpose
repos List required List of repo blocks
default_install_hook_types List [pre-commit] Hook types installed when pre-commit install is run without -t
default_language_version Dict {} Maps language name → version string; overrides per-hook defaults
default_stages List all stages Applied to every hook unless the hook specifies stages
files Regex string '' Global include pattern applied before hook-level filters
exclude Regex string ^$ Global exclude pattern
fail_fast Boolean false Stop after the first failing hook
minimum_pre_commit_version String '0' Minimum pre-commit version required to use this config

Repo block keys

Key Required Description
repo Yes Git URL, or the special values local or meta
rev Yes (not for local/meta) Tag or SHA — must be immutable
hooks Yes List of hook override blocks

Hook override block keys

These keys appear under hooks: inside a repo block. All are optional overrides of the hook's upstream manifest values.

Key Type Description
id String (required) Hook identifier — must match an id in the repo's .pre-commit-hooks.yaml
alias String Extra name for targeting with pre-commit run <alias>
name String Override the display name
language_version String Override language version
files Regex string Override file include pattern (appended to upstream with AND logic)
exclude Regex string Override file exclude pattern
types List AND-logic type filter (all tags must match)
types_or List OR-logic type filter (any tag must match)
exclude_types List Exclude files matching these types
args List Additional CLI arguments prepended before filenames
stages List Which git stages trigger this hook
additional_dependencies List Extra packages to install into hook environment
always_run Boolean Run even if no files match the filter
verbose Boolean Always print output (not only on failure)
log_file String Write output to this file path on failure

Complete annotated example

minimum_pre_commit_version: '3.0.0'
fail_fast: false
default_language_version:
  python: python3.11
default_stages: [pre-commit, pre-push]
exclude: ^vendor/

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: pretty-format-json
        args: [--autofix]
      - id: trailing-whitespace
        exclude: ^tests/fixtures/

  - repo: local
    hooks:
      - id: validate-manifest
        name: Validate marketplace manifest
        entry: python scripts/validate_manifest.py
        language: python
        files: ^\.claude-plugin/marketplace\.json$
        always_run: false

  - repo: meta
    hooks:
      - id: check-hooks-apply
      - id: check-useless-excludes

Multi-line exclude pattern (readable for long lists)

- id: my-hook
  exclude: |
    (?x)^(
        path/to/file1.py|
        path/to/file2.py|
        path/to/generated/.*
    )$

Stages

Valid stages values: pre-commit, pre-push, commit-msg, prepare-commit-msg, post-checkout, post-commit, post-merge, post-rewrite, pre-merge-commit, pre-rebase, manual.

The manual stage only runs when explicitly invoked: pre-commit run --hook-stage manual <hookid>.

To install hooks for non-default stages, pass them to install:

pre-commit install -t pre-commit -t pre-push -t commit-msg

Or declare them in config so they install automatically:

default_install_hook_types: [pre-commit, pre-push, commit-msg]

types vs types_or vs files

  • types: [json, text] — file must carry ALL listed tags (AND)
  • types_or: [javascript, typescript] — file must carry ANY listed tag (OR)
  • files: \.py$ — regex applied via re.search() (not full match) on the file path
  • exclude: \.generated\.py$ — regex excludes matching paths after files matches

Both types and files filters must pass for a file to be processed. Use identify-cli <file> to see what tags a file has.

Local hooks (repo: local)

No external repository required. Required fields: id, name, language, entry.

- repo: local
  hooks:
    # System tool already installed (don't let pre-commit manage env)
    - id: shellcheck
      name: shellcheck
      entry: shellcheck
      language: unsupported   # formerly "system"
      types: [shell]

    # Script in the repo
    - id: run-tests
      name: Run test suite
      entry: bash tests/run-tests.sh
      language: unsupported_script  # formerly "script"
      pass_filenames: false
      always_run: true
      stages: [pre-push]

    # Always-fail guard (lightweight, no env needed)
    - id: no-dotenv
      name: No .env files
      entry: .env files must not be committed
      language: fail
      files: \.env$

    # Python with managed dependencies
    - id: my-checker
      name: My Python Checker
      entry: python -m mymodule.checker
      language: python
      additional_dependencies: [requests==2.28.0]
      types: [python]

Language choices for local hooks

Language Description
unsupported / system Runs executable from system PATH — pre-commit does not manage environment
unsupported_script / script Runs a script path relative to repo root
fail Always fails; entry text becomes the error message — good for forbidden file patterns
python Creates isolated venv; additional_dependencies are pip-installed
node Creates isolated node env
ruby, golang, rust, docker, docker_image Language-specific isolated envs

pass_filenames behavior

true (default): entry arg1 arg2 file1 file2 file3 false: entry arg1 arg2 — hook gets no filenames; use for repo-wide or stateful checks.

Meta hooks (repo: meta)

- repo: meta
  hooks:
    - id: check-hooks-apply       # each hook must match ≥1 file — catches dead hooks
    - id: check-useless-excludes  # each exclude must exclude ≥1 file — catches dead excludes
    - id: identity                # debug: prints every filename passed to pre-commit

Hazmat helpers (v4.5.0+)

Entry-point prefixes for edge cases:

# Change directory before running (monorepo)
entry: pre-commit hazmat cd subdir my-bin --

# Treat non-zero exit as warning instead of failure
entry: pre-commit hazmat ignore-exit-code my-bin --
verbose: true

# Run hook once per file (not batched)
entry: pre-commit hazmat n1 my-bin --