How to Build Rules File for AI Agents like Cursor

AI-powered coding assistants like Cursor are changing how developers write, refactor, and understand code. But here’s the thing, an AI agent is only as good as the instructions it follows and that’s where rule files come in.

Think of rule files as a contract between you and the AI agent. They set boundaries, define style preferences, and tell the agent how to behave in specific scenarios so you don’t waste time correcting bad assumptions.

In this post, we’ll break down:

  • How to design effective rule files for frontend and backend projects.
  • The difference between .cursorrules, rules/ directory, and commands.
  • Real-world examples and best practices.

Why Rule Files Matter

Out of the box, Cursor (and similar AI dev tools) are powerful but generic. Without context, they might:

  • Suggest code that doesn’t match your team’s style.
  • Use dependencies you don’t allow.
  • Miss domain-specific constraints.
  • Rewrite code in ways that create regressions.

By building rule files, you essentially “teach” the agent:

  • How should code look? (linting, formatting, naming conventions)
  • What is off-limits? (forbidden libraries, outdated APIs, insecure patterns)
  • What are the must-follow steps? (e.g., UTC conversions, auth checks, logging rules)

Anatomy of a Rule File

A good rule file is like a developer guide distilled into structured text. Most setups use YAML, JSON, or plain text with sections.

Here’s a simple structure:

# .cursorrules.yml
style:
  language: "javascript"
  framework: "react"
  formatting: "prettier"
  variable_naming: "camelCase"

restrictions:
  - "Do not use moment.js (use date-fns instead)."
  - "Avoid deprecated React lifecycle methods."
  - "Do not commit API keys or secrets."

workflow:
  - "Always validate input data before API calls."
  - "Convert all dates to UTC before saving."
  - "Use async/await, avoid .then chains."

documentation:
  - "Every function must include a short JSDoc comment."
  - "Complex components should have usage examples."

Example: Frontend Rule File for a Next.js Project

# .cursorrules.yml
style:
  language: "typescript"
  framework: "nextjs"
  css: "tailwind"

restrictions:
  - "No inline CSS. Always use Tailwind classes."
  - "Do not use 'any' type in TypeScript."
  - "Do not use console.log in production code (use logger util)."

workflow:
  - "Pages must use Next.js routing conventions."
  - "Use server components unless client-side interactivity is required."
  - "For API routes, always sanitize inputs and handle errors gracefully."

documentation:
  - "Exported hooks and utils must include TypeDoc comments."
  - "All API routes must include Swagger docs (via OpenAPI)."

This ensures Cursor generates UI and API route code consistent with your FE stack.

Example: Backend Rule File for a NestJS/Express Project

# .cursorrules.yml
style:
  language: "typescript"
  framework: "nestjs"

restrictions:
  - "Do not use raw SQL queries (use TypeORM/Prisma)."
  - "Never log sensitive user data."
  - "Do not use bcrypt directly, always use the project's password util."

workflow:
  - "All controllers must use DTOs for request validation."
  - "Always wrap database operations in try/catch with logging."
  - "Use dependency injection for all services (no inline new statements)."
  - "Ensure all endpoints implement authentication and role-based guards."

documentation:
  - "Every public API route must have OpenAPI decorators."
  - "Each service should include inline comments explaining complex logic."

With this in place, Cursor won’t suggest unsafe DB queries or bypass project-specific security practices.

Want to Build a AI-driven Development Workflows?

1. .cursorrules vs rules/ Directory vs commands

This is where many teams get confused. Here’s the breakdown:

1. .cursorrules (Single File)

  • Use when you want one central, lightweight config.
  • Best for small/medium projects or solo devs.
  • Good for setting global style, restrictions, and workflows.

Think of it like .eslintrc one file to enforce team-wide coding practices.

2. Rules/ Directory

Use when your project is large or full-stack and you need modular rules.

  • Example:
    • rules/frontend.yml
    • rules/backend.yml
    • rules/security.yml

This way, FE devs don’t need to dig through BE rules, and vice versa.

Easier to maintain when multiple teams contribute.

Think of it like having multiple ESLint configs or microservice-specific Dockerfiles.

3. Commands

  • Use when you want interactive, task-specific shortcuts.
  • Example: instead of typing “write unit tests for this service,” you can define:
# commands.yml
"generate-tests":
  description: "Generate Jest unit tests for current file"
  run: |
    Write unit tests for this file using Jest.
    Follow project conventions for mocks and test folder structure.
  • Best for repetitive workflows generating boilerplate, refactoring, writing tests, or scaffolding files.
  • These don’t replace rules, they complement them.

Best Practices for Writing Rule Files

  • Be explicit, not vague
    • Bad: “Write clean code.”
    • Good: “Use camelCase for variables, PascalCase for components, no underscores.”
  • Keep it short but layered
    • Rules should be readable in under 5 minutes.
  • Update with your codebase
    • Treat them like documentation they evolve.
  • Test your rules
    • Ask Cursor to scaffold a new component/service and see if it follows the rules.
  • Don’t over-engineer
    • Too many rules can choke creativity. Focus on must-haves.

Starter Full-Stack .cursorrules.yml

# .cursorrules.yml
style:
  language: "typescript"
  frontend: "react + nextjs + tailwind"
  backend: "nestjs"
  formatting: "prettier"

restrictions:
  - "Do not use 'any' in TypeScript."
  - "Do not use console.log in production (use logger util)."
  - "Avoid deprecated React lifecycle methods."
  - "Do not use raw SQL (use Prisma/TypeORM)."
  - "Do not hardcode secrets, always use env vars."

workflow:
  frontend:
    - "Pages follow Next.js conventions."
    - "Components are functional and typed."
    - "Client components only when interactivity is needed."
  backend:
    - "Controllers use DTOs for validation."
    - "Services use dependency injection."
    - "Endpoints must enforce auth & role guards."
  shared:
    - "Convert all dates to UTC before saving."
    - "Use async/await instead of .then."
    - "Write tests for all exported functions."

documentation:
  - "Components, hooks, and services must include TypeDoc/JSDoc comments."
  - "All API endpoints must include Swagger decorators."
  - "Complex logic must have inline comments."
coma

Conclusion

AI agents like Cursor are incredibly powerful, but without clear direction, they can become more of a distraction than a helper.

  • Use .cursorrules for small projects.
  • Use a rules/ directory for larger full-stack or multi-team setups.
  • Use commands for repeatable tasks.

If you’ve been frustrated with AI-generated code that doesn’t “fit” your project, try building a rule file today. Start small, enforce what matters most, and watch your AI agent transform into a true coding partner.

Keep Reading

  • Let's create something together!