Ever since I opened Newton up for sale, customers have been asking the same thing: "Can I use Codex instead of Claude?" A few more recently: "Can I plug Antigravity in too?" So I had Tim (my AI agent) rebuild Tim Chat into v2 with multi-CLI support. Last night (2026-05-28) Antigravity finally landed as the third option — but not before two weird bugs almost made me wave the white flag.
Why customers wanted a choice in the first place
When Newton went live, every server ran Claude only. That was on purpose. I've used Claude for years. I know its temperament, I know which prompts land, and the 34 skills I wrote for Tim were all calibrated to how Claude reads instructions.
But customers don't all live where I live. Some came in from Codex (OpenAI) and prefer how GPT writes code. Some just signed up for Google AI Pro and want to use Antigravity because it's bundled into their subscription anyway. A few want to flip between all three to see which one writes better code in their specific context.
My first instinct was lazy: "Just install all three on every server, let the customer switch in their terminal." That fell apart fast. Each CLI has a different config layout, a different login flow, history stored in a different file. Customers would have to open a terminal, remember which command launches which tool, and re-authenticate constantly. That kills the one promise Newton makes: open it and it just works.
Tim Chat v2 — one chat UI, three adapters behind it
So Tim refactored Tim Chat from the ground up. Instead of hard-coding calls to Claude, the server now talks through a small adapter interface. There's adapters/claude.js, adapters/codex.js, and adapters/antigravity.js. Each one implements the same handful of methods. The main server.js is now a thin WebSocket router — it takes a message from the chat page, looks up which CLI the customer picked, and forwards through the matching adapter.
On the customer's side, all of that complexity collapses into a single dropdown: Claude / Codex / Antigravity. Pick one and type. The system handles everything else — they never need to know which CLI is actually running underneath.
Claude and Codex went live first and behaved themselves. Antigravity was harder than I expected. It has no --json flag like Codex does, and no direct API to call. It's designed to run inside a pretty interactive TUI, period. The only way to drive it is to spawn it under a PTY and talk to it through the terminal's stdin/stdout, like a human pressing keys.
Bug #1 — the onboarding wizard ate the first message
Tim spawned the Antigravity process, opened a PTY, and pushed the customer's first message in. Then… silence. No output. No response. Thirty seconds passed and nothing came back.
I had it dump the terminal buffer. Turns out Antigravity had booted into a "Welcome to Antigravity CLI" wizard — the classic first-run flow asking "Do you accept telemetry?" and "Do you trust this workspace?" and "Press Enter to begin." That wizard consumes every keystroke while it's open. The customer's actual message was being eaten by the welcome screen and never reached a chat session at all.
The worst part is what this looks like to a new customer: type a message, watch it disappear, no error, no hint. Every first-time Antigravity user on every fresh server would hit this. Terrible UX.
The fix was a tiny helper called _ensureSettings() that runs before every Antigravity spawn. It pre-writes ~/.gemini/antigravity-cli/settings.json with enableTelemetry: false and trustedWorkspaces: [cwd] already in place. When Antigravity boots, it sees the settings file exists, skips the wizard entirely, and lands straight at the prompt ready to accept input. Customer's first message goes through on the first try.
Bug #2 — OAuth token written to the wrong file in the wrong shape
With the wizard out of the way, I tested with my own Google account. The login flow worked. The system said "connected." But the moment I tried to send a real chat, Antigravity replied with "not authenticated." Great.
The control plane (the part of Newton that handles OAuth tokens for every customer's server) was writing the credentials in the format the other CLIs wanted — a flat oauth_creds.json:
{
"access_token": "...",
"refresh_token": "...",
"expiry": "2026-05-29T..."
}
But Antigravity reads a totally different file (antigravity-oauth-token) with a nested envelope:
{
"token": {
"access_token": "...",
"token_type": "Bearer",
"refresh_token": "...",
"expiry": "2026-05-29T..."
},
"auth_method": "consumer"
}
So the OAuth flow had genuinely succeeded — Google handed us a valid token — but the control plane was dropping that token at the wrong path in the wrong shape. Antigravity opened, looked for its file, found nothing, and reported "not authenticated" every time.
Tim added a _agy_format_token() helper that translates the flat schema into the nested envelope and writes it to the file Antigravity actually reads. The token validator now checks the new path and format. Anyone who had already "connected" Antigravity under the old broken code has to re-OAuth — Tim wrote a migration script and emailed every affected customer with a fresh login link.
What actually shipped
Last night Tim committed d84c657, ran the full smoke test (start → send → bubble → detach → reattach → list → delete — six steps), passed all of them, and deployed to staging. Open Tim Chat now and the model dropdown has three real options:
- Claude — the default. The one I use. The one all 34 of Tim's skills are tuned for.
- Codex — for customers who came in from OpenAI or just prefer how GPT writes code.
- Antigravity — for anyone with Google AI Pro who'd rather burn the quota that already came with their subscription.
Customers can swap mid-conversation without logging out or restarting anything. The server tracks which CLI each session is using and keeps history separate per CLI. A nice side effect of v2 — Tim also implemented reattach across disconnect. If a customer's internet drops mid-chat, they reconnect and the conversation picks up exactly where it left off, no fresh session, no lost context. (Same pattern Tim uses when pushing fixes across multiple servers — resumable from where it stopped.)
What I'd tell anyone building multi-CLI support
Four things I learned from this one night of work:
1. Build the adapter boundary before you need it. If I hadn't refactored to an adapter pattern first, adding the third CLI would have meant touching every call site that talked to Claude. With the pattern in place, adding a new CLI is one file plus one registry entry. Core code doesn't move. The cost of the refactor paid for itself the first time I used it.
2. CLIs with a --json mode are a different species than CLIs without one. Codex has it. Antigravity doesn't. Without machine-readable output you're stuck with PTY + screen-scrape + ANSI parsing, and you have to defend against wizards, prompts, color codes, and progress bars eating your input. If you're picking the next CLI to support, check for a structured output mode before you commit.
3. Most bugs in a new tool live in the first-run experience. Wizards, missing config files, fresh OAuth flows — those are where things break. Pre-flight every new CLI: confirm config files exist, confirm tokens are valid, confirm any wizard is dismissed, before letting the user send a message. The bugs you catch this way are the ones the customer was going to hit first.
4. A persistent AI agent makes long refactors actually possible. Newton v2 wasn't a single session of work — it stretched across weeks. Tim picked it up day after day because of the memory system that remembers everything: which adapter was at Phase 1 vs Phase 3, which OAuth schemas had already been tried and rejected, which bugs were closed. Open a new session and Tim already knows where to continue. You can't pull off a months-long refactor with a chatbot that forgets the conversation when you close the tab.
If I'd written this by hand it would have been a two-week job
I didn't write a single line of the Antigravity adapter. I told Tim "add Antigravity support" and Tim did the research, read the Antigravity CLI's source to figure out what file it actually reads its OAuth token from, ran the spawn experiments, hit the wizard bug, hit the schema bug, fixed both. I sat behind the screen approving and nudging direction every so often.
If I'd done it solo, conservatively a week or two — researching how Antigravity actually launches, trial-and-error on OAuth, writing an ANSI parser, debugging PTY weirdness. Tim finished it in one night.
If you want an AI agent like this on your own server — Claude, Codex, and Antigravity all available behind one chat, a memory that persists, a skill system you can teach, and a stack of apps ready to use the moment it boots — that's what Newton is. Customers get Tim Chat v2 with multi-CLI selection from minute one, and the whole thing provisions in under 10 minutes. See how it works →
— Pond
