How to write Cursor rules that actually work

Put rules in .cursor/rules as small .mdc files, each with frontmatter setting description, globs or alwaysApply. Keep one always-on file with core conventions, attach framework rules by file pattern, and write concrete, checkable instructions with short code examples instead of general advice.
What are Cursor rules?
Cursor rules are persistent instructions that Cursor adds to the model’s context when it chats, edits or runs in agent mode. They carry the knowledge the model cannot infer: your conventions, preferred libraries, architecture boundaries and commands.
Modern project rules live in the .cursor/rules folder as .mdc files, a Markdown format with a small frontmatter header. The older single .cursorrules file in the repo root still works but is considered legacy.
Rules help most in codebases with strong local conventions: a design system, a particular data access layer, or testing patterns that differ from the framework defaults. Without rules, the model falls back to generic patterns from its training data.
They are also the cheapest way to scale good habits across a team. One well-written rule reaches every developer and every agent session, instead of being repeated in code review comments.
The limit is attention. Rules compete with the task, the open files and the conversation for the model’s focus, so fewer and sharper rules work better than a long list.
Which rule type should you use?
The frontmatter decides when a rule loads. Choosing the right trigger matters more than wording, because a rule that never loads cannot help and a rule that always loads costs context on every request.
Most teams need only two types in practice: one Always rule and several Auto Attached rules scoped by globs. Agent Requested and Manual rules are useful for occasional procedures, such as a release checklist or a migration template, that should not load on every request.
If you are unsure which type fits, start with Auto Attached and a narrow glob, then widen it only if the rule is missing where you need it.
| Rule type | Frontmatter | When it loads | Use it for |
|---|---|---|---|
| Always | alwaysApply: true | Every request in the project | Core stack, package manager, hard rules |
| Auto Attached | globs: pattern such as src/**/*.tsx | When matching files are in context | Framework or folder-specific conventions |
| Agent Requested | description set, no globs, alwaysApply false | When the model decides the description is relevant | Occasional workflows, such as writing migrations |
| Manual | No description, globs or alwaysApply | Only when you mention it with @ruleName | Rare procedures, templates |
How to set up rules step by step
- Create the folder: mkdir -p .cursor/rules at the project root (Cursor’s command palette also offers a New Cursor Rule command).
- Create a core file such as .cursor/rules/project.mdc with alwaysApply: true and five to fifteen lines about the stack and non-negotiables.
- Add file-scoped rules, for example react.mdc with globs: src/components/**/*.tsx for component conventions.
- Add a description to every non-always rule; for Agent Requested rules the description is what the model reads to decide.
- Include one short good example and, where useful, one bad example in each rule.
- Reference real files with @filename in a rule so the model can pull in a canonical example, such as a model component.
- Commit .cursor/rules so the whole team and every agent session get the same behaviour.
- Test a rule by asking for a task it covers in a fresh chat and checking whether the output follows it.
What does a good Cursor rule look like?
Good rules are specific, scoped and short. They name the tool, the path and the exact expected pattern, so the model and a human reviewer can both check compliance.
Short code snippets inside a rule are often more persuasive than prose. The model imitates examples closely, so a six-line snippet of the preferred pattern tends to beat a paragraph describing it.
State the reason behind a rule in one clause when it is not obvious, such as “because the API client handles retries”. A reason helps the model apply the rule sensibly to cases the rule did not list.
| Vague rule | Rule that works |
|---|---|
| Use best practices for React. | Components are function components with named exports; props types are declared as type Props above the component. |
| Handle errors properly. | Server functions return { ok: false, error } instead of throwing; UI shows error with the Toast component from src/ui/toast. |
| Write good tests. | Tests use Vitest and Testing Library; query by role, never by CSS class. |
| Keep the code clean. | No new dependencies without asking; prefer utilities in src/lib/utils.ts. |
How should you organize rules in a larger codebase?
- One always-on file for global facts; keep it short because it loads on every request.
- One rule per concern (testing, styling, data access, API routes) rather than one giant file.
- Nested .cursor/rules folders inside packages of a monorepo, scoped to those directories.
- User Rules in Cursor settings only for personal preferences, such as answer language or verbosity; never project facts.
- If the team also uses Claude Code or Codex, keep shared content in AGENTS.md and let Cursor rules focus on file-scoped details, to avoid three diverging copies.
Common mistakes with Cursor rules
- Pasting a huge community rules file you found online; most of it does not apply to your code and it drowns your real conventions.
- Marking every rule as alwaysApply, which burns context and weakens each individual rule.
- Globs that never match because of a wrong path or extension, so the rule silently never loads.
- Missing descriptions on Agent Requested rules, leaving the model no reason to fetch them.
- Instructions that contradict the existing code; the model often copies nearby code over the rule, so fix the code or the rule.
- Rules about things a linter or formatter can enforce, like semicolons; configure the tool instead.
- Never revisiting rules after a migration, so the agent keeps generating the old pattern.
How do you migrate from .cursorrules?
Reading how mature open-source projects write their rules is a quick calibration exercise. RepoLoot’s catalog flags repositories built with AI coding workflows, many of which ship their rule files alongside the code.
- Read the old file and split it into themes: global, per framework, per folder, workflows.
- Move global lines into an alwaysApply rule and the rest into scoped rules with globs or descriptions.
- Delete rules that duplicate linter settings or restate the obvious.
- Remove the .cursorrules file once the new rules behave correctly, so there is no conflicting second source.
How do Cursor rules relate to other instruction files?
Cursor rules are one of several instruction formats. Claude Code reads CLAUDE.md, many agents read AGENTS.md and GitHub Copilot reads .github/copilot-instructions.md. They solve the same problem with different loading mechanics.
What makes Cursor rules distinct is scoping. Globs and descriptions let you load a testing rule only when test files are involved, which keeps the always-loaded context small.
If your team uses more than one tool, decide which file owns each fact. A good split is global project facts in AGENTS.md, file-scoped conventions in Cursor rules, and a CI check that fails when the documented commands stop working.
How do you check whether a rule is working?
Treat rules like tests you run by hand. Open a fresh chat, ask for a task the rule covers, and compare the result against the rule line by line.
If the output ignores it, first confirm the rule was attached; Cursor shows which rules were applied to a request. Only then reword the rule, add an example or narrow its scope.
Keep a short list of prompts that exercise your most important rules and repeat them after large edits to the rules folder. This catches rules that were accidentally deleted, broken by a frontmatter typo or overridden by a newer, conflicting rule.
Frequently asked questions
- Is .cursorrules still supported?
- The root .cursorrules file still works in Cursor but is treated as legacy. Project rules in .cursor/rules as .mdc files are the recommended format because they support scoping by globs, descriptions for agent-requested loading and splitting rules into focused files. Migrate when you next touch your rules.
- How long should a Cursor rule be?
- Short. A focused rule of a few lines to a few dozen lines with one concrete example is usually enough. Long rules cost context each time they load and hide the important sentences. If a rule grows large, split it by concern or file pattern.
- Do Cursor rules apply to autocomplete?
- Rules are applied to the chat and agent features, where the model receives them as context. Inline tab completion works differently and does not follow your rule files in the same way. Put conventions that must hold everywhere into linters, formatters and type checks as well.
- Why is Cursor ignoring my rule?
- Check that it loads first: the glob must match the files in context, Agent Requested rules need a clear description, and Manual rules need an @mention. If it loads but is ignored, make it more specific, add an example, and check whether nearby code contradicts it.