← All guides

How to write Cursor rules that actually work

The difference between rules that get followed and rules that get ignored.

Start with correct frontmatter

Every .mdc file needs a YAML frontmatter block. Without it, Cursor may silently ignore the entire file.

---
description: TypeScript error handling for API routes
globs:
  - "src/api/**/*.ts"
  - "src/routes/**/*.ts"
---

Three fields matter:

Common mistake: Setting alwaysApply: false with no globs. This creates a rule that only fires when manually referenced by name. If that's not what you want, add globs or set alwaysApply: true.

Be specific, not vague

The model already knows how to "write clean code." Telling it to do so wastes tokens and changes nothing.

❌ Vague

Write clean code.
Follow best practices.
Handle errors properly.
Use good naming.

✓ Specific

Wrap all route handlers in try-catch.
Return {error, code} on failure.
Prefix private methods with underscore.
Name booleans with is/has/should.

Show, don't tell

A code example is worth 50 tokens of explanation. The model follows patterns better than prose.

❌ Telling

When handling errors in API routes, make sure to catch all errors and return a structured JSON response with an error message and an appropriate HTTP status code.

✓ Showing

catch (error) {
  return Response.json(
    { error: error.message,
      code: "INTERNAL_ERROR" },
    { status: 500 }
  );
}

Use imperative language

Rules are commands, not suggestions. The model follows direct instructions better than hedged requests.

Skip "please," "try to," "consider," and "maybe." These waste tokens and weaken the instruction.

One concern per rule

A rule that covers TypeScript naming, React component structure, AND testing patterns is too broad. The model handles focused rules better.

Split by concern:

Say what to do, not just what to avoid

"Don't use var" tells the model what's wrong but not what's right. Always provide the alternative.

❌ Negation only

Don't use var.
Don't use any.
Avoid nested callbacks.

✓ With alternative

Use const instead of var. Use let only for reassignment.
Use specific types instead of any. Use unknown for truly unknown types.
Use async/await instead of nested callbacks.

Validate before committing

Run your rules through the linter to catch broken frontmatter, vague instructions, and other issues before they hit your project:

npx cursor-doctor scan

Or paste a single rule into the playground for instant feedback.

Related guides

Try the playground

Paste a rule and get instant feedback on frontmatter, structure, and prompt engineering.

Open Playground →