Open a moderately large project and Cursor’s status bar reads Indexing 5% for half an hour, or finishes indexing and immediately re-triggers, with your fans at max. 90% of the time Cursor isn’t crashed — it’s trying to index node_modules/, dist/, .git/, and other directories that should never be indexed. On a mid-size frontend project those alone easily exceed a million files, which no consumer SSD will index quickly. This article gives the .cursorignore template that fixes it, the rebuild command, and how to confirm the index is healthy.
Common causes
Ordered by hit rate, highest first.
1. node_modules/ isn’t excluded
Most common. A mid-size frontend’s node_modules/ is 300k–800k files, two orders of magnitude more than your source. Cursor should skip it by default, but odd workspace configs or symlinks occasionally pull it back in.
How to spot it: find node_modules -type f | wc -l. If > 100,000 and Cursor stays on Indexing forever, this is almost certainly it.
2. Build output directories (dist/ / build/ / .next/ / .astro/)
On projects with hot reload, build output is rewritten constantly, so Cursor sees file changes and re-indexes, creating an “index finished → detected changes → re-index” loop.
How to spot it: Indexing re-triggers repeatedly while your dev server is running, and stops the moment you kill the dev server.
3. .git/ object directory
Large repos can have hundreds of thousands of pack files in .git/objects/. Cursor usually skips it, but cloned mirrors or LFS-heavy repos sometimes leak through.
How to spot it: du -sh .git/. If > 500MB and not explicitly ignored, suspect it.
4. Cache and log directories
.cache/, .turbo/, .vercel/, logs/, coverage/ are written to constantly and trigger the same re-index loop.
How to spot it: When Cursor re-indexes, sort Activity Monitor by disk I/O for the Cursor process and see which directory is being scanned.
5. Monorepo subpackages all contribute artifacts
apps/web/.next, apps/api/dist, packages/ui/storybook-static all indexed together stack to millions of files. Each subpackage needs its own .cursorignore, or the root needs wildcard rules.
How to spot it: find . -name dist -o -name .next -o -name build -type d. If > 3 hits with no ignore coverage, that’s the problem.
Shortest path to fix
Step 1: Write a thorough .cursorignore
At project root, create or edit .cursorignore:
# Dependencies
node_modules/
# Version control
.git/
# Build output
dist/
build/
out/
.next/
.astro/
.svelte-kit/
.nuxt/
.output/
# Caches
.cache/
.turbo/
.vercel/
.parcel-cache/
.pytest_cache/
__pycache__/
# Test coverage
coverage/
.nyc_output/
# Logs and lockfiles
*.log
*.lock
For monorepos, drop a local .cursorignore into each subpackage:
# packages/web/.cursorignore
.next/
.turbo/
Step 2: Force a full index rebuild
.cursorignore changes don’t auto-rebuild — you must trigger it.
Cmd/Ctrl + Shift + P → "Cursor: Reset Index"
Or more thoroughly (recommended for the re-index loop case):
# Quit Cursor, then wipe the workspace index cache
rm -rf ~/Library/Application\ Support/Cursor/User/workspaceStorage/*/cursorIndex
# Linux:
rm -rf ~/.config/Cursor/User/workspaceStorage/*/cursorIndex
# Relaunch Cursor
Step 3: Wait and confirm
Restart Cursor and reopen the project:
- Status bar briefly shows
Indexing 0% - Within 1–3 minutes it switches to
Indexed(mid-size projects); 5–10 minutes for large monorepos - If still incomplete after 10 minutes, go back to Step 1 and check for missed artifact directories
Open Settings → Features → Codebase Indexing and check “Files Indexed.” Healthy mid-size projects are typically 5k–30k. If you’re still at 100k+, your ignore list isn’t taking effect.
Step 4: Isolate dev server output too
If indexing finishes but the dev server keeps triggering re-runs, add dev output paths to .cursorignore. Vite / Webpack let you direct build output into a single ignored directory:
// vite.config.ts
export default {
build: {
outDir: 'dist', // already in .cursorignore
},
cacheDir: '.cache/vite', // already in .cursorignore
}
Prevention
- Commit
.cursorignorethe moment you create a new repo, and maintain it alongside.gitignore - Don’t scatter cache / build output dirs in odd locations; keep them at the root
- For monorepos, drop a
.cursorignorein each subpackage — don’t rely on root wildcards to cover all variants - After installing a new dependency, changing build tools, or adding a generator, manually Reset Index — don’t wait for a loop
- Always ignore directories your dev server or hot reload writes to frequently (
.cache/,.turbo/)
Related
- Cursor missed the full project context
- Cursor keeps reading the wrong files
- Cursor cannot apply edits
- Multiple AI agents created conflicts
- AI pre-commit review workflow
Tags: #Cursor #AI coding #Debug