Skip to content

System Prompts — .cursorrules and CLAUDE.md Explained

Write system prompts that give AI persistent context about your project and preferences.

12 min readai-tools, system-prompts, cursorrules, claude-md, configuration

Every time you start a conversation with an AI coding tool, it knows nothing about your project. It doesn't know your tech stack, your coding style, your project structure, or the decisions you've already made. You have to re-explain everything. Every. Single. Time.

Unless you use system prompts.

System prompts are files that sit in your project and automatically tell the AI about your context every time it starts. They're the difference between an AI that constantly needs to be corrected and an AI that already knows the rules.

What Is a System Prompt?

In AI terms, a "system prompt" is background instruction given to the AI before you start interacting with it. It shapes how the AI behaves, what it knows, and how it responds.

In practical terms for vibe coders, system prompts are files in your project that your AI coding tool reads automatically. The two most common ones are:

  • .cursorrules — Read by Cursor
  • CLAUDE.md — Read by Claude Code

Other tools have their equivalents (Windsurf has .windsurfrules, for example), but the concept is the same everywhere.

Why System Prompts Matter

Without a system prompt, this happens constantly:

You: Add a new API route for user settings
 
AI: *creates a JavaScript file with Express.js*
 
You: No, I'm using Next.js with TypeScript
 
AI: *rewrites with Next.js but uses Pages Router*
 
You: No, App Router
 
AI: *finally gets it right, but uses inline styles instead of Tailwind*
 
You: I use Tailwind CSS
 
AI: *fixes styling, but puts the file in the wrong directory*

Four rounds of correction for one task. With a system prompt:

You: Add a new API route for user settings
 
AI: *creates src/app/api/settings/route.ts using Next.js App Router
     conventions, TypeScript, and your existing patterns*

One round. Done. The system prompt handled all the context that would otherwise require correction.

Writing a .cursorrules File

.cursorrules sits in your project's root directory. Cursor reads it before every interaction. Here's how to write a good one:

The Structure

# Project Overview
[One or two sentences about what this project is]
 
# Tech Stack
[List every technology with version numbers where relevant]
 
# Project Structure
[Describe where different types of files go]
 
# Coding Conventions
[Your style preferences and patterns]
 
# Constraints
[Things the AI should never do]
 
# Context
[Any other information that affects how the AI should work]

A Real Example

# Project Overview
TaskFlow is a project management app for freelancers. It helps users
track projects, log time, and generate invoices.
 
# Tech Stack
- Next.js 16 (App Router)
- TypeScript (strict mode)
- Tailwind CSS (no custom CSS files)
- Supabase (PostgreSQL database + Row Level Security)
- Clerk (authentication)
- Stripe (payments)
- Zod (validation)
- React Hook Form (forms)
 
