ANTIGRAVITY LABJP
Articles/Integrations
Integrations/2026-07-08Advanced

Antigravity Now Saves OAuth Tokens to the OS Keyring — Keeping Auth Alive in Headless Runs

In v2.2.1, refreshed OAuth tokens are saved to the OS keyring automatically. Pleasant on the desktop, but on headless scheduled runs the vault itself may not exist and auth quietly breaks. We design explicit backend selection, a safe file fallback, and per-location liveness checks.

Antigravity315OAuthauthentication9keyringheadless2automation77

Premium Article

On my desktop, one login keeps Antigravity quiet for days. Yet the server-side scheduled job wired to the same account kept losing its authentication every few hours and running on empty. That asymmetry puzzled me for a while.

The cause was neither permissions nor the network. It was where the token gets stored. In v2.2.1, refreshed OAuth tokens are saved to the OS keyring automatically. On the desktop this cuts re-authentication dramatically. But a headless server with no terminal and no display often has no such keyring standing up at all. The save fails silently, the next run can't find the token, and the whole dance starts over. That loop was the real meaning of "breaks every few hours."

As an indie developer running several Dolice Labs sites unattended, this kind of "won't reproduce on the desktop" bug is the one I dread most. It never shows up where I can watch it, so I had no lead until I re-read the logs from the angle of storage location. This article hands you that angle from the start, walking from how the vault works to how to design for headless runs.

What the OS keyring actually is

First, let's pin down what "keyring" concretely means per OS. Leave this fuzzy and every fix becomes guesswork.

OSThe actual vaultAccess precondition
macOSKeychain (the login keychain)An unlocked login session
WindowsCredential LockerAn interactive user logon session
Linux (desktop)Secret Service (gnome-keyring / KWallet)A D-Bus session and an unlocked keyring daemon
Linux (headless)Usually nonexistentNo D-Bus session, no Secret Service responder

The key point: macOS and Windows tie the vault tightly to "the interactive user's session." A shell you merely SSH'd into, or a resident service that starts without passing a login screen, may not reach the unlocked keychain even under the same username.

Linux desktops share a spec called Secret Service, with gnome-keyring or KWallet acting as its responder. Which means the reverse is also true: in an environment with no responder, the save request has nowhere to go. Headless servers and containers are exactly that case.

The moment the keyring disappears on headless

Let's decompose the symptom. When auth breaks on an unattended scheduled run, this is the order of events inside:

  1. The agent refreshes the token (this part succeeds).
  2. It tries to save the refreshed token to the OS keyring.
  3. No keyring (Secret Service responder) exists, so the save fails.
  4. That failure is not treated as fatal, and the run proceeds anyway.
  5. On the next start it reads the keyring — which of course holds nothing.
  6. No token is found, so it re-acquires, or drops into a re-login prompt in an environment with no terminal to answer it.

The nasty part is step 4, "proceeds anyway." A failed save is often just a warning and never reaches the exit code. This is the same quiet failure I covered in when Antigravity CLI stalls on a 401 during unattended runs: "recorded as success, but empty inside." If that one was about the token's lifespan, this one is about the token's address.

Start by confirming whether your runtime has a vault responder at all.

#!/usr/bin/env bash
# Goal: decide whether Secret Service (the keyring responder) actually answers.
# Settle "present / absent" first, or everything downstream becomes guesswork.
set -uo pipefail
 
has_secret_service() {
  # With no D-Bus session, there is no responder, full stop.
  [ -n "${DBUS_SESSION_BUS_ADDRESS:-}" ] || return 1
  command -v dbus-send >/dev/null 2>&1 || return 1
  # Ask whether org.freedesktop.secrets exists on the bus.
  dbus-send --session --dest=org.freedesktop.DBus \
    --type=method_call --print-reply \
    /org/freedesktop/DBus org.freedesktop.DBus.ListNames 2>/dev/null \
    | grep -q "org.freedesktop.secrets"
}
 
if has_secret_service; then
  echo "[keyring] Secret Service present: OS keyring is usable"
else
  echo "[keyring] Secret Service absent: switching to a headless storage strategy"
fi

Run this check before the real work. Rather than noticing after a save fails, establish whether the vault exists, then choose the path. That way the later branch rests on fact, not on a hunch.

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 pinpoint the baffling case where auth works on the desktop but only breaks on a server's scheduled run, by looking at where the token is stored
You'll take home a concrete implementation that pins the keyring backend explicitly and falls back safely to a permission-hardened file when no vault exists
You'll gain a decision rule, drawn from real operations, for whether to sync tokens across machines when running agents on several boxes
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 $10 for lifetime access
View Membership →

Related Articles

Integrations2026-06-27
Rotate Keys Without Stopping an Unattended Agent: An Overlap-Window Design
API keys and tokens are worth rotating on a schedule before they leak. But an unattended agent goes quietly dead the moment auth breaks during the swap. As an indie developer running several sites on autopilot, I lay out an overlap-window design that rotates keys without downtime.
Integrations2026-06-17
When the Antigravity CLI Stalls on a 401 During Unattended Runs
If your scheduled Antigravity CLI job suddenly stops producing output after a single 401 in the logs, here is how to separate an expired token from a silent re-login prompt and rebuild your unattended setup.
Integrations2026-06-13
Running Antigravity CLI Headless: Design Before It Hits CI and cron
The Antigravity CLI was rewritten in Go. Here is how to run it unattended in CI and cron, covering exit codes, idempotency, timeouts, and output parsing.
📚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 →