
Cursor rules for production teams live in a shared .cursor/rules/ directory, get versioned in Git alongside the code, and encode three things every teammate (human or AI) must follow: security guardrails (never write secrets, never auto-commit), test-first discipline (write or update tests before shipping), and stack conventions (the framework, the linter, the file layout). A solo .cursorrules file is fine for one developer; production teams need a directory of small, scoped MDC files reviewed in PRs.
The shift from solo to team is where most engineering orgs trip. One person's prompt preferences turn into another person's mystery bugs. A junior pushes a refactor that uses the wrong ORM because Cursor's default suggestion didn't match the team's actual stack. A senior wires up a new service and Cursor cheerfully invents an AWS_ACCESS_KEY_ID literal in a config file. Both problems disappear when the team agrees on the rules and ships them as code.
This guide is the production-team version of the basics. If you want a primer on Cursor rules syntax and the older .cursorrules file, the sibling Cursor rules complete guide covers that ground. Here we focus on what changes when 4-20 engineers (and a few AI agents) share the same editor.
A single developer's .cursorrules file lives in their head as much as in the repo. They wrote it. They remember what each line means. When a new engineer joins, none of that context transfers.
Three concrete failure modes we see in production teams:
The fix is process, not tooling. Treat rules as code. Review them. Version them. Onboard against them.
Cursor supports two formats: the legacy single .cursorrules file (still works, deprecated) and the newer .cursor/rules/ directory of MDC (Markdown with YAML frontmatter) files. Production teams should use the directory format. It scales, supports per-glob rule scoping, and reads like code review fodder instead of a wall of text.
A canonical layout for a Next.js + TypeScript + Postgres team:
.cursor/
rules/
00-team-baseline.mdc # always-on, applies everywhere
01-security.mdc # always-on, security guardrails
02-typescript.mdc # auto-attached to *.ts, *.tsx
03-react-components.mdc # auto-attached to components/**
04-api-routes.mdc # auto-attached to app/api/**
05-database.mdc # auto-attached to db/**, prisma/**
06-testing.mdc # auto-attached to *.test.ts, *.spec.ts
99-style.mdc # agent-requested, for formatting passes
Each file is ≤500 lines and answers one question. The numeric prefix is a load order convention so reviewers know which rules take precedence when there's overlap.
Here's a minimal 01-security.mdc that every team should ship on day one:
---
description: Security guardrails. Always applied.
alwaysApply: true
---
# Security rules (non-negotiable)
- NEVER write API keys, tokens, passwords, or database URLs as
literal strings in any file. Always read from `process.env.*`.
- NEVER commit `.env`, `.env.local`, or any file in `secrets/`.
These are in `.gitignore` for a reason.
- NEVER run `git commit` or `git push` automatically. The user
reviews every diff before commit. Stage changes, suggest a
message, then stop.
- NEVER `rm -rf` outside `node_modules/`, `.next/`, or `dist/`.
- When unsure if an operation is destructive, ask first.
Five rules, ten lines of body, applies to every file the agent touches. This is the floor.
There's no single right answer. Below are the four patterns we see in production, with honest trade-offs.
| Approach | Setup cost | Scales to | Best for | Trade-off |
|---|---|---|---|---|
Legacy .cursorrules only | 10 min | 1-3 devs | Solo founders, small consultancies | One file becomes unreadable past 200 lines |
Single .cursor/rules/baseline.mdc | 30 min | 1-5 devs | Early-stage startups, MVPs | Still monolithic; no per-glob targeting |
Modular .cursor/rules/ directory | 2-4 hours | 5-50 devs | Most production teams | Requires rule-review process in PRs |
| Modular + per-team subdirectories | 1-2 days | 50+ devs | Platform teams, large monorepos | Coordination overhead; needs an owner |
If you're below 5 engineers, the second row is fine. Between 5 and 50, the third row is the sweet spot. Above 50, you're running a platform-engineering function and the rules are part of your DX charter.
These are the rules that show up in nearly every mature .cursor/rules/ directory we audit.
Covered above. The single highest-value rule. Without it, Cursor's default behavior is to make up plausible-looking config and inline it. Once. In a Dockerfile. That gets pushed.
Cursor's agent mode can run terminal commands. By default it will happily git add -A && git commit -m "WIP" if you ask it to "save your progress." For a production team this is wrong. The diff must hit a human's eyes before it lands. Add to your security rule:
- Stage and diff. Never commit. Never push. Never rebase.
Test-first rules turn Cursor from a feature-shipper into a feature-and-test-shipper. Example for a TypeScript team:
---
description: Testing discipline for TypeScript code.
globs: ["**/*.ts", "**/*.tsx"]
---
# Testing rules
- Every new function in `src/` has a colocated `*.test.ts` file.
- Every bug fix starts with a failing test that reproduces it.
- Run `pnpm test --filter=<changed-package>` before declaring
a task complete. Paste the output in the chat.
- If a test fails, fix the code, not the test. Only update the
test if the behavior change is intentional and named in the PR.
The "paste the output" line is load-bearing. It forces Cursor to actually run the tests instead of claiming it did. We've watched a paid Senior engineer skip this and ship a regression; we've never seen them skip it twice.
Cursor's training data biases toward whatever was on GitHub in 2024. If your stack is Fastify, Drizzle, and SolidJS, the model's first instinct is Express, Prisma, and React. A short rule fixes this:
---
description: Stack conventions. Always applied.
alwaysApply: true
---
# Stack
- Backend: Fastify 4, Drizzle ORM, Postgres 16, Zod validation.
- Frontend: SolidJS, Tailwind v4, Vite.
- Tests: Vitest. NEVER Jest.
- Package manager: pnpm. NEVER npm or yarn.
- Node: 20 LTS.
- When suggesting code, match these. If the user asks for
Express or Prisma, ask "are you sure?" before scaffolding.
The most common Cursor anti-pattern in a team setting: agent writes a new formatDate() helper when there's already one in src/lib/dates.ts. The fix is to point Cursor at the existing module:
- Before writing utility code, check `src/lib/` for an existing
helper. Common modules: `dates`, `currency`, `strings`,
`errors`, `logger`, `db`, `auth`.
- If you write a new helper, add it under `src/lib/` with a
test and a one-line JSDoc.
For larger codebases, MDC supports @file references so a rule can pin a specific file as required context. Use this for your errors.ts and logger.ts. The agent will read them before writing anything that touches error handling or logging.
Cursor will happily compose a PR description. Without a rule, it composes whatever it feels like. With a rule, it composes yours:
---
description: PR description format.
globs: ["**/*"]
---
# PR descriptions
When asked to draft a PR description, use this template exactly:
## What
1-2 sentences.
## Why
Link the issue, ticket, or Linear card.
## How to test
Bullet list of manual steps OR the test command to run.
## Risk
LOW / MED / HIGH plus one sentence.
That single rule eliminates the "what does this PR do?" Slack thread for half your team.
The under-appreciated use of a .cursor/rules/ directory: it doubles as your engineering handbook. A new hire reads 00-team-baseline.mdc through 06-testing.mdc on day one and knows the stack, the conventions, the security floor, and the testing bar. No 40-page Notion doc, no two-week shadowing period.
We work with a 12-engineer fintech team that cut their onboarding from "productive in 3 weeks" to "first merged PR in 4 days" by treating their rules directory as the source of truth. New hires were told: read the rules, then have Cursor scaffold a small feature. The PR review caught the gaps in the rules, which got merged back in. The rules improved. The next hire onboarded faster.
This is also where Cadence's hiring model lines up well. Every engineer on Cadence is AI-native by default, vetted on Cursor, Claude Code, and GitHub Copilot fluency in a voice interview before they unlock bookings. They show up able to read a rules directory and ship inside it. The team doesn't have to teach the Cursor part; the rules teach the codebase part.
If you're booking through Cadence, send the rules directory in the booking spec. Mid-tier engineers (Mid, $1,000/week) read it on day one and ship inside it on day two. Median time to first commit across the platform is 27 hours; a clear rules directory takes that down further.
We've watched three different teams discover a secret in their git history because Cursor wrote it during a "set up env vars" task. In each case the engineer didn't review the diff carefully (the file looked right at a glance). In each case the rule that would have prevented it is a one-liner.
A non-negotiable security rule should:
alwaysApply: true, not auto-attached.NEVER in caps for the things that must not happen. Cursor's compliance rate jumps measurably when the rule uses ALL-CAPS for hard prohibitions.For more on safe agent workflows, see our piece on how to use Cursor's agent mode in production. The TL;DR: agent mode is powerful and dangerous; the rules are the guardrail.
Rules are code. Treat them like code.
alwaysApply: true rules; one for scoped ones.alwaysApply: true content.A surprising number of teams skip versioning because "they're just prompts." They're not. They're the spec the agent codes against. If the spec drifts, the code drifts with it.
For the bigger picture on this discipline, see our AI-assisted refactoring playbook, which covers prompt-as-spec rigor in detail. The same principle applies: an artifact reviewed by humans is an artifact you can trust.
You don't need to write all of this from scratch. Several open libraries publish opinionated rule packs:
.cursor/rules packs by framework. Searchable by stack..cursorrules files; useful for the initial draft.Pick a starter pack matching your stack, prune the rules that don't apply, add your security baseline, ship it. You'll iterate from there.
If your team has no rules directory yet, the 90-minute starter:
.cursor/rules/ and add the security file from this post.If your team already has rules but they've drifted, do the audit:
still true / stale / unclear.stale ones in a single PR.If you're booking an engineer to ship a feature this week, attach the rules directory to the booking spec. It's the single highest-signal context document you have. Or decide whether a feature is worth building before you book, then book against the answer.
For more on what AI-native engineering looks like in practice (and why rules are central to it), see the AI-native engineering ROI piece, which puts numbers on the productivity gap between teams that use Cursor with rules and teams that use it without.
Want an AI-native engineer who reads your rules directory and ships inside it from day one? Every engineer on Cadence is vetted on Cursor, Claude Code, and Copilot fluency before they unlock bookings. 48-hour trial, weekly billing, replace any week. Get a Build / Buy / Book recommendation for your next feature.
.cursorrules and .cursor/rules/?.cursorrules is the legacy single-file format; it still works but is deprecated. .cursor/rules/ is the directory format using MDC (Markdown with YAML frontmatter) files. Production teams should use the directory format because it supports per-glob scoping, scales past a few hundred lines, and reads like code review fodder.
User Rules are set per-developer in Cursor's settings and apply globally across all projects. Workspace rules in .cursor/rules/ are project-scoped and shared via Git. User Rules can override or conflict with workspace rules silently. The fix is a team agreement: User Rules are for personal preferences (commenting style, verbosity), workspace rules are for team conventions (stack, security, testing). Document this in your 00-team-baseline.mdc.
.cursor/rules/ to Git?Yes. The entire point of team rules is that they're shared and versioned. Commit the whole directory. Review changes in PRs. The only files that should be gitignored are personal editor settings (like .cursor/settings.json if you use it for keyboard shortcuts).
Ship an alwaysApply: true rule that says NEVER (in caps) write API keys, tokens, or passwords as literal strings; always read from process.env.*. Pair it with .gitignore entries for .env* and a pre-commit hook (Husky + git-secrets) as a second line of defense. Test the rule quarterly by asking Cursor to "set up Stripe with these test keys" and watch what it does.
You can't force it, but you can raise the rate dramatically. Add a testing rule that requires Cursor to run pnpm test (or your equivalent) and paste the output in the chat before declaring done. The "paste the output" requirement is load-bearing because Cursor cannot fake test output convincingly when the rule asks for it explicitly. Pair with CI to catch the cases where it skips anyway.
Past 8-10 separate MDC files, the agent starts ignoring rules in the middle of the load order. Keep the always-applied rules to 3-4 files (baseline, security, stack). Use globs aggressively so the rest only load for relevant files. If your directory grows past 15 files, it's a signal to consolidate or to split by subdirectory for a platform team.
Senior frontend developer at withRemote. Writes on React, Next.js, performance budgets, and modern web tooling.