Skip to content

Rules Pipeline

A composition pipeline so every new project inherits a universal baseline plus optional stack-specific modules, and only overrides what is actually project-specific.

Composition order (highest priority last)

  1. Global baseline (global-baseline/*.mdc) — universal style, architecture, quality.
  2. Stack module(s) (stack-modules/<stack>/*.mdc) — backend / frontend / data / infra.
  3. Project overrides (project-overrides/<project>/*.mdc) — only what's truly local.

Cursor reads rules from .cursor/rules/. The bootstrap skill (/rules-bootstrap) generates a project's .cursor/rules/ directory by copying or symlinking the right slices in this order, so duplication is near zero.

Files

shared/rules/
├── global-baseline/                 # always applied
│   ├── 010-style.mdc
│   ├── 020-architecture.mdc
│   ├── 030-quality-and-tests.mdc
│   ├── 040-security-baseline.mdc
│   ├── 050-cursor-defaults.mdc
│   └── 060-commit-and-pr-discipline.mdc
├── stack-modules/                   # opt-in by stack
│   ├── backend/
│   │   └── 100-backend.mdc
│   ├── frontend/
│   │   └── 100-frontend.mdc
│   ├── data/
│   │   └── 100-data.mdc
│   └── infra/
│       └── 100-infra.mdc
├── project-overrides/               # per-project deltas
│   └── _example-project/
│       └── 200-overrides.mdc
└── bootstrap/
    ├── manifest.schema.json         # project rule manifest
    └── bootstrap-instructions.md    # what /rules-bootstrap does

Bootstrap skill

The rules-bootstrap skill (under .cursor/skills/rules-bootstrap/) is the operational entry point. Invoke it with /rules-bootstrap in a target project to compose its .cursor/rules/ directory.

Numbering convention

Rule files are prefixed with a 3-digit ordering number so Cursor evaluates them deterministically. 0xx for global, 1xx for stack, 2xx for project.

Drift gate

A project's .cursor/rules/ is generated, so it can drift from what its manifest declares. In tool-chest that is enforced rather than trusted:

make rules-sync    # render .cursor/rules/ from rules-manifest.yaml
make rules-check   # fail if the rendered directory has drifted

rules-check catches a symlink replaced by a hand-edited copy, a copy whose content no longer matches its source, and any .mdc that no manifest layer declares. It runs from the repo's pre-commit hook via make check. Prefer rendered.mode: symlink — identical content on both sides means drift can be made impossible rather than merely detected.

Success gate

Two distinct projects bootstrap their .cursor/rules/ from this pipeline, sharing ≥ 80% of rule text by reuse, with each holding ≤ 20% project-specific rules.