Building with Cursor Part 2 of 3: Context Management for Large Codebases
As your codebase grows, Cursor's automatic context becomes less precise. This guide covers the modern .cursor/rules/ directory system, @file/@folder/@codebase/@docs references, Plan Mode, and parallel agents. These techniques keep Cursor accurate when you have hundreds of files to manage.
The Context Problem at Scale
Part 1 of this series covered Cursor's four editing modes and .cursorrules setup. If you followed it, you have a working workflow for feature-sized tasks. But as your codebase grows past 50 files, past 200, and past the size where you still know where everything lives, a new problem appears.
Cursor's automatic context becomes noisy. The agent pulls in files that look relevant but aren't. It misses files that are critical but have non-obvious names. It makes changes that contradict conventions you've established elsewhere. The more code you have, the more important it becomes to control what Cursor sees and when.
This is Part 2 of the Building with Cursor series:
- Part 1: The four editing modes, .cursorrules setup, and the workflow that replaced VS Code
- Part 2 (this guide): Context management for keeping Cursor accurate in large codebases
- Part 3: Advanced Cursor, including model selection, MCP tools, hooks, and parallel agents
From .cursorrules to .cursor/rules/: What Changed
If you set up a .cursorrules file in Part 1, it still works. But Cursor's recommended approach has shifted to a directory-based system: .cursor/rules/ with individual .mdc files.
The old approach uses one big .cursorrules file, which has a fundamental problem: everything in it is included in every conversation, whether it's relevant or not. A rule about your API response format is injected into every session, including the ones where you're just writing tests or fixing a CSS issue. Over time, the file grows, the context window fills with boilerplate, and the agent starts ignoring the parts it doesn't need.
The new system solves this with four rule types, each with different activation behaviour:
Rule Types in .cursor/rules/
Each rule is an .mdc file (markdown with frontmatter). The frontmatter controls when it applies:
---
alwaysApply: true
---
# Project Overview
This is a multi-tenant SaaS for restaurant inventory management.
Tech stack: Next.js 14, TypeScript, Prisma ORM, PostgreSQL.
The four rule types, in order of how often you'll use them:
- Always Apply (
alwaysApply: true). Injected into every session. Use for your project overview and core constraints, usually one or two rules at most. Keep these short. - Apply to Specific Files (
globs: "**/*.tsx"). Activated when a matching file is in context. Use for framework-specific conventions, like React component patterns or API route standards. - Apply Intelligently (
description: "..."). The agent reads the description and pulls the rule in when it decides it's relevant. Use for domain rules that apply to some tasks but not others. - Apply Manually (no frontmatter fields). Only activated when you
@mentionit in chat. Use for reference material, onboarding docs, or migration guides you want available on demand.
A Production Rule Structure
Here's what a well-organized .cursor/rules/ directory looks like for a Next.js project:
.cursor/rules/
project-overview.mdc # alwaysApply: true. 1 paragraph about the app
conventions.mdc # alwaysApply: true. 10 key rules, nothing more
react-components.mdc # globs: "**/*.tsx". Component patterns
api-routes.mdc # globs: "app/api/**/*.ts". Route conventions
database.mdc # description: "Prisma schema and query patterns"
testing.mdc # description: "Testing approach and patterns"
migration-guide.mdc # manual. Only needed during migrations
The project overview and conventions files are always included (they're short). The rest load only when the agent is working on relevant files or tasks. Total context from rules: around one to two thousand tokens, not eight thousand.
Creating Rules
Cursor's rules documentation lists /create-rule as one way to create a rule. Type the command in the Cursor agent input and describe what you want. The agent generates the .mdc file with correct frontmatter and saves it to .cursor/rules/.
Or create the file manually: make a new .mdc file in .cursor/rules/, add frontmatter, write the rule. Commit it to git. Every developer on your team gets the same context automatically.
Explicit Context References: @file, @folder, @codebase, @docs
Rules handle the standing context, which is what Cursor knows at the start of every session. But for specific tasks, you need to point the agent at specific things. That's what @ references are for.
@file: Point to Specific Files
When you know exactly which file the agent needs, tag it directly:
@app/api/auth/route.ts Update the login handler to return a 401 instead of 403 on invalid credentials
The agent opens that file and operates on it with full content. This is more reliable than hoping the semantic search finds it, especially for files with generic names (utils.ts, helpers.ts, index.ts) that don't appear in searches for task-specific terms.
When to use @file:
- The file has a non-obvious name relative to your task
- You need the agent to read something in full rather than excerpts
- You're debugging and you know which file has the bug
- You want the agent to follow the exact pattern in a specific file
@folder: Include a Directory
For tasks that span a module or feature area, reference a folder instead of individual files:
@app/components/forms/ Review these components for accessibility issues and create a summary
Cursor's 1.0 changelog says @folder tries to include the files that fit within the context window. Use it when you're working on a self-contained area of the codebase, such as a feature module, a shared component library, or a set of related API routes.
Caveat: Large folders with many files can flood the context. If a folder has 40+ files, be more specific with @file, or reorganise so related files are grouped in smaller directories.
Free AI Builder Newsletter
Weekly guides on AI tools & builder strategies.
@codebase: Full Semantic Search
@codebase triggers a semantic search across your entire indexed codebase. Use it when you don't know where something lives:
@codebase Find all places where we're handling Stripe webhooks and check they all validate the signature
The agent uses grep and semantic search to find relevant files across the project, then reasons about the results. This is how Cursor automatically finds context without you tagging anything. You can also invoke it explicitly when you want the agent to do a broader search than it might do by default.
Use @codebase for:
- Auditing a pattern across the codebase ("are we consistently handling errors?", "where do we use X library?")
- Finding code when you know what it does but not where it lives
- Onboarding questions about unfamiliar parts of the project
@docs: External Documentation
@docs lets you reference external documentation that Cursor has indexed. When you're working with a library and want the agent to use the current docs instead of its training knowledge:
@Prisma Add a new migration for the UserSubscription model with the fields in the schema
Cursor indexes popular library docs (Next.js, Prisma, React, etc.) automatically. For less common libraries, you can add a doc URL in Cursor Settings → Features → Docs, and Cursor will crawl and index it.
This matters because AI training data has a cutoff. Using @docs for a library that's changed significantly since training (like Next.js App Router) prevents the agent from generating code that follows outdated patterns.
Plan Mode: Think Before You Build
For larger tasks that touch more than three or four files, or where getting the architecture wrong is expensive to fix, Plan Mode is worth the extra step.
Press Shift+Tab in the agent input to toggle Plan Mode. Instead of immediately writing code, the agent:
- Searches your codebase to understand the relevant context
- Asks clarifying questions if it needs them
- Creates a detailed implementation plan with specific file paths and proposed changes
- Waits for your approval before building anything
Plans open as Markdown files. You can edit them directly to remove steps you don't want, change the approach, or add constraints the agent missed. Then approve and let it run.
Plans are not saved to .cursor/plans/ automatically. Choose Save to workspace, as described in Cursor's Plan Mode guide, to store a plan there. A saved plan can help you resume an interrupted build, give a teammate context, or rerun a corrected approach instead of picking apart half-completed changes.
When Planning Is Worth It
Not every task needs a plan. Use Plan Mode when:
- The task touches 5+ files
- You're implementing a new feature that could go in several directions architecturally
- You've had the agent misunderstand a similar task before
- The task involves a database migration or other irreversible change
- Multiple developers will be affected by the change
Skip planning for: quick bug fixes, one-file changes, tasks where the implementation is obvious and low-risk.
Managing Context in Long Sessions
One of the most common Cursor problems developers hit: the agent starts strong on a complex task, then starts making mistakes after many turns. Contradicting earlier decisions, forgetting constraints you mentioned, getting confused about which file is which.
This is a context window problem. Long conversations accumulate noise from tool outputs, intermediate reasoning, and repeated content. The most useful context gets diluted.
The Fix: Start Fresh When You Change Tasks
Start a new conversation when:
- You're moving to a different feature or module
- The agent seems confused or keeps repeating the same mistake
- You've finished one logical unit of work
Continue the same conversation when you're iterating on the same feature and the agent needs the recent exchange as context.
@Past Chats: Bringing Back Earlier Context
When you start a new conversation but need context from a previous one, use @Past Chats. The agent reads the relevant parts of your chat history selectively, instead of you having to paste the whole thing.
@Past Chats I was working on the rate limiting implementation yesterday. Continue from where we left off.
This is more efficient than duplicating conversations and keeps the new session clean.
Structuring Rules for Accuracy at Scale
As your codebase grows, the rule structure matters more. Here's the pattern that works at scale:
Keep Always-Apply Rules Small
Your alwaysApply: true rules should be under 100 lines combined. They're in every session. If they're bloated, they eat context that would be better used for actual code. Limit them to:
- Project overview (1 paragraph)
- Tech stack (a short list)
- The three to five conventions that, if violated, create serious bugs or inconsistencies
- What NOT to do (the most underused rule section)
Use Glob-Based Rules for Framework Patterns
The most valuable rules for large codebases are glob-scoped. When the agent opens a .tsx file, it automatically gets the React component conventions. When it opens an API route, it gets the response format rules. You never have to remind it because the right context loads automatically.
---
globs: "app/api/**/*.ts"
---
# API Route Conventions
All API routes return:
- 200: { data: T }
- 400: { error: "user-facing message" }
- 401: { error: "Unauthorized" }
- 500: { error: "Internal error" } (never expose stack traces)
Authentication: use the getSession() helper from @/lib/auth. Never access cookies directly.
See app/api/users/route.ts for a canonical example.
Reference Examples, Don't Copy Code
Rules that copy code become stale as the codebase changes. Instead, point to canonical examples:
---
description: "React component structure and patterns for this project"
globs: "**/*.tsx"
---
Follow the component pattern in components/ui/Button.tsx. It shows correct prop typing, variant handling, and className merging. For forms, see components/forms/LoginForm.tsx.
When you update the canonical component, the rule stays accurate without any editing.
A Reference Workflow: Working on an Unfamiliar Module
Here's what a context-aware Cursor workflow looks like when you're working on a part of the codebase you haven't touched recently:
1. Orient with @codebase
@codebase How does the subscription billing flow work? What files are involved?
Get a map of the relevant files before you start making changes.
2. Read the key files with @file
@app/lib/billing.ts @app/api/webhooks/stripe/route.ts Show me what happens when a subscription is cancelled
Explicit references for the files that matter most.
3. Plan before building
For any non-trivial change, use Plan Mode (Shift+Tab) to get a structured plan before the agent touches any files.
4. Review the diff carefully
In a large codebase, the agent may touch files you didn't expect. Review each changed file in the diff view. If it modified eight files for a change you expected to be in three, figure out why before accepting.
What's Next
Part 3 of this series covers the parts of Cursor that most developers never reach: model selection and when to switch between them, MCP tools to connect Cursor to Slack, databases, and Sentry, Hooks for long-running agent loops, and running parallel agents on the same codebase using git worktrees.
If you're finding these guides useful and want to go further with AI-assisted development across the full toolchain of agents, MCP, and production workflows, join AI Builder Club. It's a community of developers sharing what's actually working, with weekly deep-dives on new tools and techniques.
Sources & Verification
This guide is written from hands-on testing, then cross-checked against primary sources - official documentation and first-party announcements. Field results and opinions are labeled as such. See our editorial standards.
Join AI Builder Club
$37/mo
Get the free newsletter
Weekly deep-dives on AI tools, automation workflows, and builder strategies. Join 5,000+ readers.
No spam. Unsubscribe anytime.