Filter Pre-Commit Hooks by Directory | Generated by AI

Home 2026.03

Question: How do you specify only certain subdirectories in a pre-commit hook (e.g., for ruff-check)?


Answer:

There are two keys you use in .pre-commit-config.yaml to filter by path:

Key Purpose
files Include only files matching this regex pattern
exclude Skip files matching this regex pattern

Both accept Python regular expressions matched against file paths relative to the repo root.


Method 1 — files: to include only specific subdirs

Run ruff only on src/ and tests/:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.5
    hooks:
      - id: ruff-check
        args: [ --fix ]
        files: ^(src|tests)/     # only run in src/ and tests/
      - id: ruff-format
        files: ^(src|tests)/

Method 2 — exclude: to skip certain subdirs

Run ruff on everything except docs/ and migrations/:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.5
    hooks:
      - id: ruff-check
        args: [ --fix ]
        exclude: ^(docs|migrations)/
      - id: ruff-format
        exclude: ^(docs|migrations)/

Method 3 — Verbose regex for many paths (cleaner syntax)

When the regular expression becomes unwieldy with many paths, you can use YAML’s multiline literal combined with the (?x) verbose regex flag:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.5
    hooks:
      - id: ruff-check
        args: [ --fix ]
        exclude: |
          (?x)^(
            docs/.*|
            migrations/.*|
            legacy/.*|
            scripts/old/.*
          )$

Method 4 — Global exclude (applies to ALL hooks)

You can also set a top-level exclude at the root of the config file to apply to every hook, without repeating it per hook:

exclude: |
  (?x)^(
    docs/.*|
    migrations/.*|
    .*cache.*/.*|
    .*venv.*/.*
  )$

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.5
    hooks:
      - id: ruff-check
        args: [ --fix ]
      - id: ruff-format

Important: force-exclude for Ruff

The ruff-pre-commit hooks use --force-exclude by default, which ensures that Ruff respects exclusion patterns even when files are explicitly passed on the command line by pre-commit. This means Ruff’s own exclude in pyproject.toml will also be honoured. However, if you encounter cases where exclude in pyproject.toml is being ignored, the safest solution is to also add the exclude pattern directly in .pre-commit-config.yaml for the ruff hook.


Combined Real-World Example

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.5
    hooks:
      - id: ruff-check
        args: [ --fix ]
        files: ^src/           # only lint the src/ directory
        exclude: ^src/legacy/  # but skip the legacy subfolder inside it
      - id: ruff-format
        files: ^src/
        exclude: ^src/legacy/

References:


Back Donate