# Tune Cursor for large codebases

URL: https://developertoolkit.ai/en/cursor-ide/operate/performance-optimization/
Description: Make Cursor fast on a large repo: trim the index with .cursorignore, audit extensions, cap watchers and search, and prove each change with before/after numbers.

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](/en/cursor-ide/operate/performance/) instead.

## What you get from tuning Cursor

- 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

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:

```bash
# 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.

## 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:

```gitignore
# 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](/en/cursor-ide/build/large-codebase-strategies/). This page stays on the editor's own cost.

**Copy-paste prompt: propose a .cursorignore from evidence**

```text
Audit this repository for files that should be excluded from Cursor's index.

1. Run these from the repo root and show me the output:
   git ls-files | cut -d/ -f1 | sort | uniq -c | sort -rn | head -20
   git ls-files -z | xargs -0 du -k 2>/dev/null | sort -rn | head -20
2. For each directory or pattern that holds generated code, snapshots,
   fixtures, vendored or minified code, open two sample files to confirm
   what they are. Look for "generated" or "do not edit" headers.
3. Propose a .cursorignore. For every line give: the pattern, the number
   of files it removes, and one sentence of evidence.
4. Do NOT propose excluding src/, lib/, app/, tests you would extend, or
   any config file. List anything you were unsure about separately.

Do not write the file. Show me the proposal first.
```

## 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:

```json
{
  "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).

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

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.

**Copy-paste prompt: turn the extension list into a workspace policy**

```text
I will paste the output of "Developer: Show Running Extensions" below.

For this repository:
1. Detect which languages and tools are really used (file extensions,
   package.json, pyproject.toml, Dockerfile, CI config).
2. Classify each running extension as KEEP (needed for a language or tool
   in this repo), DISABLE-HERE (not used in this repo), or INVESTIGATE
   (activation time over 300 ms or activates on startup).
3. Write a .vscode/extensions.json with "recommendations" for the KEEP set
   and "unwantedRecommendations" for the DISABLE-HERE set.
4. Never put the TypeScript, ESLint or test-runner extensions this repo
   uses in the DISABLE-HERE list.

Show the table first, then the file.

<paste the Running Extensions list here>
```

## Keep worktrees from multiplying the cost

Local parallel agents in Cursor can run in Git worktrees, as [the Agents Window and Projects in Cursor](/en/cursor-ide/build/agents-window/) 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.

## 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:

**Copy-paste prompt: check the agent still finds the code**

```text
Without asking me for paths, find and open each of these, and tell me the
file and line where you found it:
1. The function that creates a user session
2. The main HTTP router or route table
3. The database schema or migration directory
4. One test file that covers the billing or payments code
5. The CI workflow that runs the test suite

If you cannot find any of them, say which one and list the ignore
patterns (.gitignore, .cursorignore) that might be hiding it.
```

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

**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](/en/cursor-ide/operate/token-management/) for context size and [model selection](/en/cursor-ide/quick-start/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`.

`.cursorignore` keeps files out of the index and away from the agent, but it is not a secrets control. Keep credentials out of the repository and out of the agent's environment. For checking a codebase for leaked secrets, see [the security audit workflow in Cursor](/en/cursor-ide/operate/security/).

## Where to go next after tuning Cursor

- [Essential configuration](/en/cursor-ide/quick-start/essential-configuration/) is the prerequisite: the settings every Cursor project starts from.
- [Large codebase strategies](/en/cursor-ide/build/large-codebase-strategies/) covers the working habits that keep a big repository manageable: scoped prompts, rules and monorepo workspaces.
- [Token management](/en/cursor-ide/operate/token-management/) shows how to cut the context you send, which also shortens responses.
- [Cursor operations overview](/en/cursor-ide/operate/) separates editor performance from application performance, security and monitoring.
- Using Claude Code as well? See [Claude Code performance and cost tuning](/en/claude-code/operate/performance-optimization/).
