6.5 KiB
Antigravity Rust Proxy
OpenAI-compatible proxy that intercepts and relays requests to Google's Antigravity language server, impersonating the real Electron webview.
Quick Start
# Build
cargo build --release
# Run (language server must be running)
RUST_LOG=info ./target/release/antigravity-proxy
# Custom port
RUST_LOG=info ./target/release/antigravity-proxy --port 9000
Default port: 8741
Endpoints
| Method | Path | Description |
|---|---|---|
POST |
/v1/responses |
Responses API (primary) — supports stream: true/false |
POST |
/v1/chat/completions |
Chat Completions API (OpenAI compat shim) |
GET |
/v1/models |
List available models |
GET |
/v1/sessions |
List active sessions |
DELETE |
/v1/sessions/:id |
Delete a session |
POST |
/v1/token |
Set OAuth token at runtime |
GET |
/v1/usage |
MITM-intercepted token usage stats |
GET |
/v1/quota |
LS quota — credits, per-model rate limits, reset timers |
GET |
/health |
Health check |
Available Models
| Name | Label |
|---|---|
opus-4.6 |
Claude Opus 4.6 (Thinking) — default |
opus-4.5 |
Claude Opus 4.5 (Thinking) |
gemini-3-pro-high |
Gemini 3 Pro (High) |
gemini-3-pro |
Gemini 3 Pro (Low) |
gemini-3-flash |
Gemini 3 Flash |
Development & Testing
- Dev/testing model:
gemini-3-flash— use this for all development, debugging, and iterative testing - Production model:
opus-4.6— use sparingly for real-world validation only (has quota limit) - See
docs/ls-binary-analysis.mdfor full reverse-engineered model catalog and proto enum mappings
Example: Responses API
Sync
curl -s http://localhost:8741/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-flash",
"input": "Say hello in exactly 3 words",
"stream": false,
"timeout": 60
}' | jq .
Streaming
curl -N http://localhost:8741/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-flash",
"input": "Say hello in exactly 3 words",
"stream": true,
"timeout": 60
}'
Multi-turn (session reuse)
curl -s http://localhost:8741/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-flash",
"input": "What is 2+2?",
"conversation": "my-session-1",
"stream": false
}' | jq .
# Follow-up in same cascade:
curl -s http://localhost:8741/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-flash",
"input": "Now multiply that by 10",
"conversation": "my-session-1",
"stream": false
}' | jq .
Authentication
The proxy needs an OAuth token. Three ways to provide it:
- Environment variable:
export ANTIGRAVITY_OAUTH_TOKEN=ya29.xxx - Token file:
echo 'ya29.xxx' > ~/.config/antigravity-proxy-token - Runtime API:
curl -X POST http://localhost:8741/v1/token -d '{"token":"ya29.xxx"}'
Version Detection
Version strings (Antigravity, Chrome, Electron, Client) are auto-detected at startup from the installed Antigravity app:
product.json→ app version + client/IDE version- Binary → Chrome + Electron versions via
strings
Falls back to hardcoded values if the app isn't installed. No manual updates needed when Antigravity updates.
Stealth Features
- TLS fingerprint: BoringSSL with Chrome JA3/JA4 + H2 fingerprint via
wreq(version auto-detected) - Protobuf: Hand-rolled encoder producing byte-exact match to real webview traffic
- Warmup: Mimics real webview startup RPC calls
- Heartbeat: Periodic keep-alive matching real webview lifecycle
- Jitter: Randomized polling intervals to avoid automation fingerprint
- Session reuse: Cascades are reused for multi-turn, matching real webview behavior
- MITM proxy: TLS-intercepting proxy for real token usage capture (opt-in)
MITM Proxy
Built-in MITM proxy intercepts LS ↔ Google/Anthropic traffic to capture real token usage (input, output, cache read, cache creation). Disabled with --no-mitm.
Setup
# 1. Start proxy (generates CA cert automatically)
RUST_LOG=info ./target/release/antigravity-proxy
# 2. Patch extension to enable proxy detection (required!)
# The LS has a protobuf field `detect_and_use_proxy` that defaults to UNSPECIFIED,
# which means it ignores HTTPS_PROXY for LLM API calls. This patch sets it to ENABLED (1).
# Must be re-applied after every Antigravity update.
sudo sed -i -E 's/detectAndUseProxy=[^,;)]+/detectAndUseProxy=1/g' \
/usr/share/antigravity/resources/app/extensions/antigravity/dist/extension.js
# 3. Install wrapper (patches LS binary to route through MITM)
./scripts/mitm-wrapper.sh install
# 4. Restart Antigravity — done!
# Check status
./scripts/mitm-wrapper.sh status
# Uninstall
./scripts/mitm-wrapper.sh uninstall
Extension Patch Details
The LS uses daily-cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse for LLM API calls (regular HTTPS+SSE, NOT gRPC). The LS binary checks a protobuf field (detect_and_use_proxy, field 34 on init metadata) to decide whether to honor HTTPS_PROXY. The extension defaults this to UNSPECIFIED (ignore proxy). The sed patch above changes it to ENABLED (value 1), allowing the MITM wrapper's env vars to take effect.
Verify patch: grep -o 'detectAndUseProxy=[^;]*' /usr/share/antigravity/resources/app/extensions/antigravity/dist/extension.js should show detectAndUseProxy=1.
Model IDs (for standalone LS testing): See docs/ls-binary-analysis.md for the full proto enum mapping.
Usage Stats
curl -s http://localhost:8741/v1/usage | jq .
Returns aggregate token counts from all intercepted API calls.
CLI Flags
--no-mitm: Disable MITM proxy entirely--mitm-port <PORT>: Override MITM proxy port (default: auto-assign)