The apply block connects rules to the parts of your codebase where they should be enforced. Without an apply entry, a rule is defined but never executed.


Structure

Each entry in apply is a named group that maps one or more rules to one or more modules:

apply:
  - name: domain-layer        # A label for this group (used in output)
    rules:                    # Rules to enforce in this group
      - attribute-matches-type
      - bool-method-prefix
    modules: contexts.*.domain  # Module path pattern to match

Fields

Field Required Description
name Yes Human-readable label for this application group
rules Yes List of rule names to enforce (must be defined in the rules block)
modules Yes A module path pattern that selects which files to check

Module Patterns

Module paths use Python's dotted notation — the same way you would import them. For example, src/domain/service.py becomes src.domain.service.

Exact Match

To target a single module, write its full dotted path:

modules: myapp.core.utils

This matches only the file myapp/core/utils.py.

* — Single Level

* matches exactly one segment in a dotted module path. It cannot match across dots.

modules: contexts.*.domain

This matches:

  • contexts.boards.domain
  • contexts.auth.domain
  • contexts.payments.domain

But not:

  • contexts.domain (missing the middle segment)
  • contexts.boards.sub.domain (too many levels between contexts and domain)

Example:

apply:
  - name: domain-layer
    rules: [attribute-matches-type]
    modules: contexts.*.domain

** — One or More Levels

** matches one or more segments. Use it to select all modules under a path, regardless of depth.

modules: contexts.**.domain

This matches:

  • contexts.boards.domain
  • contexts.boards.sub.domain
  • contexts.a.b.c.domain

Example — apply a rule to the entire codebase:

apply:
  - name: all
    rules: [bool-method-prefix]
    modules: "**"

The "**" pattern matches every module in the project. Use quotes to avoid YAML parsing issues.

Example — apply rules to all modules under a sub-package:

apply:
  - name: services
    rules: [function-snake-case]
    modules: myapp.services.**

Named Capture ({name})

{name} captures a single path segment (equivalent to *) and makes the captured value available for back-referencing within the same pattern.

modules: contexts.{context}.domain

This behaves like contexts.*.domain but the captured value (e.g. boards) is bound to the name context.

Example:

apply:
  - name: domain-isolation
    rules: [attribute-matches-type]
    modules: contexts.{context}.domain

Every module matching contexts.<anything>.domain is selected, and the middle segment is captured as context. This can be used in rule logic that references the captured value, enabling context-aware enforcement.


Multiple Apply Groups

You can define multiple apply groups to apply different rules to different parts of your codebase:

apply:
  - name: domain-layer
    rules:
      - attribute-matches-type
      - bool-method-prefix
      - domain-module-naming
      - constant-upper-case
    modules: contexts.*.domain

  - name: global-exceptions
    rules: [exception-naming]
    modules: "**"

Here, the domain-specific rules are enforced only in contexts.*.domain, while exception-naming is enforced everywhere. A single module can be matched by multiple groups — all matching rules will be applied.


Summary

Concept Syntax Description
apply block name, rules, modules Connects rules to specific module paths
Exact match myapp.core.utils Matches a single specific module
Single-level wildcard * Matches exactly one level in a dotted module path
Multi-level wildcard ** Matches one or more levels in a dotted module path
Named capture {name} Captures a single level for back-referencing
Multiple groups multiple apply entries Different rules for different parts of the codebase