antigravity-intern 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sinan Tufekci
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,465 @@
1
+ Metadata-Version: 2.4
2
+ Name: antigravity-intern
3
+ Version: 0.10.0
4
+ Summary: MCP server bridging Antigravity CLI (agy) so Claude Code can use it as a sub-agent
5
+ Author: Sinan Tüfekçi
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/SinanTufekci/antigravity-intern
8
+ Project-URL: Repository, https://github.com/SinanTufekci/antigravity-intern
9
+ Project-URL: Issues, https://github.com/SinanTufekci/antigravity-intern/issues
10
+ Project-URL: Sponsor, https://github.com/sponsors/SinanTufekci
11
+ Keywords: mcp,claude,claude-code,antigravity,gemini,agy,llm,ai
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Code Generators
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: fastmcp>=2.0.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=8; extra == "dev"
28
+ Requires-Dist: ruff>=0.6; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ <div align="center">
32
+
33
+ # Claude Code × Antigravity CLI — MCP Bridge
34
+
35
+ <img src="assets/bridge-animation.svg" width="100%" alt="Claude Code x Antigravity CLI Bridge Animation" />
36
+
37
+ **Use Google's [Antigravity](https://antigravity.google/) (Gemini 3.5 Flash) as a sub-agent inside [Claude Code](https://claude.com/claude-code) — for text answers *and* image generation, on the AI Pro quota you already pay for.**
38
+
39
+ [![CI](https://github.com/SinanTufekci/antigravity-intern/actions/workflows/ci.yml/badge.svg)](https://github.com/SinanTufekci/antigravity-intern/actions/workflows/ci.yml)
40
+ [![GitHub release](https://img.shields.io/github/v/release/SinanTufekci/antigravity-intern?color=2ea44f)](https://github.com/SinanTufekci/antigravity-intern/releases/latest)
41
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
42
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
43
+ [![MCP server](https://img.shields.io/badge/MCP-server-7c3aed)](https://modelcontextprotocol.io/)
44
+ [![agy 1.0.9 verified](https://img.shields.io/badge/agy-1.0.9%20verified-2ea44f)](https://antigravity.google/)
45
+ [![platform](https://img.shields.io/badge/platform-Windows%20·%20macOS%20·%20Linux-lightgrey)](#requirements)
46
+ [![Sponsor](https://img.shields.io/github/sponsors/SinanTufekci?logo=githubsponsors&label=Sponsor&color=ea4aaa)](https://github.com/sponsors/SinanTufekci)
47
+
48
+ </div>
49
+
50
+ ---
51
+
52
+ `agy`, Google's Antigravity CLI, ships a headless print mode (`agy -p`) that's **broken**: it
53
+ authenticates, talks to the model, gets the answer back… and then writes it to the *controlling
54
+ terminal* instead of its stdout — so anything capturing stdout gets nothing (and, run under a TUI,
55
+ agy's text leaks straight into the host's prompt). This bridge runs `agy -p` anyway, **detaches it
56
+ from your terminal** so it can't leak, reads the answer straight out of agy's *own* transcript
57
+ files, and hands it to Claude Code as clean MCP tools. Delegate cheap tool-calling work to Gemini
58
+ without leaving your terminal.
59
+
60
+ > [!WARNING]
61
+ > **This runs unsandboxed code with your privileges.** `agy -p` auto-executes its tools
62
+ > (read/write files, run shell commands, reach the network) with **no usable approval gate**.
63
+ > `--sandbox` (fixed for `-p` in agy 1.0.6+) blocks only *shell commands* — file writes and
64
+ > network egress stay wide open — so it's no real boundary. The `workspace` argument is a
65
+ > *starting context*, **not** a security boundary. Only use it with **trusted prompts on trusted
66
+ > content**; for real isolation, run the bridge inside a container or VM. **[Full details →](#security)**
67
+
68
+ ## Why you'd want this
69
+
70
+ | | |
71
+ |---|---|
72
+ | 🧠 **Second opinion** | Ask a different model family mid-task without switching tools. |
73
+ | 🎨 **Image generation** | Have Gemini draw an image and get the saved file back — no extra API key or image tool. |
74
+ | 💸 **Cheap delegation** | Burn Antigravity AI Pro quota on grunt work instead of Claude tokens. |
75
+ | 📁 **Cross-repo reads** | Point it at another project directory and let Gemini read/answer there. |
76
+ | 🔌 **Zero new auth** | Piggybacks the login you already did in the Antigravity IDE — no keys to manage. |
77
+
78
+ ## How it works
79
+
80
+ ```mermaid
81
+ flowchart LR
82
+ A([Claude Code]) -- "MCP tool call" --> B["agy bridge<br/>(server.py)"]
83
+ B -- "agy -p prompt" --> C[Antigravity CLI]
84
+ C -- "Gemini 3.5 Flash (High)" --> M((model))
85
+ M -- "answer" --> C
86
+ C -. "writes (stdout stays empty)" .-> T[("transcript.jsonl")]
87
+ B -- "reads final PLANNER_RESPONSE" --> T
88
+ B -- "plain text" --> A
89
+ ```
90
+
91
+ `agy -p` persists its real answer — the one it never sends to stdout — to:
92
+
93
+ ```
94
+ ~/.gemini/antigravity-cli/brain/<conv-id>/.system_generated/logs/transcript.jsonl
95
+ ```
96
+
97
+ The bridge runs agy, locates the conversation via `cache/last_conversations.json` (falling back to
98
+ the newest `brain/` directory touched since launch), streams the transcript, and returns the final
99
+ `source=MODEL, status=DONE, type=PLANNER_RESPONSE` entry — the answer, minus the intermediate
100
+ tool-calling steps. `antigravity_continue` pins the workspace's **exact** conversation id via
101
+ `--conversation`, so it never resumes the wrong thread.
102
+
103
+ ## Set up in 60 seconds
104
+
105
+ ```bash
106
+ git clone https://github.com/SinanTufekci/antigravity-intern.git
107
+ cd antigravity-intern
108
+ pip install fastmcp
109
+ python test_smoke.py # 3 real round-trips (ask, continue, image) — should print three PASS lines
110
+ ```
111
+
112
+ > [!NOTE]
113
+ > The smoke test costs a tiny bit of AI Pro quota and takes ~30–60 s. You must have logged into
114
+ > Antigravity **once** (via the IDE or `agy -i`) so agy has a credential to reuse.
115
+
116
+ Then register the server with Claude Code — add this under `mcpServers` in `~/.claude.json`,
117
+ using the absolute path to `server.py`:
118
+
119
+ <table>
120
+ <tr><th>Windows</th><th>macOS / Linux</th></tr>
121
+ <tr><td>
122
+
123
+ ```json
124
+ "antigravity-intern": {
125
+ "command": "python",
126
+ "args": ["C:\\path\\to\\server.py"]
127
+ }
128
+ ```
129
+
130
+ </td><td>
131
+
132
+ ```json
133
+ "antigravity-intern": {
134
+ "command": "python3",
135
+ "args": ["/path/to/server.py"]
136
+ }
137
+ ```
138
+
139
+ </td></tr>
140
+ </table>
141
+
142
+ > [!TIP]
143
+ > **No-clone, auto-updating install (recommended once published to PyPI):** skip the `git clone`
144
+ > and let [`uvx`](https://docs.astral.sh/uv/) pull the latest published release on every launch —
145
+ > no path to hardcode, no `git pull` to remember:
146
+ > ```json
147
+ > "antigravity-intern": {
148
+ > "command": "uvx",
149
+ > "args": ["antigravity-intern"]
150
+ > }
151
+ > ```
152
+ > Each launch runs the newest version in an isolated environment. (The bridge is published to PyPI
153
+ > automatically on every version tag — see [Releasing](#development).)
154
+
155
+ Restart Claude Code. Eight tools appear: **`antigravity_ask`**, **`antigravity_continue`**, **`antigravity_ask_watch`**, **`antigravity_image`**, **`antigravity_image_watch`**, **`antigravity_swarm`**, **`antigravity_image_swarm`**, and **`antigravity_status`** (each prefixed `mcp__antigravity-intern__`).
156
+
157
+ > *"Use antigravity_ask to summarize the README of this repo in three bullets."* → Claude routes the prompt
158
+ > through the bridge, agy reads the file under the workspace root, and the answer comes back as a
159
+ > plain string.
160
+
161
+ ## Tools
162
+
163
+ | Tool | Purpose |
164
+ |---|---|
165
+ | `antigravity_ask(prompt, workspace?, timeout_s?=180)` | Start a **new** Antigravity conversation. |
166
+ | `antigravity_continue(prompt, workspace?, timeout_s?=180)` | Continue the conversation **rooted at `workspace`** (pinned by id). |
167
+ | `antigravity_ask_watch(prompt, workspace?, timeout_s?=180)` | 🧪 **Experimental.** Like `antigravity_ask`, but opens the **Antigravity Intern** live browser window so you can watch agy work (see [Watch mode](#watch-mode)). |
168
+ | `antigravity_image(prompt, output_path?, workspace?, timeout_s?=240)` | Generate an image with Antigravity; saves the file (extension corrected to the real bytes) and returns its path + format/size. |
169
+ | `antigravity_image_watch(prompt, output_path?, workspace?, timeout_s?=240)` | 🧪 **Experimental.** Like `antigravity_image`, but streams progress and **shows the generated image** in the Antigravity Intern window. |
170
+ | `antigravity_swarm(prompts, workspaces?, max_concurrency?=4, timeout_s?=180, watch?=false)` | Run **several prompts in parallel** as independent agy workers; returns every answer in one block (see [Swarm](#swarm)). |
171
+ | `antigravity_image_swarm(prompts, output_paths?, workspaces?, max_concurrency?=4, timeout_s?=240, watch?=false)` | Generate **several images in parallel** (one worker per prompt). |
172
+ | `antigravity_status()` | Offline setup diagnostics (agy version/compat, state dirs, newest transcript readable). Spends no quota. |
173
+
174
+ `workspace` defaults to the MCP server's current working directory. Point it at a real project dir
175
+ for context-aware answers — agy gives the model access to files under that root.
176
+
177
+ `antigravity_image` forces agy to save to an explicit absolute path — without one, agy
178
+ falls back to its own scratch dir (`~/.gemini/antigravity-cli/scratch/`). It then
179
+ corrects the file extension to match the real bytes: agy's image model picks the
180
+ format itself (JPEG for photo-like images, PNG for flat graphics), so a requested
181
+ `out.png` may come back as `out.jpg`. The returned path always reflects the true
182
+ format.
183
+
184
+ <a id="watch-mode"></a>
185
+
186
+ ## 👁️ Watch mode — Antigravity Intern (experimental)
187
+
188
+ `antigravity_ask_watch` / `antigravity_image_watch` do the same work as `antigravity_ask` / `antigravity_image`, but
189
+ let you **watch agy work live in a little terminal-style browser window** called
190
+ **Antigravity Intern**. agy still runs headless; alongside it the bridge serves a tiny page on
191
+ `127.0.0.1` and opens it in a small, chromeless app window that streams agy's steps —
192
+ its planner narration (▸), the **real commands** it runs (`$`), and completions (✓) —
193
+ read live from the transcript, with the final answer rendered as Markdown (and, for
194
+ `antigravity_image_watch`, the generated image shown inline).
195
+
196
+ - **Cross-platform & best-effort.** Prefers a Chromium browser (`--app` mode) for the
197
+ windowed look; falls back to a normal browser window. If nothing can open, the run
198
+ still completes and returns normally.
199
+ - **Window size.** Set **`AGY_WATCH_WINDOW_SIZE`** (e.g. `AGY_WATCH_WINDOW_SIZE=480,700`)
200
+ to resize the window; default is `560,760`. Press **Enter / Esc** in the window to
201
+ close it.
202
+ - **Coarse, not token-level.** agy flushes its transcript in chunks, so you get a
203
+ handful of live steps, not character streaming. The returned value is identical to
204
+ the non-watch tool. Nothing is sent anywhere but your own machine.
205
+
206
+ <a id="swarm"></a>
207
+
208
+ ## 🐝 Swarm — run agy workers in parallel
209
+
210
+ `antigravity_swarm` and `antigravity_image_swarm` fan a list of prompts out to
211
+ **independent agy workers that run truly concurrently** (capped at
212
+ `max_concurrency`, default 4), then return every worker's result in one block.
213
+ Good for independent, cheap sub-tasks — summarise N files, ask the same question
214
+ about N repos, generate N images — without paying for them one at a time.
215
+
216
+ ```
217
+ antigravity_swarm(prompts=[
218
+ "Summarise src/auth.py in 2 bullets.",
219
+ "Summarise src/db.py in 2 bullets.",
220
+ "List the public functions in src/api.py.",
221
+ ])
222
+ ```
223
+
224
+ **How it stays correct under concurrency.** The single-agent tools serialize
225
+ through a lock because agy rewrites `last_conversations.json` on every call, so
226
+ concurrent runs sharing one state dir would race. The swarm sidesteps this
227
+ entirely: each worker runs with its **own isolated `HOME`/`USERPROFILE`**, so
228
+ agy's `brain/`, `cache/`, and `last_conversations.json` never collide — no lock
229
+ needed. Auth still works because agy reads it from the **OS credential store**,
230
+ not from `~/.gemini` (verified on agy 1.0.9). Each worker's `cwd` is still its
231
+ real `workspace`, so file access there is unchanged — HOME redirection isolates
232
+ *state only*. Measured ~**2.8× speedup at 3 workers** (the AI Pro backend does
233
+ not serialize per-account); higher `max_concurrency` trades quota/rate-limit
234
+ pressure for wall-clock.
235
+
236
+ - **`workspaces`** — omit for the server cwd; pass a **1-item list** to point every
237
+ worker at the same dir; pass **one entry per prompt** for per-worker dirs.
238
+ - **Error isolation** — a worker that fails is reported in place; the others still
239
+ return.
240
+ - **`watch=true`** — opens a thin live **Antigravity Swarm** dashboard (one row per
241
+ worker showing the repo, prompt, and latest step). **Click a row** to pop that
242
+ agent out into its own window streaming its full step log, beside the dashboard.
243
+
244
+ > [!WARNING]
245
+ > A swarm launches **N unsandboxed agy agents at once** — N× the prompt-injection
246
+ > "lethal trifecta" surface of a single call (see [Security](#security)). Only use
247
+ > it with **trusted prompts on trusted content**.
248
+
249
+ ## Model & auth
250
+
251
+ - **Model:** effectively **Gemini 3.5 Flash (High)** — whatever the `"model"` field in agy's
252
+ `settings.json` is set to. agy 1.0.5 added a `--model` flag (and a `models` subcommand) that *is*
253
+ wired into print mode, but **switching to a different model in `-p` hangs the call** (verified on
254
+ 1.0.5: passing the already-active label returns in seconds, any other label hangs >60 s). So the
255
+ bridge stays single-model; change it via agy's `settings.json` if you need a different one. Flash
256
+ High is speed-optimized for tool-calling, so this fits best as a *fast sub-agent for cheap work*,
257
+ not a heavy reasoning partner.
258
+ - **Auth:** piggybacks whatever credential store `agy` uses on your OS (Windows Credential Manager,
259
+ macOS Keychain, libsecret on Linux — the bridge never touches it directly). Log in once; every
260
+ call after that silent-auths on the **same AI Pro quota** you already pay for.
261
+
262
+ <a id="security"></a>
263
+
264
+ ## ⚠️ Security
265
+
266
+ `agy -p` runs the model as an **autonomous agent that auto-executes its own tools** — reading and
267
+ writing files, running shell commands, and reaching the network — with **no approval gate and no
268
+ opt-out**. This isn't a choice the bridge makes; it's how agy's print mode works. Re-verified
269
+ empirically on **agy 1.0.9 / Windows** (all three checks below still hold):
270
+
271
+ - Print mode runs out-of-workspace file writes and live network fetches **even without**
272
+ `--dangerously-skip-permissions` — that flag is a **no-op** for `-p`. There is **no** agy flag
273
+ that disables tool execution in print mode.
274
+ - agy 1.0.5 integrated a permission system (its logs show `toolPermission=request-review`), but it
275
+ **still does not gate print-mode execution** — a fresh `-p` run created a file outside the
276
+ workspace with no prompt.
277
+ - `--sandbox` is **not** a usable boundary. agy 1.0.6 fixed its propagation into `-p` (the 1.0.6/1.0.7
278
+ changelog calls this "sandbox isolation correctly enforced") and it now **does** block terminal/
279
+ shell command execution — but re-verified on 1.0.9 that it leaves the `write_to_file` tool and
280
+ network **wide open**: under `--sandbox` the model still wrote a file *outside* its workspace. agy
281
+ 1.0.9 hardened the sandbox's *command* path (stricter exact-match command checks; `.git` added to
282
+ its dangerous-paths list), but none of that closes the out-of-workspace `write_to_file` hole. On
283
+ top of that, a `--sandbox` run whose blocked terminal command halts it writes **no JSONL
284
+ transcript** (only the SQLite `.db`, re-confirmed on 1.0.9), so the bridge couldn't read a
285
+ response — so the bridge deliberately never passes `--sandbox`.
286
+
287
+ **What that means for you:**
288
+
289
+ - The `workspace` argument is only a *starting context*, **not a security boundary** — the agent
290
+ can and does act outside it.
291
+ - Every call effectively runs **arbitrary code with your user privileges**.
292
+ - Only invoke this with **trusted prompts on trusted content**. Untrusted input here is the classic
293
+ prompt-injection *lethal trifecta*: private-data access + code execution + network egress.
294
+ - For real isolation, run the **whole bridge inside a container or VM**.
295
+
296
+ The bridge itself does only cross-platform filesystem reads under `~/.gemini/antigravity-cli/` — no
297
+ private APIs, no token theft. The risk above is entirely in what the agy sub-agent is allowed to do.
298
+
299
+ ## FAQ
300
+
301
+ <details>
302
+ <summary><b>Is this against Google's Terms of Service?</b></summary>
303
+
304
+ It runs the **official `agy` CLI under your own AI Pro session** — no private APIs, no token theft,
305
+ no quota abuse. It just bridges what the CLI already does. That said, your AI Pro / Antigravity ToS
306
+ apply, and you're responsible for staying within them.
307
+ </details>
308
+
309
+ <details>
310
+ <summary><b>Will it break when agy updates?</b></summary>
311
+
312
+ Possibly — it reads agy's **internal, undocumented** state files, so a release can change paths or
313
+ schemas and break it silently. Re-verified working on **1.0.9** (transcript schema and `-p` JSONL
314
+ output unchanged; live ask/continue/image round-trips pass). The known future risk is agy's
315
+ **SQLite (`.db`) conversation format** (added in 1.0.4, slated to become the default): agy 1.0.9
316
+ still **dual-writes** every conversation to `~/.gemini/antigravity-cli/conversations/<id>.db`
317
+ alongside the JSONL transcript, so once it stops writing JSONL the reader needs a SQLite path. Pin a
318
+ known-good `agy` version if you depend on this.
319
+ </details>
320
+
321
+ <details>
322
+ <summary><b>Why only Gemini 3.5 Flash?</b></summary>
323
+
324
+ agy 1.0.5 added a `--model` flag, but switching to a different model in `-p` **hangs** (print mode
325
+ waits on a step it never gets headless), so in practice you get whatever model agy's `settings.json`
326
+ selects — Gemini 3.5 Flash (High) by default. The bridge doesn't expose a model knob because it
327
+ would hang on any real switch.
328
+ </details>
329
+
330
+ <details>
331
+ <summary><b>Can it generate images?</b></summary>
332
+
333
+ **Yes — that's the `antigravity_image` tool.** agy's print mode generates real images on
334
+ your AI Pro quota; `antigravity_image` drives it, saves the file to a path you choose (or
335
+ a timestamped default in your workspace), fixes the extension to match the real
336
+ bytes (agy picks JPEG or PNG itself), and returns the path. Verified on **agy 1.0.9 / Windows**.
337
+ It's request/response only and runs a normal, unsandboxed agy session (see
338
+ [Security](#security)).
339
+ </details>
340
+
341
+ <details>
342
+ <summary><b>Does it cost extra money?</b></summary>
343
+
344
+ No. It uses the same **AI Pro quota** you already pay for. The smoke test spends a negligible
345
+ amount.
346
+ </details>
347
+
348
+ <details>
349
+ <summary><b>Does it stream responses?</b></summary>
350
+
351
+ The final answer is request/response — `agy -p` returns it all at once, so the tools return when agy
352
+ finishes (each call typically takes 10–30 s). If you want to *watch* agy work as it goes, use the
353
+ experimental **watch mode** (`antigravity_ask_watch` / `antigravity_image_watch`): it opens the
354
+ **Antigravity Intern** browser window and live-streams agy's steps read from the transcript — see
355
+ [Watch mode](#watch-mode). It's coarse (a handful of steps, not token-by-token), and the returned
356
+ value is identical to the non-watch tool.
357
+ </details>
358
+
359
+ <details>
360
+ <summary><b>Can I run several calls at once?</b></summary>
361
+
362
+ The **single-agent** tools (`antigravity_ask` / `antigravity_continue` / `antigravity_image`) are
363
+ **serialized** inside the server: agy rewrites `last_conversations.json` on every call, so concurrent
364
+ runs sharing one state dir would race and could return the wrong conversation. A `threading.Lock`
365
+ makes extra requests queue rather than race.
366
+
367
+ For real parallelism use **[`antigravity_swarm`](#swarm)** — it runs each worker in its own isolated
368
+ state dir, so they don't race and the lock isn't needed (~2.8× at 3 workers). That's the supported
369
+ way to run many agy calls at once.
370
+ </details>
371
+
372
+ ## Status & caveats
373
+
374
+ - ✅ **Verified on agy 1.0.9** — base dir, `last_conversations.json`, the
375
+ `brain/.../transcript.jsonl` path, the transcript schema, and the `-p`/`-c`/`--print-timeout`
376
+ flags are all unchanged; live ask/continue/image round-trips all pass. The 1.0.5 `-p` metadata fix
377
+ also means agy no longer litters the workspace dir.
378
+ - 🖥️ **Console-detach (new)** — agy `-p` writes its progress/answer to the *controlling terminal*,
379
+ not stdout; under a TUI that text leaks into the host's prompt (seen on 1.0.9 before the fix). The
380
+ bridge now spawns agy detached from the terminal (`CREATE_NO_WINDOW` / a new POSIX session), so it
381
+ can't leak; the answer is still read from the transcript.
382
+ - ⏳ **SQLite migration is the real risk** — agy 1.0.9 still dual-writes a `.db` per conversation;
383
+ see the [FAQ](#faq). `_read_response` raises a clear, SQLite-aware error if the JSONL transcript
384
+ ever disappears.
385
+ - 🐛 **Stdout bug persists** — `-p` still doesn't print the answer to stdout on 1.0.9 (the 1.0.9
386
+ "print-mode resumption" changelog fix did **not** change this for fresh `-p`). If a future release
387
+ fixes stdout, this workaround becomes redundant but harmless.
388
+ - 👁️ **Watch mode is experimental** — `antigravity_ask_watch` / `antigravity_image_watch` open the **Antigravity Intern**
389
+ browser window to watch agy work live (coarse steps; image shown inline). Best-effort and
390
+ cross-platform; see [Watch mode](#watch-mode).
391
+ - 🔒 **No real sandbox** — agy's `--sandbox` (since 1.0.6) blocks only shell commands in `-p` but still
392
+ leaves file writes and network egress open (and breaks transcript reading), so it's no boundary;
393
+ see [Security](#security).
394
+
395
+ ## Requirements
396
+
397
+ - Python 3.10+
398
+ - [`agy`](https://antigravity.google/) 1.0.0 or newer on `PATH` (state-file layout re-verified on **1.0.9**)
399
+ - An active Antigravity / AI Pro session
400
+
401
+ > [!TIP]
402
+ > If `agy` isn't reliably on `PATH` (e.g. a new terminal or reboot drops it on Windows), set the
403
+ > **`AGY_BIN`** env var to its full path and the bridge will use that instead of `"agy"` — e.g.
404
+ > `AGY_BIN=%LOCALAPPDATA%\agy\bin\agy.exe`.
405
+
406
+ The bridge uses only cross-platform Python (`Path.home()`, `subprocess`) and reads paths under
407
+ `~/.gemini/antigravity-cli/`, which `agy` writes the same way on every OS. **Developed and verified
408
+ on Windows; macOS and Linux should work unmodified provided `agy -i` runs there.** If you test it on
409
+ those platforms, please open an issue / PR to confirm.
410
+
411
+ ## Development
412
+
413
+ ```bash
414
+ pip install -e ".[dev]" # fastmcp + pytest + ruff
415
+ pytest test_server.py test_swarm.py # offline unit tests — no agy, no quota
416
+ ruff check . && ruff format --check .
417
+ ```
418
+
419
+ `test_server.py` and `test_swarm.py` cover the pure parsing/version/swarm logic with temp fixtures
420
+ (no agy needed); `test_smoke.py` is the live end-to-end check (ask, continue, image, and a parallel
421
+ swarm) that spends a little quota. Set **`AGY_BRIDGE_DEBUG=1`**
422
+ to log per-call diagnostics (resolved conversation id, agy exit code, elapsed) to stderr — and on
423
+ startup the server warns if your installed agy is newer than the version it was verified against.
424
+
425
+ **Staying up to date.** The bridge is distributed by `git clone`, so it does not auto-update; pull
426
+ and restart Claude Code to get new versions. To make that visible, on startup the server polls the
427
+ GitHub tags API once and logs a one-line warning to stderr if a newer release tag exists than the
428
+ running code (`__version__` in `server.py`). The check is best-effort — silent when offline or
429
+ rate-limited, never blocks startup. Control it with:
430
+
431
+ | Env var | Effect |
432
+ |---|---|
433
+ | `AGY_BRIDGE_NO_UPDATE_CHECK=1` | Skip the GitHub check entirely (fully offline startup). |
434
+ | `AGY_BRIDGE_REPO=owner/name` | Point the check at a fork instead of the upstream repo. |
435
+
436
+ **Releasing.** Bump the version in **both** `pyproject.toml` and `server.py` (`__version__`), update
437
+ [`CHANGELOG.md`](CHANGELOG.md), then tag:
438
+
439
+ ```bash
440
+ git tag vX.Y.Z && git push origin vX.Y.Z
441
+ ```
442
+
443
+ The tag triggers two workflows: `release.yml` cuts a GitHub Release with auto-generated notes, and
444
+ `publish.yml` builds and uploads to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
445
+ (no stored token — `publish.yml` verifies the tag matches `pyproject.toml` first). One-time setup:
446
+ register the trusted publisher at `pypi.org/manage/project/antigravity-intern/settings/publishing/`
447
+ (repo `SinanTufekci/antigravity-intern`, workflow `publish.yml`, environment `pypi`).
448
+
449
+ ## Contributing
450
+
451
+ Personal project, **best-effort maintenance** — issues and PRs welcome, but no uptime/compat
452
+ promises. If `agy -p` ever starts printing to stdout correctly, this whole repo becomes a fun
453
+ historical artefact.
454
+
455
+ ## 🌐 Community & Acknowledgments
456
+
457
+ - **Qiita (Japan):** A huge thanks to `@fallout` and the Japanese developer community for featuring this project and providing invaluable feedback!
458
+ - [Detailed Hybrid Setup Guide (Claude Code × Antigravity CLI)](https://qiita.com/fallout/items/5097f0575b58f4c69b81)
459
+ - [Quick Installation Guide](https://qiita.com/fallout/items/d699df3d6931c07eb38d)
460
+
461
+ > 💡 **Path Resolution Fix:** Thanks to their community's real-world testing, we identified and resolved a Windows PATH edge case where the MCP server inherits a *stale* `PATH` at startup and can't find `agy`. The `AGY_BIN` environment-variable fallback was implemented directly inspired by their report!
462
+
463
+ ## License
464
+
465
+ [MIT](LICENSE). Do whatever you want with it.