Tune Cursor for large codebases
PLCursor slows down on large repositories for four local reasons: an index full of generated and vendored files, extensions that activate and compete for CPU, file watchers and search walking build output, and a TypeScript server short of memory. Tuning Cursor means fixing those four in that order, and measuring each change before and after instead of judging by feel.
You open a 12-package monorepo in the morning. Completions arrive late, the agent pauses before it reads its first file, the fans spin, and the indexing indicator has not settled since you pulled. Before you blame the model or the network, check what Cursor is actually indexing, watching and running on your machine. That part is yours to fix, and the fix lives in files you can commit.
This page is for the developer whose editor is slow and for the tech lead who wants the fix committed once for the whole team. If your application is slow rather than the editor, you want profiling and fixing application performance with Cursor instead.
What you get from tuning Cursor
Section titled “What you get from tuning Cursor”- A
.cursorignorebuilt from your repository’s real file counts, not from a generic template. - A committed
.vscode/settings.jsonthat stops the file watcher and search from walking build output. - An extension audit with a repeatable way to find the one extension that eats the CPU.
- A baseline-and-recheck table that proves the tuning worked, plus a probe that proves the agent can still find your code.
Record a baseline before you change anything
Section titled “Record a baseline before you change anything”Tuning without a baseline turns into guesswork. Take five readings now, write them down, and take the same five after each change.
-
Indexed files. Open Cursor Settings and find the codebase indexing section. Note the number of indexed files.
-
Startup time. Run Developer: Startup Performance from the Command Palette (
Cmd/Ctrl+Shift+P). Note the total time to a ready window. -
Extension activation. Run Developer: Show Running Extensions. It lists every active extension with its activation time. Note the five slowest.
-
Process memory and CPU. Run Developer: Open Process Explorer. Note the memory and CPU of the extension host, the file watcher and the TypeScript server (
tsserver). -
Time to first agent action. Start a new agent chat and send the same fixed prompt each time, for example “Find where user sessions are created and list the files”. Time how long it takes to open its first file.
Then measure the repository itself from a terminal at the repo root. These git commands show where the files are:
# Tracked files per top-level directory, largest firstgit ls-files | cut -d/ -f1 | sort | uniq -c | sort -rn | head -20
# Ignored or untracked directories sitting on disk (build output, caches)git ls-files --others --ignored --exclude-standard --directory | head -30
# The 20 largest tracked files, in KBgit ls-files -z | xargs -0 du -k 2>/dev/null | sort -rn | head -20The first command usually surprises people. Generated API clients, test snapshots, vendored SDKs and fixture data are committed, so .gitignore does not hide them, and they often outnumber the code you write.
Trim the index with .cursorignore
Section titled “Trim the index with .cursorignore”.cursorignore uses .gitignore syntax and lives at the repository root. Cursor’s agent code reads both .gitignore and .cursorignore (checked in @cursor/sdk 1.0.32, 2026-09-26). So a directory your .gitignore already lists needs no second entry. Use .cursorignore for files you commit but do not want indexed or read by the agent.
A starting point for a TypeScript monorepo, built from the kinds of paths the commands above tend to find:
# Committed generated code**/__generated__/**/*.generated.tspackages/api-client/src/gen/prisma/generated/
# Test snapshots and large fixtures**/__snapshots__/tests/fixtures/large/
# Vendored or minified third-party codevendor/**/*.min.js**/*.min.css
# Lockfiles: large and rarely useful as contextpnpm-lock.yamlpackage-lock.jsonyarn.lockLeave lockfiles out of .cursorignore if you want the agent to answer dependency-version questions. Add a line only when the file-count output justifies it. Never exclude source (src/, lib/, app/), tests you want the agent to extend, or configuration it needs to read. An excluded file is invisible to the agent, and an agent that cannot see your code writes a new version of it.
After you edit the file, trigger a resync from the indexing section of Cursor Settings and wait for the count to settle. Keep the index count you recorded next to the new one.
For monorepo-wide strategy, such as opening only the packages you work in as a multi-root workspace, see large codebase strategies. This page stays on the editor’s own cost.
Stop the watcher and search from walking build output
Section titled “Stop the watcher and search from walking build output”Cursor inherits VS Code’s file watcher and search, and both have their own exclude lists that .cursorignore does not touch. Put the settings in .vscode/settings.json and commit them, so every teammate gets the same result:
{ "files.watcherExclude": { "**/dist/**": true, "**/build/**": true, "**/.next/**": true, "**/coverage/**": true, "**/.turbo/**": true }, "search.exclude": { "**/dist": true, "**/build": true, "**/coverage": true, "**/*.min.js": true, "**/*.map": true }, "typescript.tsserver.maxTsServerMemory": 6144}files.watcherExcludestops change events from build and test output. VS Code’s default list already covers.git/objectsand.git/subtree-cache, so you add only your own output directories.search.excludekeeps the editor’s text search out of the same directories, so results and the search process stay small.typescript.tsserver.maxTsServerMemoryraises the TypeScript server’s memory cap from its 3,072 MB default. Raise it only if Process Explorer showstsservernear the cap or the server restarts. VS Codemaindeprecatestypescript.tsserver.maxTsServerMemoryin favour ofjs/ts.tsserver.maxMemory(both default 3072, checked 2026-09-26). Search formaxMemoryin the Settings UI and use the key your Cursor build shows without a deprecation strike-through.
Older guides also recommend files.maxMemoryForLargeFilesMB. VS Code removed that setting, so it no longer does anything (not present in files.contribution.ts on VS Code main, checked 2026-09-26).
Audit extensions that compete for CPU
Section titled “Audit extensions that compete for CPU”Every VS Code extension you install runs in Cursor’s extension host. One busy extension can slow completions, the agent’s edits and saves for the whole window.
-
Open Developer: Show Running Extensions and scan the activation times. Anything that activates on startup (
*) and takes hundreds of milliseconds is a candidate. -
Disable language extensions for languages this workspace does not use. Use Disable (Workspace) in the Extensions view, so the extension still works in other projects.
-
Keep the language services your project depends on. Disabling TypeScript, ESLint or your language’s server removes the diagnostics the agent reads when it checks its own edits.
-
If the slowdown remains and you cannot see the cause, run Help: Start Extension Bisect. It disables half your extensions per round and asks whether the problem persists, until it names the culprit.
-
Record which extensions the team should not install in
.vscode/extensions.jsonunderunwantedRecommendations, so the decision outlives your machine.
Keep worktrees from multiplying the cost
Section titled “Keep worktrees from multiplying the cost”Local parallel agents in Cursor can run in Git worktrees, as the Agents Window and Projects in Cursor describes, and each worktree is a full checkout that needs its own dependencies. Three habits keep that cost down:
- Install dependencies with a package manager that reuses a global store, such as
pnpm,bunoruv, so a new worktree links packages instead of downloading them again. - Run your dependency setup in each new worktree before the agent starts. Cursor can create worktrees for its agents; commit one setup script every agent runs first (the Agents Window page shows an example).
- Clean up with Git itself.
git worktree listshows every checkout, andgit worktree pruneremoves records for worktrees whose directories are gone.
Prove the tuning worked
Section titled “Prove the tuning worked”Take the five baseline readings again and put them side by side. A tuning change that moves none of them was not the bottleneck, so revert it and keep the configuration small.
| Reading | Where | What “better” looks like |
|---|---|---|
| Indexed files | Cursor Settings, indexing section | Down by roughly the file counts your .cursorignore lines claimed |
| Startup time | Developer: Startup Performance | Lower, or unchanged if extensions were not the cause |
| Slowest extensions | Developer: Show Running Extensions | Nothing unexplained activating on startup |
Extension host, watcher, tsserver | Developer: Open Process Explorer | Lower idle CPU; tsserver below its memory cap |
| Time to first agent action | Your fixed prompt | Shorter, with the same files found |
Speed is only half the check. The other half is that the agent can still see everything it needs. Run a probe after every .cursorignore change:
Replace the five targets with five that matter in your repository, and keep the list in the pull request that changes .cursorignore. A tech lead reviews that pull request like any other configuration change: the file-count evidence, the before/after table and a passing probe are the sign-off, and no one has to read the patterns line by line.
When tuning Cursor does not help
Section titled “When tuning Cursor does not help”The index count barely moved. The large directories are probably committed, so .gitignore never covered them and your .cursorignore pattern does not match them. Rerun the file-count command, compare its paths with your patterns exactly, and resync the index.
The agent writes code that already exists. You excluded too much. Run the probe prompt, find the pattern that hides the missing file, narrow it, and resync.
Diagnostics or type errors disappeared from the agent’s checks. You disabled a language extension this project needs. Re-enable it for the workspace and run Developer: Reload Window.
tsserver keeps restarting. Process Explorer shows it at its memory cap. Raise typescript.tsserver.maxTsServerMemory (or js/ts.tsserver.maxMemory), then run TypeScript: Restart TS Server. If it still fails, narrow the include in tsconfig.json or split the repository with project references, because the server is loading more than the package you work in.
The editor is fast but the agent is slow. The local bottleneck is gone, and what remains is the model call, the network or the size of the context you send. Check token management for context size and model selection for the model trade-off.
Worktrees fill the disk. Run git worktree list, remove the ones whose branches are merged with git worktree remove <path>, then git worktree prune.
Where to go next after tuning Cursor
Section titled “Where to go next after tuning Cursor”- Essential configuration is the prerequisite: the settings every Cursor project starts from.
- Large codebase strategies covers the working habits that keep a big repository manageable: scoped prompts, rules and monorepo workspaces.
- Token management shows how to cut the context you send, which also shortens responses.
- Cursor operations overview separates editor performance from application performance, security and monitoring.
- Using Claude Code as well? See Claude Code performance and cost tuning.