6.9 KiB
topic, source_keys
| topic | source_keys | ||
|---|---|---|---|
| configuration |
|
.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 viare.search()(not full match) on the file pathexclude: \.generated\.py$— regex excludes matching paths afterfilesmatches
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 --