A Cursor rule that never fires is indistinguishable from a rule you never wrote. There is no warning, no log line, no UI flag. You find out when the agent, for the fifth time, generates API errors as raw strings despite your beautifully written rule saying not to. This article is about the activation mechanics that decide whether a rule loads at all.
The frontmatter
Every .mdc file in .cursor/rules/ has YAML frontmatter with three fields:
---
description: "Error handling for payment API routes"
globs: ["src/api/payments/**/*.ts"]
alwaysApply: false
---
Your rule content here.
| Field | Controls | Used by |
|---|---|---|
description |
What the model sees when deciding whether the rule is relevant | Auto Agent and Agent Requested modes |
globs |
Which file paths trigger inclusion | Auto Agent; matches against files in context |
alwaysApply |
Force-load the rule into every request | Overrides everything when true
|
The four activation modes
Cursor's UI presents four "rule types". They map onto the frontmatter like this:
| UI mode | Frontmatter | When it loads |
|---|---|---|
| Always | alwaysApply: true |
Every request, everywhere. Costs tokens always |
| Auto Agent | globs set, alwaysApply: false
|
When files matching the globs appear in the agent's context |
| Agent Requested | description set, no globs, alwaysApply: false
|
The model reads all rule descriptions and decides to pull the rule in |
| Manual |
@ruleName mention |
Only when explicitly invoked in chat |
Practical guidance:
- Always is for rules that are genuinely universal. Keep the count low; every Always rule spends your instruction budget on every request.
- Auto Agent (globs) is the workhorse. Scope by path and the rule loads exactly when relevant code is in play. This is how you afford specific knowledge without bloating always-on config.
- Agent Requested is worth using for cross-cutting rules that do not map to a path: "when writing database migrations.." applies to files whose names vary. The risk is that the model's relevance judgment is a judgment; a weak description means rare firing. Write descriptions as retrieval queries, not labels: "Applying when writing or modifying database migrations, schema files, or seed data" beats "Database stuff".
- Manual is for heavyweight references you explicitly want: style guides, long API conventions.
The five silent failure modes
1. Broken glob. globs: "src/api/**/*.ts" when your API lives in app/api/ matches nothing. The rule never loads. Nothing tells you. This is the most common failure by a wide margin, and it survives code review because the glob looks plausible.
2. Single-string glob quirks. Cursor accepts a single string or an array of strings. globs: "src/a/**/*.ts,src/b/**/*.ts" (comma-joined in one string) does not do what you hope. Use an array.
3. Description-only rules with bad descriptions. In Agent Requested mode the description is the entire retrieval surface. "Coding standards" fires on vibes. Include the trigger vocabulary the model needs to match against the task at hand.
4. alwaysApply sprawl. Every rule someone marks "important" becomes alwaysApply: true, and suddenly you are back to a 900-line implicit CLAUDE.md, except worse because it is twelve files and nobody has seen the total.
5. Filewatcher drift. Globs are matched against your repo as it exists today. Move src/api to apps/web/src/api in a restructure and every rule scoped to the old path dies on the same day, quietly. Nobody re-audits globs during a restructure.
Auditing: make firing observable
Because Cursor will not warn you, test the globs yourself. The essence of an audit is: does each glob match at least one real file, and roughly how many?
# rules_audit.py -- check every .mdc glob against the repo
import pathlib, re, sys
broken = 0
for mdc in pathlib.Path(".cursor/rules").glob("*.mdc"):
text = mdc.read_text()
m = re.search(r'globs:\s*\[?(.+?)\]?
', text)
if not m:
print(f"{mdc.name}: no globs found")
continue
# hand the glob list to pathspec/minimatch of your choice here
..
If you do not want to maintain that script: our validation harness, which ships with AgentConfig Studio, parses every rule's frontmatter (catching malformed YAML and missing activation modes), verifies required files and line budgets, and scans for placeholder rot. Every kit passes it before release, so the rule you install is the rule that loads.
Want to start from a working baseline instead? The free Next.js sample kit is MIT licensed: take it, break it, keep it.
Top comments (0)