Cursor Basics
Cursor Codebase Indexing: How the AI Understands Your Repository
Cursor indexes your codebase into searchable vectors using its own embedding model. Indexing starts automatically when you open a workspace and finishes in the background; semantic search becomes available at 80% completion. Code is encrypted at indexing time and never stored in plaintext. Cursor only stores embeddings, not your source.
On this page
What does codebase indexing do in Cursor?
When you open a project, Cursor reads your files and converts them into vector embeddings using a custom embedding model. Those embeddings let the agent answer questions like "where do we handle authentication?" or "find all places that call this function" by meaning, not just by exact string match.
Index ready — Exact Search, then @Codebase cites the file
0:40 · narratedRead this demo as text
- Open Cursor Settings, Indexing and Docs. Instant Grep is on — Cursor indexes this repo locally. There is no separate Resync percentage here; the toggle is the control.
- Exact Search for filterRecentSearches. Three hits in two files — the index is ready enough to grep.
- Attach Codebase, then ask where the helper lives. Semantic context rides with the question.
- The answer cites recentSearches.ts. Same model — the indexed codebase made the citation specific.
Practice next: Practice this yourself in the hands-on module.
Simulated Cursor 3.12 (macOS, light) — beta educational reconstruction, not the real product.
Semantic search shines when the relevant code isn't named the way you'd guess, which in a codebase with a few years on it is most of the time. Grep needs the exact string; the embedding index matches on meaning, so the agent can find the auth handler even if it's called gatekeeper.
None of that retires grep. Cursor's harness runs both, and grep is the half that wants an exact string. If you know the function is called getSessionToken, type that rather than describing it.
When the agent finds the right file without you specifying it, it used the semantic index. You gave it a natural language description of the task; it turned that into a query against the embeddings and pulled the most relevant code segments.
This is covered hands-on in Cursor First Hour — 4 short modules, free to read.
How does Cursor build and maintain the index?
Indexing runs on its own once you open a workspace, and it keeps itself current as you work. Four points are worth knowing: when it starts, when search turns on, how it stays fresh, and when an idle index gets cleared.
- 1You open a workspace, and Cursor begins indexing immediately.
- 2Semantic search becomes available at 80% completion; a progress indicator appears in the status bar.
- 3The index syncs automatically every 5 minutes, processing only changed files (not the whole repo each time).
- 4If you haven't opened the project in 6 weeks, the hosted index is deleted; reopening triggers a fresh index.
You meet the 80% gate on day one. The five-minute sync shows up later, usually after a big checkout, when the index trails the working tree for a minute or two and questions about the files you just pulled come back thin.
The six-week deletion catches people months after they last thought about it. A repo nobody has opened since the summer comes back as a fresh index, so the first question you ask lands against something half-built. The instinct at that point is to change models, which does nothing for an index that is still being built. I would wait for the indexing indicator to report done before reading anything into a weak answer.
Not everything in the folder ends up in the index. Cursor follows your ignore files: anything matched by .gitignore or .cursorignore stays out, and so do binaries and files past the size limit. Here is what falls on each side.
- Included
- All files not covered by .gitignore or .cursorignoreA file listing paths Cursor must never index or read, kept separate from .gitignore. Press Enter for the full definition..
- Excluded
- Files listed in .gitignore or .cursorignoreA file listing paths Cursor must never index or read, kept separate from .gitignore. Press Enter for the full definition.; binary files; very large files above the size limit.
- Scope
- The full workspace (all files in the opened folder and its subfolders).
Cursor has not put a number on that size limit anywhere I have looked, so read it as a reason to keep generated files out rather than a threshold to tune against.
How does the index get pulled into a prompt?
The index is only half the story. The other half is how Cursor assembles context every time you hit send. LLMs have no short-term memory, so Cursor reminds the model of the conversation on each turn. Every prompt, it summarizes everything discussed so far in the chat and packages that summary with your new message, then pulls in the relevant code via the index.
A field engineer's description of the mechanic: rather than appending every message and growing the pile, Cursor maintains one coherent storyline and refines it each turn. That keeps context utilization efficient instead of bloating the window with stale back-and-forth.
Every time you send a prompt, we're actually summarizing everything that's been discussed so far in that chat session. It's not just linearly additive. We're trying to clarify and refine and build this clear storyline.
Interactive diagram. Step through it with the Next and Previous controls below, or Tab to a region to read its detail.
The per-prompt lifecycle: summarize the conversation, retrieve code from the index, package it for the model.
That percentage you see is context utilization, measured in tokens. A token is just a unit of volume, like a GB or MB. It counts the raw amount of input a model can take. Because Cursor re-summarizes rather than stacks, you get more useful work out of the same window before utilization climbs.
Retrieval runs per prompt, which is more useful than it sounds. The query comes from what you typed, so rewording a question that came back empty can pull different code out of the same index. Cheap enough to try before you go hunting for the file yourself.
Is my source code safe during indexing?
Cursor encrypts code chunks during indexing; source is held in memory briefly, then discarded. Filenames are obfuscated and code content is never stored in plaintext on Cursor's servers. What Cursor stores are encrypted embeddings (numeric vectors), which cannot be reversed into your original code.
- Data
- Source code
- What Cursor stores
- Never stored in plaintext
- What Cursor discards
- Discarded after embedding is computed
- Data
- Filenames
- What Cursor stores
- Obfuscated identifiers
- What Cursor discards
- Real filenames not stored on server
- Data
- Embeddings
- What Cursor stores
- Encrypted vector representations
- What Cursor discards
- Deleted after 6 weeks of inactivity
| Data | What Cursor stores | What Cursor discards |
|---|---|---|
| Source code | Never stored in plaintext | Discarded after embedding is computed |
| Filenames | Obfuscated identifiers | Real filenames not stored on server |
| Embeddings | Encrypted vector representations | Deleted after 6 weeks of inactivity |
Source: cursor.com/blog/secure-codebase-indexing
The table describes the steady state. What decides whether it applies to a given file is the order you did things in: an embedding gets computed the first time Cursor sees a file, so an ignore rule only guarantees a path was never indexed if the rule was in place before that first open. Whether adding it later clears what was already stored is not something Cursor documents, and the only published figure is the six-week inactivity window.
A five-person team and a five-hundred-person one do not reach for the same control here. For the small team I would say .cursorignore plus a habit, and that is too weak as stated, because habits do not survive a new hire. Put the file in the template every repo starts from. On Enterprise, CMEK encrypts the embeddings with a key you hold, which covers who can decrypt what the index stored.
Cursor's blog post on secure codebase indexing details the technical implementation. For enterprise teams with strict data-handling requirements, read cursor.com/security alongside this before rollout.
How do I control what gets indexed?
The index respects .gitignore automatically. To exclude additional files without adding them to .gitignore, create a .cursorignore file at the project root. It uses the same syntax as .gitignore.
- `node_modules/`, `dist/`, `build/`: typically already in
.gitignore; excluded by default. - Secrets or env files: add them to
.cursorignoreif not already in.gitignore. - Large generated files: files above Cursor's size limit are excluded automatically; very large ones slow indexing.
- Sensitive internal docs: add to
.cursorignoreif you don't want them fed to the semantic search.
.cursorignore reaches further than the index, which the list above does not say. Cursor describes it as excluding files from semantic search, agent file reading and context selection. Build output can go there safely, and Cursor's own performance guidance says to put generated code and build artifacts there.
The file to weigh first is a generated API client somebody reads every week. Once it is ignored you cannot hand it to the agent on purpose either.
Don't confuse repo size with index control. A C++ program with thousands of source files isn't large by Cursor's standards; it handles very large monorepos performantly. A Cursor demo ran against Grafana, roughly 70K stars and about ten years old, and indexing behaved the way it does on a new project. That is one demo, though, and what it shows is that age and file count alone do not break indexing. How your own repo behaves depends on what is sitting in it.
If you want to hand a team a smaller subset of the codebase, that's a scoping decision, not an indexing one. Reach for .cursorignore to keep things out of the index, or a team rule to constrain what the agent works against.
A Cursor support engineer's framing: you're fundamentally "just opening a folder". The experience is about what you populate in it. Cursor's own team pulls their website out into a sub-repository so people can iterate on it for documentation without dragging the whole product codebase along.
You could use a team rule if you wanted, or use .cursorignore to exclude certain things from being indexed.
When should I still add context manually with @?
The semantic index is automatic context the agent searches in the background. For tasks where you know exactly which files are relevant, adding them manually with @filename is faster than hoping the index surfaces the same ones, and in my experience more reliable.
- Situation
- You know the exact file to edit
- Best approach
- @filename (explicit is faster)
- Situation
- You want the agent to find related code across the repo
- Best approach
- Describe the task; let the index work
- Situation
- Bug hunt across unfamiliar code
- Best approach
- Let the agent search semantically first, then pin files with @ once found
- Situation
- Architecture question spanning many modules
- Best approach
- Use @codebase or let Max Mode + index cover the breadth
| Situation | Best approach |
|---|---|
| You know the exact file to edit | @filename (explicit is faster) |
| You want the agent to find related code across the repo | Describe the task; let the index work |
| Bug hunt across unfamiliar code | Let the agent search semantically first, then pin files with @ once found |
| Architecture question spanning many modules | Use @codebase or let Max Mode + index cover the breadth |
Explicit @ context and semantic indexing are complementary, not alternatives.
A file you created in the last minute may not have synced into the index yet, and until it does the mention is the only route to it. That is the case where the speed argument stops being the point.
The rest of the when-to-attach question is answered on the @ mentions page, which carries Cursor's own guidance on when to skip the mention.
Frequently asked questions
Can I check whether my codebase has finished indexing?
Yes. A progress indicator in the Cursor status bar shows the indexing percentage. Semantic search is available from 80% onward. You can also open Settings → Cursor → Indexing to see the current index status.
Does codebase indexing work on private or air-gapped repositories?
Indexing requires an internet connection to Cursor's servers to compute and store the embeddings. Air-gapped or fully offline deployments cannot use the hosted index. For strict air-gap requirements, Cursor does not currently offer a self-hosted embedding server; this is a known gap in the enterprise offering.
How does the index handle very large repositories?
Cursor indexes all files up to a per-file size limit and excludes files in ignore lists. For very large monorepos, the initial index takes longer but still completes in the background. Semantic search becomes available at 80%, so you can start working before indexing is complete.
Does adding @codebase in a prompt use the semantic index?
Yes. @codebase triggers a semantic search against the index, retrieves the most relevant code segments and injects them as context. It is the explicit way to invoke the same indexing that the agent uses automatically.
If I add new files, do they get indexed automatically?
Yes. The automatic sync runs every 5 minutes and processes only changed or new files. New files are indexed within a few minutes of being saved without any manual action.
Sources & last verified
- Cursor - Codebase Indexing
- Cursor - Semantic Search in Agent
- Cursor - Secure Codebase Indexing (Blog)
- Cursor - Improving agent with semantic search (Blog)
Cursor ships frequently. Last updated July 28, 2026.
Keep reading
Rather do it than read about it? Run 11 interactive Cursor walkthroughs in a simulated editor. Free, no account needed.