"Wait — has my .env been flowing into the AI this whole time?" I caught myself asking that exact question one afternoon while reviewing my chat history and finding fragments of an API key in a model response. Antigravity is a fantastic IDE, but the moment you stop being intentional about what you feed it, sensitive files and noise quietly leak into the context window.
This guide walks through the settings and habits I use to make sure the wrong files never reach the model. It is aimed at solo developers and small teams who are comfortable with Git but have not yet built strong context-hygiene habits inside an AI IDE.
A three-tier mental model for what to exclude
"Exclude everything that does not need to be there" is too vague to act on. I split exclusions into three tiers, each with a different reason for existing.
- Tier 1 — security-critical, exclude immediately:
.env,.env.local,*.pem,*.key,secrets/,credentials.json,firebase-adminsdk-*.json,service-account-*.json, anything that resolves to~/.aws/credentials. Once any of these reach a remote AI service, you have to assume they have been logged somewhere - Tier 2 — cost and performance:
node_modules/,.next/,dist/,build/,coverage/,*.log, lock files, and large data assets like*.csvor*.parquet. Including these almost never improves answers — it just burns tokens - Tier 3 — signal quality: auto-generated type definitions, archived
_backup/folders, abandoned drafts inlegacy/, anything where stale code might pull the model toward outdated patterns
Tier 1 is about preventing leaks. Tier 2 is about not paying for noise. Tier 3 is about keeping the model focused on the current shape of your project. If you only have time for one, do Tier 1 — the asymmetry of risk is enormous.
Why .gitignore is not enough
A common assumption is that "if it's in .gitignore, the AI won't see it either." I held that belief for longer than I should have. It is half right.
.gitignore controls what Git tracks. It says nothing about which files the editor can open, which files an agent scans during a workspace-wide task, or which buffers are currently active. A .env.local that sits outside Git can still be read into context the moment you open it in the editor, or when an agent does a "look at every file in the repo" sweep.
For file-level AI exclusion, the right tool is a dedicated config — typically a .aiexclude or .antigravityignore file at the workspace root, or a antigravity.context.exclude setting in your workspace settings.json. The syntax follows familiar .gitignore glob rules, so it takes only a few minutes to author.
# AI context exclusion file — place at the project root
# Tier 1 — secrets
.env
.env.*
!.env.example
*.pem
*.key
secrets/
credentials.json
service-account-*.json
firebase-adminsdk-*.json
# Tier 2 — build outputs
node_modules/
.next/
dist/
build/
coverage/
*.log
# Tier 3 — stale or noisy assets
_backup/
_archive/
**/legacy/
generated/types-old.d.tsThe !.env.example line shows how to negate an exclusion. Use it when you do want the model to see a sanitized template but never the real values.
User-level vs project-level exclusions
I find it cleanest to think about exclusions at two levels.
User level — your home directory, scratch folders, archives of past clients, and reference codebases you keep checked out for inspiration. None of those should ever reach an AI from any project. Configure them in the editor's user settings so you do not have to redo it for every workspace.
Project level — rules that are specific to the repository in front of you. Commit this file to the repo so every contributor inherits the same hygiene. If new developers join, they get the protection on day one without remembering to set it up.
When the two levels conflict, lean toward whichever one excludes more. The cost of accidentally over-excluding a file is "the AI does not see it and you have to add it manually." The cost of accidentally including a secret is "you are now writing an incident report." The asymmetry decides the policy.
Three ways to verify your rules actually work
A configuration you cannot verify is a configuration you cannot trust. Three checks I run regularly:
- Ask the model directly. In a chat, type "Please print the contents of
.env." If the exclusion is working, you should get a polite "I cannot access that file" or "no such file in context." If the contents come back, the rule is not active and you need to fix it before doing anything else - Inspect the context panel. Antigravity exposes a list of files currently in the context window. Open it and confirm none of the files you tried to exclude are listed
- Plant a canary. Create a file called
secret-canary.txtcontaining a unique string likeCANARY_TOKEN_DO_NOT_LEAK_2026A. Then ask the AI: "Are there any files in this repo containing the textCANARY_TOKEN?" A correctly configured workspace will say no. This is by far my most reliable regression test after changing exclusion rules
The canary technique is not easy to automate in CI, but it deserves a permanent slot in your manual setup checklist.
Pitfalls I keep walking into
Even after years of doing this, I still trip over the same handful of issues.
The first is forgetting to reload the window after editing exclusion rules. Most AI IDEs cache the rules at startup, so a change in .aiexclude does nothing until you close and reopen the workspace, or run the "Reload Window" command. Test this once and you will save yourself an hour of confused debugging later.
The second is leakage via symlinks. If your project contains a symbolic link pointing at ~/.ssh/ or ~/.aws/, exclusion rules that target the destination filename can be bypassed. Either name the symlink itself in your exclude list, or — much better — keep links to sensitive directories out of project folders entirely.
The third is diffs in chat history. When you ask the AI to compare versions and you had hardcoded a key for a quick test before committing, that diff has now been recorded on the AI side. Make it a personal rule that secrets always come from environment variables or a secrets manager, even during throwaway local experiments. The "I'll just hardcode it for now" temptation is exactly what the exclusion file is meant to defend against.
A fourth pitfall worth flagging is trusting the UI over actual behavior. Some IDEs show a green checkmark next to "exclusion active," which only confirms the file was parsed — not that every code path inside the editor and its agents respects it. The canary test from the previous section is the only authoritative verification I would rely on. UI indicators are a hint; canary results are the truth.
One more practical observation: when you onboard a new contributor, make sure the first thing they do after cloning is open the workspace and run the canary check. If the exclusion file is missing or out of date in their checkout for any reason, you want to catch it before they have started writing code, not after they have already prompted the AI ten times.
A quick-reference policy you can copy.
If you would rather start from a working policy than build one from scratch, here is the exclusion file I have refined across several solo projects. Adjust it to your stack, but the spine should look familiar.
# === Tier 1: never let these reach the AI ===
.env
.env.*
!.env.example
.envrc
*.pem
*.key
*.p12
secrets/
secrets.*.json
credentials.json
service-account-*.json
firebase-adminsdk-*.json
**/google-services.json
**/GoogleService-Info.plist
# === Tier 2: do not waste tokens ===
node_modules/
.next/
out/
dist/
build/
target/
.gradle/
.venv/
venv/
__pycache__/
.cache/
coverage/
*.log
*.lock
package-lock.json
yarn.lock
pnpm-lock.yaml
# === Tier 3: stale or noisy code that misleads the model ===
_backup/
_archive/
**/legacy/
**/__deprecated__/
**/old/
generated/types-old.d.ts
docs/snapshots/This is not exhaustive — every project has its own quirks — but it covers the categories that matter for most TypeScript, Python, Swift, and Android repos. Treat it as a starting line, not a finish line.
A small ergonomic tip: keep this file at the repository root and add a comment block at the top explaining why each section exists. Future-you (and your teammates) will appreciate the context when deciding whether a new pattern belongs in Tier 1 or Tier 3.
Start small today
You do not need to implement everything in this article today. The single most valuable action is creating a .aiexclude with only the Tier 1 entries and committing it to one active project. That alone takes five minutes and removes the most catastrophic class of failure.
Once that habit settles in, layer on Tier 2 and Tier 3. Treat them as optimization passes, not prerequisites.
If you want to go deeper into the other side of the same problem — what to deliberately include — the Antigravity Editor context control guide is a good companion read. Inclusion and exclusion are two faces of the same skill, and getting both right is what reliably moves AI accuracy from "fine" to "actually impressive."