# Project Structure
- src/app/ — Pages and API routes (App Router conventions)
- src/components/ — Reusable UI components
- src/components/ui/ — shadcn/ui base components (don't modify these)
- src/lib/ — Utility functions and shared logic
- src/hooks/ — Custom React hooks
- src/types/ — TypeScript type definitions
- database/ — SQL migrations (numbered, e.g., 001_create_users.sql)
 
# Coding Conventions
- Use server components by default, "use client" only when necessary
- All database queries go through functions in src/lib/db/
- Form validation uses Zod schemas defined next to the form component
- Error handling: try/catch in server actions, error boundaries in UI
- Naming: PascalCase for components, camelCase for functions, kebab-case for files
- All prices stored in cents (integer), displayed with formatCurrency() from src/lib/utils
 
# Constraints
- Never use "any" type in TypeScript
- Never install new npm packages without asking first
- Never modify files in src/components/ui/ (these are shadcn/ui base components)
- Never put database queries directly in components — use lib/db functions
- Never use inline styles — Tailwind only
 
# Context
- The app is in active development. The projects and time tracking features
  are complete. We're currently building the invoicing feature.
- Users can be on free (3 projects) or pro (unlimited) plans via Stripe
- All database access uses Supabase RLS — the user's auth ID is always checked

This system prompt means every AI interaction in this project starts with a deep understanding of the codebase.

Writing a CLAUDE.md File

CLAUDE.md serves the same purpose for Claude Code but follows Markdown conventions and can contain more detailed documentation.

The Structure

# Project Name
 
## What This Is
[Description of the project]
 
## Tech Stack
[Technologies used]
 
## How to Run
[Commands to start, build, and test]
 
## Project Structure
[Directory layout and conventions]
 
## Key Decisions
[Important architectural decisions and why they were made]
 
## Known Issues
[Current bugs or limitations to be aware of]

A Real Example

# TaskFlow — Freelancer Project Management
 
## What This Is
A Next.js web app for freelancers to track projects, log time, and
generate invoices. Currently in active development with ~50 beta users.
 
## Tech Stack
- Next.js 16 (App Router) + TypeScript
- Supabase (database, auth via Clerk webhook sync, storage)
- Stripe (subscriptions: Free and Pro plans)
- Tailwind CSS + shadcn/ui components
- Deployed on Vercel
 
## How to Run
- `pnpm dev` — Development server on localhost:3000
- `pnpm build` — Production build (also runs type checking)
- `pnpm test` — Run test suite
- `pnpm db:migrate` — Run pending database migrations
 
## Project Structure
All source code is in src/. Database migrations are in database/.
Tests live next to the code they test (*filename*.test.ts).
 
## Key Decisions
- **Supabase over Firebase**: We need PostgreSQL's full-text search
  for the project search feature. Firestore's querying is too limited.
- **Clerk over Supabase Auth**: Clerk's pre-built components save us
  weeks of auth UI work. We sync Clerk users to Supabase via webhook.
- **Prices in cents**: All monetary values are stored as integers
  (cents) to avoid floating-point math issues. The formatCurrency()
  utility handles display.
 
## Known Issues
- The time tracking timer drifts by ~1 second per hour on Safari
- PDF invoice generation times out for invoices with more than 50 line items
- Mobile navigation menu doesn't close when clicking a link

.cursorrules vs. CLAUDE.md

These files serve the same purpose for different tools, but they have different strengths:

| Feature | .cursorrules | CLAUDE.md | |---------|-------------|-----------| | Used by | Cursor | Claude Code | | Format | Plain text | Markdown | | Nesting | Single file in root | Can have nested files in subdirectories | | Best for | Quick rules and constraints | Detailed documentation | | Typical length | 20-50 lines | 50-200 lines |

Can You Have Both?

Absolutely. If you use both Cursor and Claude Code, keep both files. They can contain similar information but tailored to each tool's strengths. The .cursorrules file might be more concise and rule-focused, while CLAUDE.md includes more context and explanation.

What to Include (and What to Skip)

Always Include

  • Tech stack with specific versions
  • Project structure (where files go)
  • Naming conventions
  • Key constraints (things the AI must not do)
  • Current project state (what's built, what's in progress)

Include When Relevant

  • Authentication approach
  • Database schema highlights
  • Testing conventions
  • How to run the project
  • Important architectural decisions

Don't Include

  • Every file in your project (the AI can read the file system)
  • Complete API documentation (too much noise)
  • Change history (that's what Git is for)
  • Personal preferences unrelated to coding ("I like coffee")

Advanced Techniques

Persona Setting

You can tell the AI how to behave:

When suggesting changes, explain your reasoning briefly.
When I ask for a feature, propose the approach before implementing it.
If you're unsure about something, ask rather than guessing.
Assume I'm an intermediate developer comfortable with React but
learning TypeScript.

Negative Examples

Show the AI what not to do:

# Bad patterns to avoid in this project
 
DON'T do this:
~~~typescript
// Don't query the database directly in components
const { data } = await supabase.from('projects').select('*')
~~~
 
DO this instead:
~~~typescript
// Use the db utility functions
const projects = await getProjectsByUser(userId)
~~~

Template Patterns

Give the AI a template to follow:

When creating a new API route, follow this pattern:
 
~~~typescript
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@clerk/nextjs/server'
 
export async function GET(request: NextRequest) {
  const { userId } = await auth()
  if (!userId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }
 
  try {
    // Implementation here
    return NextResponse.json({ data })
  } catch (error) {
    console.error('[API_ROUTE_NAME]', error)
    return NextResponse.json({ error: 'Internal error' }, { status: 500 })
  }
}
~~~

Maintaining Your System Prompt

System prompts aren't write-once documents. They should evolve with your project:

  • When you add a technology, update the tech stack section
  • When you establish a new convention, add it to coding conventions
  • When the AI keeps making the same mistake, add a constraint to prevent it
  • When a section becomes irrelevant, remove it to keep the prompt focused

Think of your system prompt as a living document. Every time you correct the AI about the same thing twice, that correction belongs in the system prompt.

Try this now

Write down the last three things you had to correct an AI tool about in the same project. If the correction is likely to repeat, it belongs in .cursorrules, CLAUDE.md, or both.

Prompt to give your agent

Use this when you want the agent to draft your persistent project instructions: "Help me write a system prompt file for this project. Tool target: [Cursor / Claude Code / both] Project summary: [what the app does] Stack: [frameworks, languages, key services] Repo conventions: [folders, naming, testing, styling, data access] Constraints: [things the agent must never do] Current phase: [what is already built and what is in progress]

Return:

  1. A concise .cursorrules or CLAUDE.md
  2. A short list of rules I should not include because they are too vague, too stale, or too noisy
  3. A maintenance checklist for keeping this file current as the project changes."

What you must review yourself

  • That the file contains no secrets, tokens, or private operational data
  • That the rules reflect the repo as it actually exists today, not how you wish it worked
  • That commands, folders, and conventions are current
  • That the constraints are specific enough to change behavior, not generic enough to be ignored

Common mistakes to avoid

  • Dumping your entire project into the system prompt. The agent can read files; your job is to define rules, not duplicate the repo.
  • Putting secrets in the file. System prompts should describe where secrets live, never include them.
  • Letting the file go stale. A wrong system prompt is often worse than a short one.
  • Writing contradictory rules. "Ask before installing dependencies" and "use whatever package you need" cancel each other out.

Key takeaways

  • System prompts give your agent persistent context instead of making you repeat the same corrections
  • The best files encode stack, structure, constraints, and current phase
  • Good system prompts are concise, current, and opinionated about risky behavior
  • Every repeated correction is a signal that the system prompt needs an update

What's Next

Next up: Breaking Big Ideas into Small Tasks — The Decomposition Pattern. Once the agent knows your standing rules, the next job is breaking work into pieces small enough that it can execute cleanly and you can review safely.