โ† Back to Lessons
  • coding standard guidelines

  • vibe coding

  • ai-assisted-development

  • software-architecture

  • development-best-practices

Keep Your Code Consistent: Writing Rules for Key Files with AI

What is a context rule?
Your first rule from real code

Imagine everything is going well in your development, youโ€™re vibing with the code, and suddenly the AI suggests something that doesnโ€™t follow your conventions; it duplicates logic, changes patterns, or mixes styles. Itโ€™s not being โ€œcapriciousโ€โ€”itโ€™s lacking code-close context. The solution isnโ€™t a 50-page manual, but rather short, living rules that the AI can read right where it works.

What is a context rule?

A context rule is a brief (Markdown) file that lives next to your code (for example, in .cursor/rules/) and explains how a specific file or module should look and behave:

  • Purpose of the file/module.
  • Conventions (patterns, naming, structure).
  • Minimal examples of whatโ€™s correct (โœ…) and what we donโ€™t want (โŒ).

When your AI-powered editor (e.g., Cursor) generates or modifies code, it reads these rules as a guide to maintain consistency. It doesnโ€™t replace linters or tests; itโ€™s a lightweight specification that guides the AI.

Mini-example (.mdc):

1# Purpose 2Consistent REST responses. 3 4# Conventions 5- JSON with `{ data, error }`. 6- Errors include `code` and `message`. 7 8# โœ… Correct 9return res.json({ data: user, error: null }); 10 11# โŒ Incorrect 12Responding with `{ result }` in some endpoints and `{ payload }` in others.

When to create or review rules (trigger moments)

  • New pattern (WebSockets, GraphQL, queues, uploads).
  • Major refactor or library upgrade.
  • AI suggestions โ€œderivedโ€ from the repoโ€™s style.
  • Sprint close/start or before a release.
  • Onboarding someone new.

Practical rule: if youโ€™ve corrected the same type of AI output twice, itโ€™s time to write a short rule.

Your first rule from real code

  1. Pick a โ€œVIPโ€ file. Something that sets the tone for the rest: routes.py, UserService.ts, Form.tsx, theme.ts, etc.

  2. Ask the AI to draft the rule. In Cursor, with the file open, request:

1Generate a short rule to keep this file consistent. 2Include: purpose, 3โ€“5 conventions, and at least 1 correct example. 3Donโ€™t add prose outside the rule.
  1. Save the rule. Create the .cursor/rules/ folder and save as api-endpoints.mdc (use a descriptive name).
1# Purpose 2<what it standardizes and why> 3 4# Conventions 5- <concrete rule 1> 6- <concrete rule 2> 7- <concrete rule 3> 8 9# โœ… Correct 10<minimal snippet with the expected format> 11 12# โŒ Incorrect 13<typical snippet we donโ€™t want>

Short example (.mdc):

1# Purpose 2Standardize REST endpoints with consistent responses. 3 4# Conventions 5- Respond with JSON `{ data, error }`. 6- Errors include `code` and `message`. 7- Avoid business logic in the controller; delegate to services. 8 9 10# โœ… Correct 11router.get('/users/:id', async (req, res) => { 12 try { 13 const user = await svc.getUser(req.params.id); 14 return res.json({ data: user, error: null }); 15 } catch (e) { 16 return res.status(400).json({ data: null, error: { code: 'USER_GET_FAILED', message: String(e) } }); 17 } 18}); 19 20# โŒ Incorrect 21Responding with `{ result }` in one endpoint and `{ payload }` in another.

Frontmatter YAML and globs are optional in this basic module.

To test the rule, ask the AI for a real modification to the VIP file (for example, โ€œadd GET /users with paginationโ€) and check if it follows the rule. If it deviates, adjust the rule with a single change (delta prompting), for example: โ€œadd that successful responses use status 200 and errors โ‰ฅ400; change nothing else.โ€ Repeat until the suggestions are consistent and always add a section with correct and incorrect examples, since seeing what you do and donโ€™t want helps the model lock in the standard.

Quick example: WebSocket pattern (chat)

Imagine youโ€™re adding a new chat feature to your app using WebSockets. Hereโ€™s how you could use rulesโ€”create a file like chat-websocket.mdc and outline the following:

1# Purpose 2Consistent errors and reconnection in WebSocket (chat). 3 4# Conventions (why) 5- `onerror` + `onclose` (visibility and stability). 6- Exponential backoff max 30s (avoid aggressive loops). 7- Encapsulated connection (avoid fragile global state). 8 9# โœ… Correct 10const socket = new WebSocket(URL); 11socket.onerror = (err) => { log('ws_error', err); attemptReconnect(); }; 12 13# โŒ Incorrect 14Just `console.error` without reconnection or encapsulation.

Now ask for โ€œtyping notificationsโ€ and the AI should maintain onerror + reconnection without further reminders.

To keep rules organized, store them in .cursor/rules/ with clear names and, if helpful, subfolders by module or layer. Version everything like code, commit them to git, and review them in PRs. In each PR, explain why the rule exists or changes (what problem it solves) so the team understands the context. Also, when writing and maintaining rules, avoid common pitfalls. If a rule gets long, trim it to the essentials and move large examples to a separate file. Replace vagueness (โ€œclean codeโ€) with concrete actions (โ€œuse try/catch in async fetch callsโ€). If there are duplicates or conflicts, unify or document precedence (โ€œif it overlaps with X, X takes priorityโ€). And donโ€™t skip the testโ€”ask for a real modification and verify the AI follows the rule.

What if you already started the project?

Creating rules mid-development is often easier because you have real code to start from. If, instead, youโ€™re repeating a well-known pattern (e.g., a simple REST API youโ€™ve built before), you can prepare 1โ€“2 rules from day one. There are also public collections of pre-written rules you can adapt (e.g., cursorrules).

Good to Know ๐Ÿ’ก

  • Rules Can Inherit: Like CSS, rules can build on each other. You can have base rules for global standards (like general naming conventions) and then more specific rules for particular modules or file types.
  • Feedback Loop: The more you use /Generate Cursor Rules and refine the output, the better your promptsโ€”and the better the AI will help you!

You donโ€™t need a perfect system to start. With a good rule in a key module, youโ€™ll already notice less friction and more consistency. Create your first one today, test it, and tweak it with small changes; tomorrow, your AI will already be suggesting code more aligned with your project.