After Migrating to Antigravity CLI: Deciding How Much to Delegate to Scheduled Runs
When the June 18 Gemini CLI sunset pushes you onto Antigravity CLI, you gain background scheduled runs. Convenient, but delegate everything and you won't notice when it breaks. Here is how I separate what to schedule from what to keep manual, with the actual routing rules.
The decision that arrives after it gets "convenient"
On June 18, Gemini CLI and the Gemini Code Assist IDE extension stop serving personal use, and you move to the successor, Antigravity CLI. Rewritten in Go, the CLI shares the same agent harness as the desktop app, so improvements to the core land everywhere you use it automatically. The migration itself was lighter than I feared.
The problem came afterward. Antigravity CLI gives you background scheduled runs, and you start reaching for "I can delegate this too" and "I can automate that." But after putting everything on a schedule, I caused an incident myself: one morning an agent had quietly failed and I didn't notice for half a day. Because I already run a four-site automation pipeline in Cowork as an indie developer at Dolice, stacking CLI scheduled runs on top without thought becomes a breeding ground for double-firing and silent failure.
What's needed here is a separation design: what to delegate, and what to keep in hand.
Three axes for what's safe to delegate
Not every task belongs on a schedule. I sift them through three axes.
1. Reversibility — can a failure be rolled back?
A task that only writes a draft to a file, or only emits a report, is reversible and safe to delegate. Conversely, tasks with irreversible side effects — production deploys, outbound sends, deletions — should get their final launch from a human.
2. Observability — will you notice a failure quickly?
If the result lands in chat the next morning or always leaves a log, a silent failure surfaces fast. A task that quietly writes somewhere no one looks is one you shouldn't delegate, because you won't notice when it breaks.
3. Deadline sensitivity — is lateness fatal?
A task that "doesn't have to be today" suits a schedule. One that must run at a specific time, given a scheduler's chance of missing a tick, should instead be paired with a human trigger or an idempotent re-run.
Only automate tasks where all three axes fall on the safe side. That's my baseline: reversible, observable, deadline-insensitive — delegate. Even one on the dangerous side — keep it manual. I make this call mechanically.
# delegate_decision.py — decide if a task may be delegated to a scheduledef can_delegate(task): safe = ( task["reversible"] # only reversible side effects and task["observable"] # result always hits a log/notification and not task["deadline_critical"] # no strict time requirement ) return "delegate" if safe else "keep-manual"draft = {"reversible": True, "observable": True, "deadline_critical": False}deploy = {"reversible": False, "observable": True, "deadline_critical": True}print(can_delegate(draft)) # delegateprint(can_delegate(deploy)) # keep-manual
✦
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
✦Three axes (reversibility, observability, deadline sensitivity) for splitting tasks safe to schedule from ones a human must launch
✦An exclusive-lock pattern that stops Antigravity CLI background runs from double-firing alongside your existing cron/Cowork jobs
✦A wrapper that always writes a one-line JST-dated result so silent failures never slip past you
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.
Preventing double-fire — an exclusive lock across CLI and existing schedulers
The first thing separation trips on is the same job firing twice — once from the CLI schedule, once from your existing cron / Cowork task. Set article generation on both, for instance, and you create the same slug twice and collide.
An exclusive lock prevents this. Take a simple lock file at the entry point, and bow out quietly if you can't get it.
#!/usr/bin/env bash# run_once.sh — exclusive wrapper preventing multiple launches of one jobJOB_NAME="$1"; shiftLOCK="/tmp/agjob_${JOB_NAME}.lock"# atomic lock via flock; exit immediately (not an error) if unavailableexec 9>"$LOCK"if ! flock -n 9; then echo "[$(TZ=Asia/Tokyo date '+%F %T')] skip: ${JOB_NAME} already running" \ >> "$HOME/agjob.log" exit 0fi# run the real body here"$@"
The key is that when the lock isn't acquired, you don't fail with an error — you bow out quietly with exit 0. Schedulers tend to over-fire to cover missed ticks, so "the second run does nothing and exits cleanly" is the idempotent behavior. In production, that idempotency is exactly your retry safety.
Log design that always catches silent failure
The worst enemy of scheduled runs isn't crashing loudly — it's failing without a word and going unnoticed. Antigravity CLI jobs are no exception. I wrap every scheduled job in a layer that always leaves one result line.
#!/usr/bin/env bash# logged_run.sh — always record success/failure as a JST one-linerJOB="$1"; shiftLOGDIR="$HOME/agjob_logs"; mkdir -p "$LOGDIR"STAMP=$(TZ=Asia/Tokyo date '+%F %T')if "$@"; then echo "${STAMP} OK ${JOB}" >> "$LOGDIR/$(TZ=Asia/Tokyo date '+%F').log"else CODE=$? echo "${STAMP} FAIL(${CODE}) ${JOB}" >> "$LOGDIR/$(TZ=Asia/Tokyo date '+%F').log" # on failure, also write somewhere you'll definitely see next morning echo "${STAMP} FAIL ${JOB}" >> "$HOME/MORNING_ALERTS.txt"fi
Here too the date is always built with TZ=Asia/Tokyo. Raw date runs in UTC, so a job run late at night in Japan gets written to the previous day's log file and the current day looks empty — a miss I actually hit. A gotcha worth flagging: a date skew also produces a false positive where nothing failed but it looks like it did, so whoever aggregates the logs needs the same JST basis.
A failure always leaves one line in next morning's MORNING_ALERTS.txt. Just that simple mechanism turns "it had been down for half a day before I noticed" into "I catch it in five minutes the next morning."
Decide the "take it off" condition before scheduling
The other thing that matters in delegation design is deciding the removal condition up front, not just the loading condition. A task placed on a schedule keeps running even after its assumptions change. If a referenced filename changes, or an API response shape changes, the job quietly keeps swinging and missing.
I give each job a step-down rule: "three consecutive failures, or seven days of empty results, raises an automatic pause flag." Step-down doesn't mean deletion — it just leaves a line in MORNING_ALERTS.txt saying "inspect this job" and defers the call to the next morning. In Dolice's operation, this "don't auto-kill, hand the judgment back to a human" design prevents the accident of killing a task you actually needed.
Deciding the removal condition in advance lowers the psychological barrier to scheduling at all. Precisely because there's a safety net — "if it goes wrong I'll always notice and can revert" — you can delegate reversible, observable tasks with confidence.
The separation in practice — my routing
In the end, I route like this. To the schedule I delegate reversible, observable tasks: draft generation, periodic reference-data refresh, integrity checks. In hand I keep tasks that carry irreversible judgment: final approval of a production push, price changes, article deletions.
CLI scheduled runs are powerful, but power is the flip side of "how quietly it breaks." Sift through reversibility, observability, and deadline sensitivity; stop double-firing with an exclusive lock; always catch silent failure with a log. I strongly recommend wiring up these three right after migration. Before you load everything on out of convenience, decide what to take off. That, I believe, is the design that keeps things running stably for the long haul.
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.