Rules on Rules on Rules
Rules on rules on rules—stacks on stacks on stacks—but for your AI. It's the slightly silly phrase that ends up solving a very real problem: keeping AI output consistent across a codebase.
Subtitle: A meta workflow for writing Cursor Rules that stays clean, predictable, and team-friendly.
Why Cursor Rules matter
Cursor Rules are how you stop the "new prompt, new personality" drift that happens when every developer asks the assistant a little differently. Rules turn implicit expectations into explicit guardrails.
One-off prompting is great for exploration. But as soon as a repo matters to a team, you need project-level defaults:
- Consistent naming and file structure
- Predictable changes across similar files
- Shared constraints (security, licensing, conventions)
Rules make output predictable because they move decisions from "this chat" to "this repo."
The meta trick: a rule for writing rules
The easiest way to keep rules from spiraling is to create a dedicated rule that
only applies while editing .cursor/. Think of it as a lint rule for your AI.
The idea: whenever you're editing a rule file, a "rule-writing rule" applies automatically. That rule enforces the rule format, naming, and scope so your rules stay consistent.
This prevents:
- Messy rule sprawl (random structures, random names)
- Inconsistent naming (kebab-case here, camelCase there)
- Missing globs or incorrect
alwaysApplyusage - Vague instructions that can't be enforced
If you do nothing else, do this. It's a 10-minute setup that saves you hours.
A real example rule
Here is the actual rule I use for writing rules. It's more comprehensive than a minimal example, but that's the point—it captures everything needed to keep rules consistent across a team.
.cursor/rules/cursor-rule-authoring/RULE.md
---
description: "How to format and structure Cursor Rules (.cursor/rules/*/RULE.md), including naming, placement, metadata, and best practices. Applies when editing anything in .cursor/."
globs:
- ".cursor/**"
alwaysApply: false
---
# Cursor Rules Authoring Standard (applies to .cursor/**)
## Goal
When writing or modifying anything under `.cursor/` (especially `.cursor/rules/**`), follow **Cursor's current rule system** conventions so rules are consistent, discoverable, and reliably applied.
## Where rules live
- **Project rules** live in: `.cursor/rules/`
- **Each rule is a folder** under `.cursor/rules/`.
- Each rule folder contains a **main rule file** named: `RULE.md`
- A rule folder may also contain **additional files** (templates, scripts, prompts) that the rule references.
## Folder naming (rule identity)
- **Folder name = rule name** (this is what you @-mention when using manual rules).
- Use **kebab-case** and make it descriptive:
- ✅ `api-style`
- ✅ `react-component-standards`
- ✅ `db-migration-workflow`
- ❌ `Rules1`
- ❌ `myRule`
- One rule folder should represent **one coherent purpose**.
## Required file: RULE.md
Every rule folder MUST contain:
- `.cursor/rules/<rule-name>/RULE.md`
### RULE.md structure
1. **YAML frontmatter** at the top (between `---` lines)
2. **Markdown body** with actionable instructions
#### Frontmatter fields (core)
Use these fields as the canonical baseline:
- `description` (string): clear, specific description used for relevance.
- `globs` (list of strings): file patterns that scope the rule to specific files/areas.
- `alwaysApply` (boolean): whether the rule is injected into every chat session.
> Cursor's UI "rule type" maps onto these properties (e.g., always apply, intelligent apply by description, apply by glob, manual @-mention).
### Glob conventions
- Prefer **narrow, explicit globs**.
- Typical examples:
- Frontend: `src/**/*.tsx`
- Backend: `server/**/*.ts`
- Docs: `docs/**/*.md`
- Tooling: `.github/**/*.yml`
- Avoid overly broad patterns unless you truly want wide coverage.
## How rules should be written (content requirements)
Rules MUST be:
- **Actionable**: tell the agent exactly what to do.
- **Testable**: easy to verify compliance in code review.
- **Concrete**: include examples, templates, or references when helpful.
- **Scoped**: avoid turning one rule into "everything about the project".
### Do
- Use headings and short bullet lists.
- Prefer "MUST / SHOULD / MAY" language for clarity.
- Include "when to apply" guidance in the text if it's not obvious from globs.
- Reference existing project files/templates when appropriate (e.g., "follow @path/to/template").
### Don't
- Don't write vague guidance like "write clean code".
- Don't put unrelated policies into one rule.
- Don't duplicate the same rule across many folders (create one shared rule instead).
## Rule size & composition
- Keep rules **focused** and **reasonably sized**.
- If a rule becomes large, split it into multiple composable rules (e.g., `typescript-style`, `react-style`, `testing-standards`).
## Choosing the right "application mode"
When creating a rule, choose ONE primary mode and reflect it in frontmatter:
1) Always Apply (global project baseline)
- Use when: it's universally relevant (formatting, repo-wide conventions)
- Frontmatter:
- `alwaysApply: true`
- `globs:` optional or omitted
2) Apply to Specific Files (recommended for most rules)
- Use when: rule is about a subset (frontend/backend/docs)
- Frontmatter:
- `alwaysApply: false`
- `globs: [ ... ]`
3) Apply Intelligently (relevance by description)
- Use when: hard to express via globs; keep description very crisp
- Frontmatter:
- `alwaysApply: false`
- `globs:` optional/omitted
- Content must define clear triggers ("When working on X, do Y…")
4) Apply Manually
- Use when: it's a workflow you only want sometimes
- Ensure the folder name is memorable; instructions should start with a short "How to invoke" section:
- "Invoke with: @<rule-name>"
## Required template for new rules
When creating a new rule folder, start from:
---
description: "<1 sentence. what it enforces and where/when>"
globs:
- "<patterns this rule applies to>"
alwaysApply: false
---
# <Rule Title>
## Intent
## Scope
## Rules (MUST/SHOULD/MAY)
## Examples
## References (optional)
## .cursor directory hygiene
- Keep `.cursor/rules/` version-controlled and reviewed like code.
- Avoid placing unrelated project docs inside `.cursor/` unless they're directly tied to Cursor behavior.
- Prefer small, targeted rules over monolithic ones.
## Validation checklist (before committing a rule)
- [ ] Folder name is kebab-case and purpose-specific
- [ ] RULE.md exists and has YAML frontmatter
- [ ] `description` is specific and unambiguous
- [ ] `globs` (if used) are correct and not overly broad
- [ ] Instructions are actionable and include examples
- [ ] No conflicting duplicate rules elsewhere
Yes, it's longer than a minimal example—but that's the point. This rule covers the full lifecycle: where rules live, how to name them, how to structure content, which application mode to use, and how to validate before committing. It's the single source of truth for anyone writing rules in the repo.
Rule types and when to use them
There are three common rule modes. Use each intentionally:
- Always Apply: universal constraints (licensing, security, standards).
- Globs: scoped to specific paths or file types.
- Manual: rare, opt-in rules for special tasks.
If you're unsure, start with globs. They scale better and keep unrelated tasks from inheriting rules they shouldn't.
Best practices that keep rules sane
These are the patterns that keep your rule set readable:
- Kebab-case rule names:
data-architecture,rule-authoring,frontend. - One idea per rule: small, composable, easy to swap.
- Prefer globs over global: reduce accidental scope creep.
- Write enforcement language: "must", "never", "only when".
- Add quick examples: especially when a rule is procedural.
Rules are for consistency, not creativity. Be direct and concrete.
Common mistakes (and how to fix them)
Avoid these and your rule set stays useful:
- Too vague: "write clean code" gives no enforcement signal.
- Too broad:
**/*makes everything inherit everything. - Duplication: the same policy in multiple rules means drift later.
- No examples: complex workflows need a sample to anchor behavior.
- Mega-rules: once a rule becomes a mini handbook, it stops being used.
When in doubt, split the rule and add a glob.
Starter kit: checklist + template
Checklist (keep it short):
- [ ] Rule folder uses kebab-case
- [ ] Front matter includes description, globs, alwaysApply
- [ ] Rule has a single purpose
- [ ] Scope is as narrow as possible
- [ ] Includes at least one concrete example if procedural
Starter template:
.cursor/rules/<rule-name>/RULE.md
---
description: "What this rule does in one sentence"
globs: ["path/**", "*.ext"]
alwaysApply: false
---
- Must: ...
- Never: ...
- Only when: ...
- Example:
- ...
Quick FAQ
Will this slow me down?
No. It speeds you up because you stop re-explaining the same standards.
Do I need one per repo?
Yes. Rules are repository context. Even similar repos have different
conventions.
What if we already have a mess?
Start by adding the rule-writing rule, then refactor rules incrementally.
Debugging Rule Application
Rules only work if they're in context. When behavior doesn't match your rules, debug systematically.
Check What's Injected
Ask the agent directly:
"List the rule documents you received in the <rules> block this turn, with their file paths."
Verify Rule Source
"Quote the specific rule text you're following right now (with file path)."
Understand Priority
"Which instruction has highest priority for this decision: system, developer, or user?"
Priority hierarchy (highest to lowest):
- System instructions — Cursor's built-in guidance
- Developer rules — Your
.cursor/rules/ - User instructions — What you say in chat
- Repo docs — README, inline comments
Force Loading
If a critical rule isn't being applied:
"Read .cursor/rules/[rule-name]/RULE.md and summarize the constraints you must follow from it."
This explicitly loads the rule into context.
Common Reasons Rules Don't Apply
| Symptom | Likely Cause |
|---|---|
| Rule completely ignored | Not injected (wrong scope, glob doesn't match) |
| Rule partially followed | Higher-priority instruction overrides part of it |
| Rule applied inconsistently | Conditional rule, condition sometimes doesn't match |
| Rule acknowledged but not actionable | Tool/sandbox constraints prevent execution |
Wrap-up: stack it, then ship
Rules on rules on rules isn't just a joke. It's the shortest path to stable, predictable AI output in a team codebase. Add the rule-writing rule, keep rules small and scoped, and you'll stop fighting drift.
Stack the rules. Then let your AI do the boring stuff, consistently.