The world of software development is constantly evolving, and one of the most exciting advancements in recent years has been the rise of AI-assisted coding. Tools like Cursor are revolutionizing how developers write, understand, and maintain code. But to truly harness the power of these AI assistants, you need to go beyond the default settings and tailor them to your specific projects. That's where .cursorrules
files come in.
What are Cursorrules and Why Should You Care?
At their core, .cursorrules
files are configuration files that provide project-specific instructions and guidelines to Cursor AI. Think of them as a way to inject your team's collective knowledge and best practices directly into the AI's decision-making process. By defining these rules, you can ensure that Cursor generates code that aligns with your project's architecture, coding style, and technology stack.

The Solution: Persistent, Scoped Guidance with Modern Cursor Rules
Cursor's modern Rules system solves this by allowing you to embed project-specific knowledge and personal preferences directly into the AI's context. This ensures the AI generates code that's consistent, accurate, and adheres to your standards.
There are two main types of rules in the current system:
- Project Rules: Stored in the
.cursor/rules
directory within your project, these rules are version-controlled and scoped to the codebase. They are perfect for encoding domain-specific knowledge, standardizing patterns, and automating project workflows. - User Rules: Defined globally in your Cursor settings, these rules apply across all your projects. They are ideal for setting personal preferences like response style or commonly used libraries.
(Note: The older .cursorrules
file in the project root is still supported but deprecated. It's recommended to migrate to the new Project Rules system.)
How Modern CursorRules Work

Unlike standard chat interactions, rules provide persistent context. When a rule is applied (either automatically or manually), its content is added to the beginning of the prompt sent to the AI model (Agent or Cmd-K). This ensures the AI consistently follows the specified guidelines.
Setting Up and Using Project Rules
Project rules offer fine-grained control over how the AI behaves within a specific codebase.
1. Location: Create a .cursor/rules
directory in your project's root.
2. Format: Each rule lives in its own file with the .mdc
(Markdown Components) extension. MDC allows for both metadata (frontmatter) and rule content.
3. Rule Structure:An .mdc
rule file typically looks like this:
---
description: Optional description for Agent Requested rules.
globs: ["optional/glob/pattern/**", "*.py"] # For Auto Attached rules
alwaysApply: false # True for Always rules
---
# Rule Content Starts Here
- Use this specific library/pattern.
- Avoid doing this other thing.
- Reference specific files for context: @path/to/important/file.ts
4. Rule Types (Determined by Metadata):
Rule Type | Metadata Settings | Description |
---|---|---|
Always |
alwaysApply: true |
Always included in the model context for the project. |
Auto Attached |
globs: ["pattern"] , alwaysApply: false |
Included only when files matching the globs pattern are part of the AI's context (e.g., in chat). |
Agent Requested |
description: "..." , alwaysApply: false |
The rule is available to the AI, which decides whether to fetch and use it based on the description . |
Manual |
alwaysApply: false (or omitted) |
Only included when explicitly mentioned in chat using @ruleName (e.g., @django-style ). |
5. Creating Rules:You can create .mdc
files manually or use the Command Palette (Cmd+Shift+P
or Ctrl+Shift+P
) and search for "New Cursor Rule".
6. Generating Rules:After a chat conversation where you've refined how the AI should behave, use the /Generate Cursor Rules
command to automatically create a rule based on that interaction.
User Rules: Your Global Preferences
User Rules are simpler.
- Go to
Cursor Settings > Rules > User Rules
. - Enter plain text instructions (MDC format is not supported here).
- These rules are always applied to all your projects.
Example User Rule:
Always import React explicitly: `import React from 'react';`
Respond concisely. Avoid filler phrases.
Prefer functional components with Hooks over class components.
Best Practices for Writing Rules
- Be Specific & Actionable: Vague instructions are less effective. Tell the AI exactly what to do or avoid.
- Keep them Concise: Aim for clarity and brevity. Under 500 lines is a good guideline.
- Use Examples: Include short code snippets or reference files (
@filename.ext
) to illustrate points. - Decompose: Break down complex standards into smaller, focused rules.
- Use Descriptions: For
Agent Requested
rules, write clear descriptions so the AI knows when to use them. - Iterate: Refine your rules based on the AI's performance.
Awesome Rule Examples (using .mdc
format)
Here are some examples inspired by the provided rules-mdc
files, demonstrating the modern format:
1. Django Best Practices (django.mdc
)
---
description: Provides guidance on Django best practices, models, views, templates, and ORM usage.
globs: ["*.py"]
alwaysApply: false
---
# Django Development Guidelines
## General
- Follow the Django Style Guide and PEP 8.
- Use Django's built-in features whenever possible (authentication, admin, forms).
- Keep applications modular and reusable.
## Models (`models.py`)
- Use descriptive model and field names.
- Define `__str__` methods for all models.
- Add `Meta` options for ordering, verbose names, etc.
- Use `ForeignKey` with `on_delete` specified appropriately (e.g., `models.CASCADE`, `models.SET_NULL`).
- Example: `author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')`
## Views (`views.py`)
- Prefer Class-Based Views (CBVs) for common patterns (List, Detail, Create, Update, Delete).
- Use Function-Based Views (FBVs) for simple or highly custom logic.
- Implement proper authentication and permissions (`@login_required`, `PermissionRequiredMixin`).
- Handle exceptions gracefully (e.g., `try...except ObjectDoesNotExist`).
- Use `get_object_or_404` shortcut.
## Templates
- Organize templates in app-specific directories (`templates/<app_name>/`).
- Use template inheritance (`{% extends 'base.html' %}`).
- Load static files using `{% load static %}` and `{% static 'path/to/file.css' %}`.
- Avoid complex logic in templates; use template tags or filters instead.
## ORM
- Use queryset filtering (`.filter()`, `.exclude()`) efficiently. Avoid loading unnecessary data.
- Utilize `select_related` (for one-to-one/foreign key) and `prefetch_related` (for many-to-many/reverse foreign key) to optimize database queries.
- Use `.annotate()` for database-level aggregations.
- Be mindful of lazy loading and potential N+1 query problems.
## Forms (`forms.py`)
- Use Django Forms for data validation and HTML generation.
- Prefer `ModelForm` for forms tied directly to models.
- Define custom validation methods (`clean_<fieldname>()`, `clean()`).
## URLs (`urls.py`)
- Use descriptive URL names (`path('articles/<int:pk>/', views.ArticleDetailView.as_view(), name='article-detail')`).
- Include app-specific `urls.py` files using `include()`.
## Settings (`settings.py`)
- Use environment variables for sensitive data (SECRET_KEY, database credentials). Do not commit secrets.
- Configure `STATIC_URL`, `STATIC_ROOT`, `MEDIA_URL`, `MEDIA_ROOT` correctly.
## Testing
- Write unit tests and integration tests using Django's `TestCase` or `pytest-django`.
- Test models, views, forms, and utilities.
2. Dockerfile Best Practices (docker.mdc
)
---
description: Guidelines for writing efficient and secure Dockerfiles.
globs: ["Dockerfile", "*.Dockerfile"]
alwaysApply: false
---
# Dockerfile Best Practices
## Base Image
- Use official, minimal base images (e.g., `python:3.11-slim`, `node:18-alpine`, `golang:1.20-alpine`).
- Specify exact versions or digests for reproducibility (`python:3.11.4-slim-bullseye`).
- Prefer Alpine images for size, but be aware of potential `musl libc` compatibility issues vs `glibc`.
## Minimize Layers & Build Context
- Chain related commands using `&&` to reduce layers (e.g., `apt-get update && apt-get install -y --no-install-recommends package && rm -rf /var/lib/apt/lists/*`).
- Use a `.dockerignore` file to exclude unnecessary files/directories (e.g., `.git`, `node_modules`, `.venv`, logs, local config) from the build context.
## Build Efficiency
- Order instructions from least to most frequently changing (e.g., install dependencies before copying application code).
- Leverage Docker build cache effectively.
- Use multi-stage builds to keep the final image small, separating build dependencies from runtime dependencies.
## Security
- Run containers as a non-root user. Create a dedicated user/group (`RUN groupadd -r appuser && useradd -r -g appuser appuser`) and switch to it (`USER appuser`).
- Avoid storing secrets directly in the Dockerfile. Use build arguments (`ARG`), environment variables (`ENV`), or secrets management tools at runtime.
- Scan images for vulnerabilities using tools like Trivy or Docker Scout.
- Minimize the attack surface: install only necessary packages (`--no-install-recommends`).
## Instructions
- Use `COPY` instead of `ADD` unless you specifically need `ADD`'s features (like auto-extraction or URL fetching).
- Prefer `ENTRYPOINT` for the main container command and use `CMD` for default arguments that can be overridden. Use the JSON array form (e.g., `ENTRYPOINT ["python", "app.py"]`).
- Use `WORKDIR` to set the working directory for subsequent instructions (`RUN`, `CMD`, `ENTRYPOINT`, `COPY`, `ADD`).
- Expose necessary ports using `EXPOSE`.
## Example Multi-Stage Build (Python)
```dockerfile
# Build Stage
FROM python:3.11-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
COPY . .
# Final Stage
FROM python:3.11-alpine
WORKDIR /app
# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Copy installed packages and app code from builder stage
COPY --from=builder /root/.local /usr/local
COPY --from=builder /app .
# Ensure scripts are executable if needed
# RUN chmod +x ./entrypoint.sh
USER appuser
EXPOSE 8000
ENTRYPOINT ["python"]
CMD ["manage.py", "runserver", "0.0.0.0:8000"]
**3. Python Black Formatting (`black.mdc`)**
```mdc
---
description: Ensures Python code formatting adheres to the Black style guide.
globs: ["*.py"]
alwaysApply: false
---
# Black Code Formatting Rules for Python
- Adhere strictly to the Black code style. Black is non-negotiable and has minimal configuration.
- Default line length is 88 characters.
- Use double quotes (`"`) for strings where possible, but Black will handle consistency.
- Black handles indentation, whitespace, trailing commas, and line breaks automatically.
- Ensure code passes `black .` check before committing.
- Integrate Black into your pre-commit hooks or CI/CD pipeline.
## Example Integration (pre-commit)
```yaml
# .pre-commit-config.yaml
repos:
- repo: <https://github.com/psf/black>
rev: 23.3.0 # Use a recent stable version
hooks:
- id: black
Running Black
- Format specific files:
black my_module.py your_script.py
- Format entire project (checking
.gitignore
):black .
- Check files without modifying them:
black --check .
**4. React Best Practices (`react.mdc`)**
(Assuming a file named `react.mdc` exists with similar content structure)
```mdc
---
description: Guidelines for writing modern React components and applications.
globs: ["*.js", "*.jsx", "*.ts", "*.tsx"]
alwaysApply: false
---
# React Development Best Practices
## Components
- Prefer Functional Components with Hooks over Class Components.
- Use PascalCase for component names (`MyComponent`).
- Keep components small and focused (Single Responsibility Principle).
- Use explicit `import React from 'react';` at the top (though not strictly needed with newer JSX transforms, it's good practice for clarity).
- Define `propTypes` (if using JavaScript) or TypeScript interfaces for props.
- Use destructuring for props: `function MyComponent({ name, count }) { ... }`
## State Management
- Use `useState` for simple component-local state.
- Use `useReducer` for more complex state logic or when state transitions depend on previous state.
- Lift state up to the nearest common ancestor when multiple components need access to the same state.
- For global or shared state, consider Context API (`useContext`) for moderate complexity or dedicated state management libraries (Redux, Zustand, Jotai) for larger applications.
## Hooks
- Only call Hooks at the top level of functional components or other custom Hooks.
- Don't call Hooks inside loops, conditions, or nested functions.
- Follow the Rules of Hooks. Use ESLint plugins (`eslint-plugin-react-hooks`) to enforce them.
- Use `useEffect` for side effects (data fetching, subscriptions, manual DOM manipulations). Include a dependency array to control when the effect runs.
- Use `useCallback` and `useMemo` to memoize functions and values respectively, optimizing performance where necessary (often related to `React.memo` or heavy computations).
## Keys
- Provide stable and unique `key` props when rendering lists of elements (`<li key={item.id}>`). Avoid using array indices as keys if the list order can change or items can be inserted/deleted.
## File Structure
- Organize files by feature or route (e.g., `/features/Auth`, `/components/common`).
- Colocate components, styles, tests, and hooks related to a specific feature.
## Styling
- Choose a consistent styling approach: CSS Modules, Styled Components, Emotion, Tailwind CSS, plain CSS/SASS.
- Avoid inline styles for anything beyond simple dynamic adjustments.
## Performance
- Use `React.memo` to memoize components and prevent unnecessary re-renders.
- Analyze performance with React DevTools Profiler.
- Consider code splitting (e.g., `React.lazy` and `Suspense`) to reduce initial bundle size.
## Accessibility (a11y)
- Use semantic HTML elements (`<button>`, `<nav>`, `<main>`).
- Ensure proper ARIA attributes are used when necessary.
- Test with keyboard navigation and screen readers.
Conclusion: Embrace Precision AI Assistance
Modern Cursor Rules (.cursor/rules
and User Rules) are essential for harnessing the full power of AI-assisted development. By investing a small amount of time in defining project standards and personal preferences, you enable Cursor to act as a true, context-aware pair programmer. This leads to higher code quality, increased productivity, better team collaboration, and reduced technical debt. Stop tweaking generic AI suggestions and start guiding Cursor with precision using Rules.