Problem
Repeated --group options use union semantics: a hook is selected when it belongs to any requested group. There is currently no equivalent selector for requiring a hook to belong to every requested group, so users must define an additional combined group for each needed intersection.
Proposed behavior
Add a repeatable --require-group <GROUP> option to prek run. A hook would satisfy this filter only when its groups contains every value passed through --require-group.
The filters should compose independently of argument order:
(no --group values, or any --group value matches)
AND
(every --require-group value matches)
AND
(no --no-group value matches)
--no-group would continue to take precedence over inclusion filters.
Configuration
repos:
- repo: https://github.com/astral-sh/ty-pre-commit
rev: v0.0.63
hooks:
- id: ty
groups: [lint, fast, local]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.0
hooks:
- id: ruff-format
groups: [format, fast, local]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v2.3.0
hooks:
- id: mypy
groups: [lint, slow, ci]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 26.5.1
hooks:
- id: black
groups: [format, slow, ci]
This configuration has two hooks in each functional group, two hooks in each performance group, fast hooks assigned to local, and slow hooks assigned to ci.
Usage
- Use multiple
--require-group filters:
$ prek run --all-files --require-group lint --require-group fast
This runs only ty, which belongs to both required groups.
- Combine multiple
--require-group and --group filters:
$ prek run --all-files --require-group format --require-group fast --group lint --group local
This runs only ruff-format. It belongs to every required group and matches the included local group. It does not need to match lint because repeated --group values use union semantics.
- Combine multiple
--require-group and --no-group filters:
$ prek run --all-files --require-group lint --require-group slow --no-group format --no-group local
This runs only mypy. It belongs to every required group and belongs to neither excluded group.
- Combine multiple
--require-group, --group, and --no-group filters:
$ prek run --all-files --require-group format --require-group slow --group lint --group ci --no-group fast --no-group local
This runs only black. It belongs to every required group, matches the included ci group, and belongs to neither excluded group.
Acceptance criteria
--require-group <GROUP> can be specified multiple times.
- A hook matches only when it belongs to every specified required group.
--group, --require-group, and --no-group compose according to the selection model above.
- Filter behavior is independent of argument order.
- Using
--require-group activates the same group selection mode as --group and --no-group.
- An explicit
--stage further restricts the matched hooks using the existing stage intersection behavior.
- Hooks excluded by the resulting filters are not installed or executed.
- A run fails with the existing explicit-selection error when no hook matches the complete intersection.
- Existing behavior remains unchanged when
--require-group is not provided.
References
Problem
Repeated
--groupoptions use union semantics: a hook is selected when it belongs to any requested group. There is currently no equivalent selector for requiring a hook to belong to every requested group, so users must define an additional combined group for each needed intersection.Proposed behavior
Add a repeatable
--require-group <GROUP>option toprek run. A hook would satisfy this filter only when itsgroupscontains every value passed through--require-group.The filters should compose independently of argument order:
--no-groupwould continue to take precedence over inclusion filters.Configuration
This configuration has two hooks in each functional group, two hooks in each performance group, fast hooks assigned to
local, and slow hooks assigned toci.Usage
--require-groupfilters:$ prek run --all-files --require-group lint --require-group fastThis runs only
ty, which belongs to both required groups.--require-groupand--groupfilters:$ prek run --all-files --require-group format --require-group fast --group lint --group localThis runs only
ruff-format. It belongs to every required group and matches the includedlocalgroup. It does not need to matchlintbecause repeated--groupvalues use union semantics.--require-groupand--no-groupfilters:$ prek run --all-files --require-group lint --require-group slow --no-group format --no-group localThis runs only
mypy. It belongs to every required group and belongs to neither excluded group.--require-group,--group, and--no-groupfilters:$ prek run --all-files --require-group format --require-group slow --group lint --group ci --no-group fast --no-group localThis runs only
black. It belongs to every required group, matches the includedcigroup, and belongs to neither excluded group.Acceptance criteria
--require-group <GROUP>can be specified multiple times.--group,--require-group, and--no-groupcompose according to the selection model above.--require-groupactivates the same group selection mode as--groupand--no-group.--stagefurther restricts the matched hooks using the existing stage intersection behavior.--require-groupis not provided.References
groups+prek run --group/--no-group#1385prek run#2141