Fixing Roo Code That Still Reads Files Listed in .gitignore Despite Them Being Ignored by Git
A .env file, a build output folder, or a vendored dependency is correctly excluded from version control by .gitignore — and the agent still reads straight through it, searches it, or quotes its contents back. .gitignore and the agent's own ignore mechanism are two separate systems that happen to share a very similar name and purpose, and one of them isn't automatically aware of the other.
The Problem
A project's .gitignore correctly excludes a sensitive .env file, a node_modules directory, or a generated build output folder from version control — git status doesn't show it, and it was never committed. Despite that, during a Roo Code task, the agent reads straight through one of these supposedly-ignored files, includes its contents in a search result, or quotes a value from it directly in its response, as if the .gitignore entry had no effect on it at all.
Why It Happens
.gitignore is a convention understood by git and git-aware tooling, not a universal operating-system-level rule
.gitignore only has meaning to git itself and to tools that explicitly choose to read and respect it. A file listed there is simply invisible to git's own commands — git status, git add, and so on — but the file still exists completely normally on disk, fully readable by any program that doesn't specifically go out of its way to check that same .gitignore file before accessing it.
Roo Code's own file-access tools have their own separate ignore mechanism, .rooignore, which doesn't automatically inherit .gitignore's rules
Roo Code's file-reading and search tools respect .rooignore specifically, a file with its own syntax and its own purpose — keeping the agent itself away from specific paths, independent of git. Unless a project has both files in sync, or .rooignore explicitly mirrors or includes the same patterns as .gitignore, a path excluded from version control by one has no guaranteed relationship to whether the agent's own tools will read it.
A reasonable assumption — "it's ignored, so nothing will touch it" — doesn't hold once a second, independent tool is involved
Developers reasonably think of .gitignore as the single source of truth for "files that don't matter" in a project, because for the specific question of what git tracks, it is. Extending that same assumption to every other tool that might read files in the project — including an AI agent's own file-access layer — requires that tool to specifically opt into reading the same ignore rules, which isn't something that happens automatically just because the file exists.
The Fix
1. Create a .rooignore file specifically, rather than assuming .gitignore already covers it
# .rooignore
.env
.env.local
node_modules/
dist/
build/
Since .rooignore is the file Roo Code's own tools actually check, creating it explicitly — rather than relying on .gitignore alone — is the direct fix that actually stops the agent from reading the paths in question, regardless of what git itself does with them.
2. Keep .rooignore and .gitignore in sync deliberately, since they serve closely related but not identical purposes
# A quick way to seed .rooignore from an existing .gitignore as a starting point,
# then adjust from there for anything Roo-specific:
cp .gitignore .rooignore
Starting .rooignore from a copy of the project's existing .gitignore captures the overlap between "files git shouldn't track" and "files the agent shouldn't need to read" quickly, while leaving room to diverge afterward for cases where the two lists genuinely should differ.
3. Recognize cases where the two lists should deliberately differ, rather than assuming they must always match exactly
# .gitignore might exclude build output because it's regenerated and shouldn't be committed,
# but the agent may legitimately need to read that same output to debug a build issue —
# a case where .rooignore intentionally does NOT mirror .gitignore for that specific path.
A path excluded from git for one reason (it's regenerated, it's an environment-specific secret) doesn't automatically mean the agent should never read it for any reason — a build-debugging task is a legitimate case where the agent genuinely needs access to generated output that git correctly never tracks, so treating the two ignore files as always needing to match exactly can be the wrong call in specific situations.
4. For anything genuinely sensitive — secrets, credentials — treat .rooignore as a courtesy, not a security boundary
An .env file should still never contain anything that would be catastrophic if an
AI model's context window, logs, or any tool call result ever included it — .rooignore
reduces the chance of that happening by default, but it isn't a guaranteed, audited
security control the way file permissions or a secrets manager would be.
Treating .rooignore as a best-effort reduction in exposure rather than an airtight guarantee is the realistic framing for anything genuinely sensitive — the actual security boundary for credentials should be a secrets manager or environment-level access control, with .rooignore as one additional layer rather than the only one relied on.
Why This Works
Each step addresses the core misunderstanding that .gitignore and the agent's own ignore mechanism are the same system from a different angle. Creating .rooignore explicitly is the direct fix, since it's the file the agent's tools actually check. Seeding it from .gitignore captures the genuine overlap between the two lists quickly. Recognizing where they should deliberately differ avoids over-correcting into blocking the agent from files it legitimately needs. And treating .rooignore as a courtesy rather than a hard security boundary sets the right expectation for anything where the stakes of a miss are genuinely high.
Conclusion
A file correctly excluded from git by .gitignore still being read by Roo Code isn't the agent ignoring a rule it should be following — it's two separate, independently-maintained ignore mechanisms that happen to look similar, where only one of them, .rooignore, is actually consulted by the agent's own file-access tools. Create .rooignore explicitly rather than assuming .gitignore already covers it, seed it from the existing .gitignore as a starting point, recognize the specific cases where the two lists should genuinely differ, and treat .rooignore as a best-effort reduction in exposure rather than a guaranteed security boundary for anything truly sensitive.
