ANTIGRAVITY LABJP
Articles/Tips & Best Practices
Tips & Best Practices/2026-09-02Intermediate

The work-root guard I run before letting an agent near several repositories

When several repositories share one machine, an agent's working root is remarkably easy to mix up. Here is a small guard that compares resolved paths, tested against seven inputs.

antigravity450agents136bash2workflow54safety

Premium Article

Disk space was running low, so I wrote a small routine to clear out stale checkouts. I am working in this one repository, so keep it and remove the siblings. That was the reasoning behind this line:

for OTHER in /tmp/repos/*; do
  [ "$OTHER" = "$WORK" ] && continue
  rm -rf "$OTHER"
done

As an indie developer maintaining iOS and Android apps alongside several site repositories, I usually have four or five checkouts sitting next to each other. This line was meant to protect exactly one of them.

It protected none. A single trailing slash on $WORK is enough for that comparison to never match.

Three ways a mix-up gets in

Working-root mix-ups do not announce themselves. They arrive through quiet mismatches: strings that differ while the underlying directory is the same, or the reverse. I walked into three of them.

Notation drift

/tmp/repos/siteA and /tmp/repos/siteA/ are different strings to the shell. Once two places in your code build that path, a trailing slash survives in one of them.

Symlink aliases

A convenience alias pointing at a checkout will never string-match the directory it points to.

Inherited depth

You may intend to hand the agent a repository root, but if the previous task descended into src/, that position quietly becomes the working root for the next one.

Watching it happen in a sandbox

Guessing at a fix usually shifts the problem somewhere else, so I reproduced the behaviour in a throwaway directory: siteA, siteB, and a symlink pointing at siteA.

T=$(mktemp -d); cd "$T"
mkdir -p repos/siteA repos/siteB
ln -s "$T/repos/siteA" repos/siteA-link
 
WORK="$T/repos/siteA/"          # trailing slash
for OTHER in "$T"/repos/*; do
  if [ "$OTHER" = "$WORK" ]; then echo "  skip(self): $OTHER"
  else echo "  DELETE: $OTHER"; fi
done

The output:

  DELETE: /tmp/tmp.vFHcRXrU5D/repos/siteA
  DELETE: /tmp/tmp.vFHcRXrU5D/repos/siteA-link
  DELETE: /tmp/tmp.vFHcRXrU5D/repos/siteB

The checkout I meant to keep is first in the delete list. skip(self) never printed once.

Running the same loop after normalising both sides through realpath changes the outcome:

WORK_R=$(realpath "$WORK")
for OTHER in "$T"/repos/*; do
  OR=$(realpath "$OTHER")
  if [ "$OR" = "$WORK_R" ]; then echo "  skip(self): $OTHER -> $OR"
  else echo "  DELETE: $OTHER -> $OR"; fi
done
  skip(self): .../repos/siteA      -> .../repos/siteA
  skip(self): .../repos/siteA-link -> .../repos/siteA
  DELETE:     .../repos/siteB      -> .../repos/siteB

The trailing slash is gone, the symlink is resolved, and both entry points to siteA land on the keep side. Resolve once before you compare — that is the whole idea.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You will be able to spot, on your own machine, the conditions under which an agent's working root gets mixed up with a sibling checkout
You will be able to add resolved-path matching to your cleanup routine before it deletes a checkout you meant to keep
You will be able to adapt a guard that returns the intended exit code for seven different inputs to your own repository layout
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Tips2026-07-10
You Can Measure a Request Before You Send It — Sizing Agent Tasks by Working Backward from Rework Rate
When an Antigravity agent returns code that misses the mark, the cause is rarely the wording of the prompt. It is the size of the task. Here is a Python scorer that grades a request before you send it, plus what happened when I scored 80 past requests against their actual rework outcomes.
Tips2026-06-13
A Week of Coding Hands-Free with Antigravity 2.0's Live Voice Transcription
Antigravity 2.0 added Gemini Audio-based live transcription right inside the editor. After a week of using it in real work, here's an honest take on how it differs from external dictation tools, how it handles technical terms, and where it actually earns its place.
Tips2026-05-11
What You Lose When You Treat Antigravity as a Subordinate — A Decade of Solo Dev Perspective
Over-delegating to Antigravity quietly erodes your problem-solving ability. From 10+ years of solo app development, here's how to prevent cognitive outsourcing and keep your developer judgment sharp.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →