Cursor Rules Examples: .mdc Files for Five Stacks
Five annotated Cursor rule files, for a Next.js app, a Python API, a monorepo package, writing tests and writing docs, each with the frontmatter for its rule type, plus when a plain AGENTS.md is the better choice and the lines that never belong in a rule.
8 min read
A good Cursor rule is short, specific and scoped: the commands the agent cannot guess, the conventions that differ from the defaults, and the few lines it must not cross, loaded only when they apply. Below are five realistic .mdc files, each using a different way of being loaded, with a note on why each line is there. Then AGENTS.md as the simpler alternative, and the lines that do not belong in any rule. Where rules live and how the four types work in depth is in Cursor rules for AI projects; this post is the gallery.
The frontmatter, in one table
Every project rule is an .mdc file in .cursor/rules. According to Cursor’s rules documentation (opens in a new tab), three frontmatter fields decide when it loads:
alwaysApply: true: in every chat.descriptionandglobsare ignored.alwaysApply: falsewithglobs: attached when a matching file is in context. Separate patterns with commas.alwaysApply: falsewith adescriptionand noglobs: the agent reads the description and pulls the rule in when relevant.alwaysApply: falsewith neither: loaded only when you mention it, for example@docs-style.
Example 1: a Next.js app (always apply)
--- alwaysApply: true --- # Shopfront (Next.js, App Router) - Package manager is pnpm. Never run npm or yarn; the lockfile is pnpm's. - Before saying you are done: `pnpm lint && pnpm typecheck && pnpm test`. - Server components by default. Add "use client" only for state, effects or browser APIs. - Data fetching goes through src/lib/api.ts. Never call fetch() inside a component. - Money is integer pence; format it only with formatPrice() in src/lib/money.ts. - Never edit src/generated/. Change the schema and run `pnpm codegen` instead.
- Always Apply because every line holds everywhere in this repository. Keep this file the shortest of your rules: it costs context in every chat.
- The package manager line prevents a second lockfile, the most common first mistake.
- The finish line is a command, not “test your changes”. The agent can run it and you can check that it did.
- Each convention is one the model would get wrong by default. Server components by default is a framework choice; integer pence is a team choice no linter catches.
- The generated-folder line says what to do instead. A bare “never” leaves the agent stuck or improvising.
Example 2: a Python API (auto-attached by globs)
--- globs: api/**/*.py, migrations/**/*.py alwaysApply: false --- # Orders API (FastAPI, SQLAlchemy 2, Pydantic v2) - Run: `uv run pytest`; one file: `uv run pytest tests/test_orders.py -k refund`. - Every endpoint validates input with a Pydantic model in api/schemas/. No raw dicts. - Errors are raised as ApiError(code, message). Never return a bare string or 500. - Database access goes through the repository classes in api/repos/, never the session directly. - Timestamps are timezone-aware UTC. - New endpoint? Copy the shape of @api/routes/orders.py. - Migrations: add, backfill, then drop in a later migration. Never change a column type in place.
- The globs keep these lines out of chats about the front end or the docs. A rule attached only when a matching file is in context costs nothing the rest of the time.
- The single-test command matters as much as the suite: it lets the agent check one change quickly.
- The
@reference points at a real route instead of pasting one in. Cursor’s guidance is to reference files rather than copy them, so the example cannot drift from the code. - Versions in the heading save the agent from mixing Pydantic v1 and v2 syntax, which look alike and fail differently.
Example 3: a package in a monorepo (auto-attached by globs)
--- globs: packages/ui/** alwaysApply: false --- # @acme/ui, the shared component library - Used by apps/web and apps/admin. A breaking change here breaks both. - Public API is what src/index.ts exports. Anything else may change freely. - Never import from apps/*. Packages depend on packages, not on apps. - Tests: `pnpm --filter @acme/ui test`. Stories: `pnpm --filter @acme/ui storybook`. - Changing a prop? Keep the old name working and mark it @deprecated in its JSDoc. - Colours and spacing come from tokens in src/tokens.ts, never raw values.
- The subfolder under
.cursor/rulesis only for your own order. Cursor identifies rules by full path, so two files with the same name in different folders both apply. - The first line tells the agent who depends on this package, which it cannot see from inside
packages/ui. - Commands are filtered to the package. “Run the tests” is ambiguous in a monorepo;
pnpm --filteris not. - The import rule protects the dependency direction. It is the kind of structural rule an agent breaks when a shortcut looks convenient.
Example 4: writing tests (agent-requested)
--- description: Use when writing, fixing or reviewing tests, or when a test fails. alwaysApply: false --- - Test behaviour through the public API, not private helpers. - One behaviour per test. Name it for the behaviour: "refund is rejected after 30 days". - Arrange, act, assert, in that order, with a blank line between them. - No sleeps. Use the fake clock in tests/support/clock.ts. - A failing test is information. Never change an assertion to make it pass without telling me why the old expectation was wrong. - Shared fixtures live in tests/fixtures/. Do not add real customer data to them.
- An agent-requested rule lives or dies by its description. Write it as a trigger, “use when”, not a title such as “Testing standards”. Cursor’s FAQ gives a missing description as the first reason such a rule is not applied.
- The assertion line is the most valuable in the file. The quickest way for an agent to make a red test green is to change what it expects.
- The clock line names the helper to use, so the agent does not invent a second one.
Example 5: writing docs (manual)
--- alwaysApply: false --- - British spelling. Second person. Short sentences. - Start each page with what the reader can do after reading it. - Every command in a code block must have been run; paste its real output. - Link to the reference page rather than repeating option lists. - Headings say what the section does: "Rotate a key", not "Key rotation". - Follow the layout of @docs/guides/_template.md.
- Manual because you write docs occasionally. Type
@docs-stylein the chat when you do; the rest of the time it costs nothing. - The code-block line is checkable: an example that was never run is the commonest fault in agent-written docs.
- Rules apply to the agent only. They do not affect Tab completion or Inline Edit, so a docs convention that must also hold for inline edits has to be visible in the template itself.
AGENTS.md as the alternative
If you do not need scoping, a plain Markdown AGENTS.md at the project root is simpler: no frontmatter, and other agents read it too. It follows the open AGENTS.md (opens in a new tab) format. Cursor also reads AGENTS.md files in subfolders, combines them with their parents, and lets the more specific one win. Cloud agents read it, and Cursor suggests a section for cloud-only setup; see Cursor cloud agents.
# Shopfront - pnpm only. Check with `pnpm lint && pnpm typecheck && pnpm test`. - Never edit src/generated/; run `pnpm codegen`. - API code is in api/ (see api/AGENTS.md for its commands).
Two notes. A root CLAUDE.md is always applied in Cursor too: Cursor’s rules help page (opens in a new tab) says it reads it the same way as AGENTS.md, whatever its frontmatter says. And a .cursorrules file at the root is legacy; the same page says to move its content into a new rule set to Always Apply. Sharing files between tools is covered in AGENTS.md examples and CLAUDE.md examples.
Lines that do not belong in a rule
- A copied style guide. Cursor’s docs say to use a linter instead; the agent already knows common conventions.
- Every command you know. The agent knows npm, git and pytest. List only the ones specific to your project.
- Edge cases that come up twice a year. Keep rules for patterns you hit often, and move rare procedures into a skill.
- Pasted code. Point at a canonical file with
@instead. - Vague virtues: “write clean, maintainable code”. Nothing checkable follows from it.
- Secrets, internal URLs with tokens, or personal data. Rules are committed and read by every assistant that opens the repository.
- Security you are relying on. A rule is guidance, and Cursor says AI guidance should not be your only security control. Anything that must never happen needs a permission behind it.
Keep each file under 500 lines, and add a rule when you see the same mistake twice, not before. As for “cursor rules examples github” collections: Cursor does not import rules from a repository on their own. To share a set across teams, package it as a plugin (opens in a new tab) and install it from a marketplace. Read any community rule before you commit it; it becomes an instruction to your agent.
Check that a rule loads
Test a new rule before you rely on it. Open Customize, then Rules, where Cursor lists every rule with its status. Then start a fresh chat, bring a matching file into context, and ask for something the rule should change, such as a new endpoint for the API rule. If the result ignores it, check the type first: a globs rule whose pattern does not match the file in context, or an agent-requested rule whose description never matches what you ask, will sit there unused. When the agent makes a mistake a rule should have prevented, edit the rule, not the chat, and commit it so the next session and the rest of the team get the fix.
The rule most sets leave out
All five examples describe the code. None says which task the agent is on, what counts as finished, or where it reports what it did. That belongs in one more Always Apply rule, pointing the agent at your task board over MCP: read the task first, record the plan, comment what changed and how it was checked, and leave Completed to a person. The full rule, written for a fenbs board, is in Cursor rules for AI projects. Things every assistant on the board should know, whatever editor it runs in, go in fenbs AI context rather than in one repository’s rules.
Related
Connect the board with the snippet on Connect Cursor. What each rule costs in the context window: context engineering in Cursor. Which modes read them: Cursor agent vs ask vs plan.