207 lines
6.9 KiB
Markdown
207 lines
6.9 KiB
Markdown
---
|
|
topic: configuration
|
|
source_keys:
|
|
- 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
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
- 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:
|
|
```bash
|
|
pre-commit install -t pre-commit -t pre-push -t commit-msg
|
|
```
|
|
|
|
Or declare them in config so they install automatically:
|
|
```yaml
|
|
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`.
|
|
|
|
```yaml
|
|
- 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`)
|
|
|
|
```yaml
|
|
- 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:
|
|
|
|
```yaml
|
|
# 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 --
|
|
```
|