← 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.