`opencode-antigravity-auth`: The Account-Rotation Engine Behind a Shadow AI Access Layer
A TypeScript plugin that treats OAuth, quota, and retry logic as one survival system for staying ahead of model limits, bans, and API drift.
- The repo behaves less like a login helper than a control plane that scores identities, routes requests, and keeps sessions alive under quota pressure.
- Its distinctive move is to treat account health as a live signal, then combine penalties, cooldowns, jitter, and retries into one rotation loop.
- Request shaping matters as much as OAuth here, because the plugin changes how traffic reaches the backend instead of merely passing credentials through.
- The whole system feels infrastructural because it manages state, concurrency, and failure as first-class product features.
The real product is survival
The most interesting thing about opencode-antigravity-auth is that it does not behave like a normal auth plugin. It behaves like an operating system for scarce access: score each identity, route traffic to the healthiest one, cool down the damaged ones, and keep enough entropy in the loop to avoid obvious patterns.
That is why the repo is better read as infrastructure than glue code. The point is not to log in once. The point is to keep a multi-account path usable when quota gets tight, failures cluster, and the backend starts pushing back.
A number of users have reported their Google accounts being banned or shadow-banned (restricted access without explicit notification).
How a Google login becomes a project ID
The authentication flow is only the first gate. The plugin uses PKCE and a Google-specific scope set, then calls a project-discovery step that resembles an IDE bootstrap rather than a generic OAuth callback. The key move is simple: the client must become the right kind of client before the backend yields the project identity it expects.
const token = await authorizeAntigravity({
scopes: ANTIGRAVITY_SCOPES,
pkce: true,
});
const projectID = await fetchProjectID(token.accessToken);
return {
refreshToken: token.refreshToken,
projectID,
managedProjectID: projectID,
};
That sequence matters because it turns a generic identity into a managed workspace identity. In other words, the plugin is not just asking for permission. It is negotiating shape.
Rotation is the core algorithm
The heart of the repo is the health scoring loop. Accounts are not treated as equal, and they are not rotated in a simple round robin. Each identity accumulates reward for success and penalties for quota exhaustion, transient failures, and repeated bad outcomes, then waits out a tiered backoff before it is eligible again.
| Simple client | This repo | Why it matters |
|---|---|---|
| Retry after failure | Score, cool down, and route away before failure repeats | It avoids turning every error into a stampede |
| One account at a time | A pool of identities with current health states | Access survives by distributing risk |
| Flat retry timing | Tiered backoff plus jitter | Retries do not synchronize into self-inflicted bursts |
| Stateless auth | Stateful quota awareness | The system remembers which identities are fragile |
The important detail is that the model for selection is not static. A healthy account today can become a bad choice after a few quota hits, and the tracker is built to notice that drift fast enough to matter.
Request shaping is where the model behavior changes
Once a request is in flight, the plugin stops being a passive pipe. It reshapes the body, routes between quota pools, and primes thinking sessions so the downstream model behaves the way the caller expects. That is the boundary where the repo moves from auth into session control.
function buildThinkingWarmupBody(prompt: string) {
return {
model: "claude-opus-4.6-thinking",
thinking: true,
messages: [{ role: "user", content: prompt }],
};
}
const route = cliFirst ? "gemini-cli" : "antigravity";
const body = buildThinkingWarmupBody(userPrompt);
This is also why the project feels risky and disciplined at the same time. It does not merely hope the backend cooperates. It actively nudges the request into the shape most likely to succeed, then keeps the session warm enough to keep working.
Storage, concurrency, and the cost of many identities
The more accounts you manage, the more storage stops being a convenience and becomes a correctness problem. The repo packs refresh token, project ID, and managed project ID into a single persisted string, then uses locking to keep concurrent writers from corrupting shared state.
| Simple client | This repo | Why it matters |
|---|---|---|
| One process, one token | Many sessions, one shared account store | Concurrency becomes a data-integrity issue |
| Plain refresh token storage | Packed token plus project metadata | Credential state stays portable across flows |
| Best-effort writes | Lockfile-protected updates | Two writers do not race each other into corruption |
That design tells you what kind of system this is. It is not a user-facing plugin that caches a few secrets. It is a coordination layer that expects motion, contention, and recovery.
Why this repo feels more like infrastructure than a plugin
Ordinary auth helpers answer a narrow question: can I log in? This repository answers a harder one: can I keep traffic flowing while the backend changes its mind, quota windows close, and identities age out at different speeds?
| Ordinary OAuth helper | This repo | Why it matters |
|---|---|---|
| Authenticate once | Authenticate, score, rotate, and recover | Access is treated as an ongoing system |
| Pass credentials through | Shape requests and warm sessions | Behavior changes, not just permissions |
| Retry on error | Preemptive routing with jittered backoff | The system avoids predictable failure patterns |
| Single-account simplicity | Multi-account state management | The architecture resembles a control plane |
That is the editorial takeaway. Whatever one thinks of the use case, the engineering pattern is clear: observe, score, route, retry, and adapt. The plugin is built like a control plane because that is what keeping shadow access alive demands.





