# Cursor rules

> Most Cursor rules do nothing, because the frontmatter decides when a rule applies and a rule with the wrong extension is ignored entirely. Four rule types, one directory, and the MCP servers worth adding on top. $20/mo, and the rules themselves are free.

Source: https://aistack.sh/stack/cursor-rules
Category: Code · Agent setup
Level: Intermediate
Last verified by a human: 2026-09-04

## The tools

### Cursor — The editor

- Pricing: Free Hobby · $20/mo Pro · $60/mo Pro+ · $200/mo Ultra · $40/seat Business
- Site: https://cursor.com
- Why this one: Rules are a Cursor feature, not an add-on. They live in the repo as files, so they are version controlled and arrive with a clone.
- Swap in instead: Claude Code, Windsurf
- More: https://aistack.sh/tool/cursor

### Context7 — Live documentation

- Pricing: Free
- Site: https://context7.com
- Why this one: Rules tell the agent how you work; this tells it how a library works today. Together they cover the two things it otherwise guesses.
- More: https://aistack.sh/tool/context7

### Supabase MCP — Database access

- Pricing: Free
- Site: https://supabase.com/docs/guides/getting-started/mcp
- Why this one: A rule can say 'always check the schema first'. This is what makes that instruction possible to follow.
- More: https://aistack.sh/tool/supabase-mcp

### CodeRabbit — Review

- Pricing: Free for OSS · $30/mo per dev Essentials ($24 billed annually) · $60/mo Team · $90/mo Advanced
- Site: https://coderabbit.link/aistacksh
- Why this one: Rules shape what gets written. Nothing in the editor checks whether the result was right, and the agent that wrote it is the wrong reviewer.
- More: https://aistack.sh/tool/coderabbit

## Monthly cost

### $20/mo — Solo, open source (small)

- Cursor: $20
- Context7: $0
- Supabase MCP: $0
- CodeRabbit: $0 OSS

### $50/mo — Solo, private repos (medium)

- Cursor: $20
- Context7: $0
- Supabase MCP: $0
- CodeRabbit: $30

### $210/mo — Team of 3, business seats (heavy)

- Cursor: $120 Business ×3
- Context7: $0
- Supabase MCP: $0
- CodeRabbit: $90

## Workflow

### 1. Put the rule in the right place, with the right extension (Cursor)

Project rules live in .cursor/rules as .mdc files and are version controlled, so they arrive with a clone. The extension matters more than it looks: a plain .md file in that directory is ignored by the rules system, because it has no frontmatter to carry description, globs and alwaysApply. That is the single most common reason a rule appears to do nothing.

**Prompt: Create one**

```
mkdir -p .cursor/rules

# .mdc, not .md. A .md file here is silently ignored.
touch .cursor/rules/conventions.mdc

# Or let Cursor scaffold it: type /create-rule in Agent and
# describe what you want.
```

### 2. Pick the type, because the frontmatter is the trigger (Cursor)

There are four types and the frontmatter alone decides which one you get. alwaysApply: true applies the rule to every chat session. A description with alwaysApply: false leaves it to the agent to decide when it is relevant. A globs pattern with alwaysApply: false fires only when a matching file is in play. Nothing at all means the rule only runs when you @-mention it. Most rules people write want the third and get the first.

**Prompt: Always: conventions that are never wrong to apply**

```
---
alwaysApply: true
---

- The middleware file is proxy.ts, not middleware.ts.
- Content lives under content/, not lib/. The lib/*.ts files are thin loaders.
- Do not add a dependency without saying why in the PR description.
```

**Prompt: Scoped: only when the agent touches these files**

```
---
globs: ["**/*.test.ts", "**/*.spec.ts"]
alwaysApply: false
---

- Tests use the real database against a scratch schema, not mocks.
- One assertion per test. If a test needs three, it is three tests.
- Never assert on a snapshot of generated output.
```

**Prompt: Agent-decided: describe when it matters**

```
---
description: Use when writing or changing a database migration.
alwaysApply: false
---

- Read the live schema before writing SQL. Do not infer it from the types.
- Every migration is additive. No destructive change without a separate PR.
- RLS is on. A new table with no policy is invisible to the client, which
  is the intended default, not a bug to work around.
```

### 3. Add MCP servers for what rules cannot supply (Context7)

A rule can tell the agent to check the current docs before writing code. Whether it can actually do that is a separate question, and the answer is MCP. This is the split worth internalising: rules are instructions, servers are capabilities, and an instruction to do something impossible just gets ignored.

### 4. Review outside the editor (CodeRabbit)

Rules shape what gets written and nothing in the editor checks the result. Open the pull request and let something read it cold, without the reasoning that produced it. Feed the comments back into the session and let the agent apply the fixes.

## What it produced

**What a rule that works looks like**

The rules that earn their place are the ones that encode a thing the agent gets wrong repeatedly, not the ones that describe your project. 'The middleware file is proxy.ts, not middleware.ts' prevents a specific failure every time it fires. 'This is a Next.js app with Tailwind' prevents nothing: the agent can read package.json. A useful test is whether you can name the last time the rule saved you. If you cannot, delete it.

## Pitfalls

- **Using .md instead of .mdc** — A plain .md file in .cursor/rules is ignored by the rules system, because it carries no frontmatter to specify description, globs or alwaysApply. Nothing warns you. The rule sits in the repo looking correct and never fires.
- **Setting alwaysApply on everything** — Every always-on rule is in the context of every request, including the ones it has nothing to do with. Test conventions loaded while writing a migration are noise that crowds out what matters. Scope with globs unless the rule really is never wrong to apply.
- **Writing a description that is a title** — For agent-decided rules, the description is the trigger. 'Database conventions' tells the agent nothing about when to reach for it. 'Use when writing or changing a database migration' does. Write it as a condition, not a label.
- **Describing the project instead of the failures** — Rules that restate what package.json already says cost context and prevent nothing. The agent can read your dependencies. It cannot know that your middleware lives under a name the framework does not expect.
- **Expecting rules to supply capability** — A rule saying 'check the current documentation' cannot make the agent able to. That needs an MCP server. Instructions and capabilities are different things, and an instruction to do something impossible is just ignored.

---

Curated by omar on aistack.sh. Last updated 2026-09-04.
