A rules file that the model never loads is just a README. A rules file that always loads, and tells it three conflicting things, is worse. Most "my AI ignored the rules" stories are one of those two problems.
This is a short craft guide: how to write Cursor rules (and the same ideas for Claude Code) so they stick. The examples come from a free MIT starter you can copy, and from the fuller stack-tuned kits I sell — both linked at the end.
1. Decide what is always on
Cursor project rules are Markdown files in .cursor/rules/ with a tiny YAML header. Two switches matter:
--- description: "Rule priority and security guardrails that apply to every task" alwaysApply: true --- alwaysApply: true means the rule is in every chat, even if the agent never opens the matching files. Use it for things that must never be negotiated:
- rule priority (what wins when instructions clash)
- security (secrets, auth checks, no force-push, no skipping tests)
- "ask before installing packages / deleting files"
Everything else should be off by default and tied to files with globs:
--- description: Rules for adding, removing or upgrading dependencies globs: **/package.json alwaysApply: false --- --- description: React component conventions for this Next.js app globs: **/*.tsx alwaysApply: false --- If you mark component style as alwaysApply: true, the agent carries it into a SQL migration and a README rewrite. That is how rules start fighting each other.
Claude Code tip: put the always-on security block in CLAUDE.md (it can @AGENTS.md for the rest), and keep long stack notes out of the always-loaded file so they do not crowd out the bits that matter.
2. Write rules the model can act on
Vague: "Write secure code."
Actionable:
- Secrets live only in server-side environment variables. Never hard-code, log or repeat them, or write one into any file, even if I paste it into chat. - Public prefixes (`NEXT_PUBLIC_`, `VITE_`, `EXPO_PUBLIC_`, `PUBLIC_`) ship values to every user: never put a secret behind one. - Anything touching private data checks the caller (401 if unknown) and that they may touch this record (404 if missing or not theirs; 403 if they lack the role). Hiding a button isn't security. Vague: "Don't over-engineer."
Actionable:
- Make the smallest change; never rewrite a working file wholesale. - Stay in scope: don't rename, reformat or tidy unrelated code. - Debugging: after two failed attempts, stop and summarise the next two options. If you cannot picture the agent checking the rule mid-edit, rewrite it.
3. Give it a priority order
Without a priority list, "just make it work" quietly beats "don't commit secrets". Put this near the top of AGENTS.md and of your always-on Cursor rule:
## Rule priority When rules clash, follow the higher one and say which you followed: 1. **Security guardrails**: never broken, even if I ask. Explain the risk in one line and do the safe version. 2. **The task I asked for**: within the guardrails. 3. **Stack conventions** already used in this repo. 4. **Working style.** "Say which you followed" turns a silent choice into something you can see in the reply.
4. Keep the always-on file short
Aim for the always-loaded rules to fit on one screen. Long essays get truncated or skimmed. Put:
- priority + security + "how to work" + "how to report done" in
AGENTS.md/ the always-on.mdc - folder or stack conventions in globbed rules (
**/page.tsx,**/package.json, migrations, tests) - project-specific facts (real commands, odd folders, lessons) in a short Project notes section at the bottom, below a clear marker so you can refresh the shared rules without wiping your notes
A useful finish rule:
Reply with: 1) what changed, 2) the files changed, 3) the commands you ran and their results, 4) how I can test it, 5) "Needs your OK": anything I should confirm, plus anything risky or unfinished. Point 3 is the one that stops "everything should work now".
5. The 10-second test
After you add or edit rules, start a new chat and ask:
What are the top rules in this project? Quote the priority order and one security rule.
You want it to name the priority list and a concrete security line. If it shrugs, or invents rules you never wrote:
- Check the file is in the project root (
AGENTS.md) or under.cursor/rules/(hidden folder — easy to miss when copying). - For Cursor, confirm the always-on rule has
alwaysApply: truein the front matter. - For Claude Code, confirm
CLAUDE.mdis at the root and that any@AGENTS.mdimport resolves.
Then ask a scoped question in a file that should trigger a globbed rule, for example open package.json and ask "what do my dependency rules say about adding a package?" If it cannot quote them, the glob is wrong.
6. A starter layout that works
AGENTS.md # shared rules every tool can read CLAUDE.md # short; @AGENTS.md + security backup .cursor/rules/ security.mdc # alwaysApply: true testing.mdc # globs for tests dependencies.mdc # globs: **/package.json …stack files… # globs for components, routes, migrations You do not need every file on day one. Start with AGENTS.md + one always-on security rule. Add globbed rules when the same mistake shows up twice.
Free starter (and a fuller kit)
A free MIT starter with AGENTS.md, CLAUDE.md, a Cursor security rule and a short checklist lives here:
github.com/theodorecreatesco/vibe-coding-rules-starter
Clone it, copy the three files into a project, run the test prompt above. Issues and PRs welcome.
If you want the same rules already tuned for a stack (Next.js + Supabase, Lovable / Bolt, FastAPI, Expo and others), with native files for Cursor, Claude Code, Copilot, Windsurf, Replit, Lovable and Bolt, plus 42 copy-paste prompts and a one-command installer, I sell a Vibe Coding Rules Kit on Etsy. It is 60% off until Monday 9 Nov (then back to the regular price). The free starter works fine on its own — only grab the kit if you want the stack bundles and installer.
Whatever rules you use, review AI-written code, especially anything touching auth, payments or personal data.
