I'm Masaki Hirokawa — an indie developer who has been shipping iOS and Android apps since 2014 (about 50 million downloads in total across our wallpaper and meditation apps) and now runs Dolice Labs, a set of four AI-focused sites. Since moving my refactoring work over to Antigravity, the single most frustrating issue has been small: pieces of an agent's diff quietly disappearing after I click Apply. The root cause turned out to be a race between Auto Save and the agent's streaming writes, and three settings changes have been enough to stop it for good.
What the symptom looks like
You ask the agent something like "split this function and add tests for it." The diff preview looks correct. You hit Apply. The original file updates, but the newly created test file ends up as an empty buffer — or sometimes the new file is never created at all. The confusing part is that the editor pane still shows the right content for a second, then a refresh of the file tree or a tab switch reveals that the changes have partially rolled back.
In my own wallpaper-app refactor I tried splitting SettingsViewController.swift into three files four times in one afternoon. Each time the same one of the three new files came out written-but-empty. I spent half a day chasing the wrong cause before I realised the autosave timer was the real culprit.
Reproduction conditions
I've confirmed the issue tends to fire when three things line up:
Files: Auto Saveis set toafterDelay(oronFocusChange/onWindowChange)- The agent edits an existing file and creates a new file in the same transaction
- Three or more dirty tabs (those with the dot indicator) are already open
In short, the editor's "flush unsaved buffers to disk shortly" behaviour collides with the agent's "stream chunks of text into a newly created file" behaviour, and they end up fighting for the same file descriptor. If the editor wins and writes an empty buffer first, the agent reads the now-existing file, decides it shouldn't overwrite a file that's already there, and skips the rest of its writes. The result: an empty file you never asked for.
What's actually happening
Antigravity's agent branches on whether the target file is dirty (unsaved):
- Not dirty: it writes through its virtual filesystem layer directly to disk, then asks the editor to reload
- Dirty: it routes through the WorkspaceEdit API, replacing the editor buffer and leaving saving up to the user
With Auto Save on, creating a new file starts the afterDelay timer immediately. If that timer fires while the agent is still streaming the body, the editor flushes the buffer as an empty string and clears the dirty flag. The next streamed chunk hits the agent's first branch — "file already exists, leave it alone" — and the write is silently dropped.
How to fix it (in the order I'd try)
1. Turn Auto Save off (most reliable)
Drop a workspace .vscode/settings.json and add:
{
"files.autoSave": "off",
"files.autoSaveDelay": 5000,
"files.autoSaveWhenNoErrors": false,
"editor.formatOnSave": false
}I also disable formatOnSave because Prettier (or its language-specific equivalent) running on save will see a half-streamed file as malformed, half-format it, and then collide with the next agent chunk. Keeping the setting at the workspace level means only your Antigravity repos are affected — the rest of your editing stays untouched.
2. Toggle Auto Save only while the agent is editing
If you can't live without Auto Save day to day, register a task in tasks.json that toggles it on demand:
{
"version": "2.0.0",
"tasks": [
{
"label": "agent-mode-on",
"type": "shell",
"command": "code --command 'workbench.action.toggleAutoSave'",
"presentation": { "reveal": "never" }
}
]
}Bind it to a shortcut (I use Cmd+Shift+A) so you can flip it right before clicking Apply and flip it back when the agent finishes. Fully automating the toggle is tempting, but doing it by hand kept me aware of "who is editing right now: me or the agent?" and that awareness cut my own mistakes too.
3. Split "create new file" and "edit existing file" into separate prompts
You can also fix this at the prompt layer. Say "Please create XXXView.swift first. After I confirm it looks right, I'll ask you to update SettingsViewController.swift." Splitting agent transactions so they never accumulate more than one or two new dirty tabs at once removes the race entirely. The same instinct that keeps pull requests small — small, reviewable units — applies to agent edits.
Prevention checklist
Over time, this is the routine I settled on:
- Set
files.autoSave: offin.vscode/settings.jsonfor every Antigravity repo (dotfile-managed across all four of my Dolice Labs projects) - Close every dirty tab (
Cmd+K W) before starting agent edits - After the agent finishes, run
git statusand confirm the expected files all appear in the diff
The third step became my single most useful habit. Once "click Apply → check git status" became one continuous gesture, "I shipped an empty file and didn't notice for hours" simply stopped happening.
A small script to catch empty-file regressions
Eyeballing every Apply is great in theory but breaks down when you're running a four-articles-per-day publishing pipeline across multiple sites in parallel. I added a pre-commit hook that blocks any commit containing a staged-and-empty file with a real extension:
#!/usr/bin/env bash
# .git/hooks/pre-commit
set -e
empty_files=$(git diff --cached --name-only --diff-filter=AM \
| xargs -I{} sh -c 'test -f "{}" && [ ! -s "{}" ] && echo "{}"' 2>/dev/null)
if [ -n "$empty_files" ]; then
echo "🛑 Empty file(s) staged — likely autosave/agent diff conflict:"
echo "$empty_files" | sed 's/^/ - /'
echo ""
echo "Restore from agent panel, or 'git restore --staged' and re-apply."
exit 1
fiAfter this hook went in, I never shipped an empty file to production again. Antigravity's Apply history fades after a few hours, so if the hook isn't there to catch it, regenerating the change is your only option.
Look-alike symptoms with different causes
A few problems look similar but aren't caused by Auto Save. Quick triage:
- The new file doesn't exist at all (not even as an empty file): the agent's transaction was discarded because the chat was closed before Apply finished. Reopen the chat session and ask "please re-apply the last diff you proposed."
- An existing file is wiped: a formatter (in or outside the editor) decided the half-written code was broken and removed everything. Recover with
git restore --source=HEAD~1 path/to/filerather than searching reflog. - Only half the diff lands: the language server (TS Server, etc.) restarted in the middle of the edit. Don't start a new agent edit immediately after running
Cmd+Shift+P → TypeScript: Restart TS Server.
These each need different fixes, so figuring out "is the file empty or missing?" first will save you the most time.
If you've tried everything and it still happens
There's usually one more "someone is saving on my behalf" process hiding in the background. In my case it was swiftformat's file-watcher daemon, sitting outside the editor entirely and reformatting on every disk write. launchctl list | grep -i swift surfaced it; a small shell function in ~/.zshrc lets me pause it while the agent works. If turning off the editor's Auto Save doesn't fix the empty-file issue, check whether anything else has its hands on your filesystem.
I hope this saves you the half-day I lost figuring it out the first time. Thanks for reading.