Skip to content

Cursor 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.

  • A .cursorignore built from your repository’s real file counts, not from a generic template.
  • A committed .vscode/settings.json that 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.

  1. Indexed files. Open Cursor Settings and find the codebase indexing section. Note the number of indexed files.

  2. Startup time. Run Developer: Startup Performance from the Command Palette (Cmd/Ctrl+Shift+P). Note the total time to a ready window.

  3. Extension activation. Run Developer: Show Running Extensions. It lists every active extension with its activation time. Note the five slowest.

  4. 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).

  5. 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:

Terminal window
# Tracked files per top-level directory, largest first
git 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 KB
git ls-files -z | xargs -0 du -k 2>/dev/null | sort -rn | head -20

The 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.

.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.ts
packages/api-client/src/gen/
prisma/generated/
# Test snapshots and large fixtures
**/__snapshots__/
tests/fixtures/large/
# Vendored or minified third-party code
vendor/
**/*.min.js
**/*.min.css
# Lockfiles: large and rarely useful as context
pnpm-lock.yaml
package-lock.json
yarn.lock

Leave 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.watcherExclude stops change events from build and test output. VS Code’s default list already covers .git/objects and .git/subtree-cache, so you add only your own output directories.
  • search.exclude keeps the editor’s text search out of the same directories, so results and the search process stay small.
  • typescript.tsserver.maxTsServerMemory raises the TypeScript server’s memory cap from its 3,072 MB default. Raise it only if Process Explorer shows tsserver near the cap or the server restarts. VS Code main deprecates typescript.tsserver.maxTsServerMemory in favour of js/ts.tsserver.maxMemory (both default 3072, checked 2026-09-26). Search for maxMemory in 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).

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.

  1. Open Developer: Show Running Extensions and scan the activation times. Anything that activates on startup (*) and takes hundreds of milliseconds is a candidate.

  2. 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.

  3. 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.

  4. 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.

  5. Record which extensions the team should not install in .vscode/extensions.json under unwantedRecommendations, so the decision outlives your machine.

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, bun or uv, 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 list shows every checkout, and git worktree prune removes records for worktrees whose directories are gone.

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.

ReadingWhereWhat “better” looks like
Indexed filesCursor Settings, indexing sectionDown by roughly the file counts your .cursorignore lines claimed
Startup timeDeveloper: Startup PerformanceLower, or unchanged if extensions were not the cause
Slowest extensionsDeveloper: Show Running ExtensionsNothing unexplained activating on startup
Extension host, watcher, tsserverDeveloper: Open Process ExplorerLower idle CPU; tsserver below its memory cap
Time to first agent actionYour fixed promptShorter, 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.

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.