The index and the ignore files answer two different questions, and confusing them is expensive. The index determines what the agent can find quickly. The .cursorignore file determines what is unavailable to it at all: the listed paths are closed to the agent, to editor suggestions, to pointed edits and to mentions. Next to it there is a separate file that excludes only from the index - the contents stay available for direct reading. The difference is one line of configuration and a whole class of expectations: in the first case the file does not exist for the editor, in the second it simply is not found by search.
The naive model is to write secrets into the ignore file and consider the question closed. It breaks on a simple fact: an exclusion applies to the editor's own features but does not stop the terminal and does not limit the tools of connected MCP servers. A command run by the agent reads the file system just like any process with your rights. The documentation warns directly that ignoring does not provide full protection - and that is worth taking seriously rather than as a formal caveat.
Hence the correct role of exclusions: they are context hygiene, not a security boundary. They remove from view what should not end up in requests and in the index - secrets, dumps, generated code, vendored directories. Real protection is built by other means: file-system permissions, the sandbox, approvals, hooks and separate credentials for the agent. One complements the other but does not replace it, and telling them apart matters precisely because the first looks like the second.
It helps to see a sensible ignore list once. Below are environment files in all their forms, credential files, private keys, the build directory and generated vendored files. The syntax is familiar from .gitignore, which is convenient, but it has a subtlety: a negation will not bring back a deeply nested file if the parent directory is excluded entirely - the path has to be opened level by level.
The index itself is arranged more carefully than one might think. Paths are encrypted, search works on embeddings, source code is not stored in the clear, and file chunks are held in memory only for the duration of indexing. For custom path encryption there is a separate key file. The practical conclusion is not to relax but to understand exactly which data leaves the machine and in what form: the question has a documented answer, and it can be cited in a conversation with security.
Multi-root workspaces are a separate case. Every root is indexed on its own, and features that need a single shared git root may be unavailable in such a configuration. That is not a defect but a consequence of the design: if you keep three repositories in one window, some mechanisms simply do not know which one to treat as the main one. It is better to plan for that in advance than to discover it in the middle of a task.
The practical scenario that makes the difference between protection and hygiene worth keeping looks like this. The agent runs a command, the command fails, and the output contains a connection string with a password. The ignore file has nothing to do with it: it closes contents to the editor's features, while the output came from a process and landed in the conversation in full. Hence the practice: separate credentials for agent work, environment variables visible only to the process that needs them, and the habit of attaching a fragment of the output rather than the whole buffer.
The second reason to write exclusions carefully is search quality. Generated directories, built bundles and vendored copies repeat the source code almost word for word, so search honestly finds them on a par with the original. The sign is familiar to everyone who has been through it: the agent confidently edits a file inside the build directory, the check passes, and the edit disappears on the next build. Excluding such directories from the index costs less than explaining this in the instructions every time.
The engineering conclusion is simple. Exclusions are written not as an afterthought but together with the project's first setup: the secrets file, build and vendor directories, everything generated. That lowers both the cost of context and the chance of a leak into the transcript at once. But where the cost of a mistake is real, permissions, the sandbox and separate credentials stand next to it without fail.
The typical failures are predictable. Treating the ignore file as protection from the terminal and MCP. Writing a negation inside an excluded directory and being surprised the file is still invisible. Forgetting about a multi-root workspace and expecting features that require a single git root to work. And leaving generated directories in the index, paying for them in every search.
# .cursorignore - .gitignore syntax
**/.env
**/.env.*
**/credentials.json
**/*.pem
dist/
vendor/generated/**
# a negation will not bring a file back if the parent directory is excluded entirely