Browse Source

feat: add native Antigravity (Google Provider) support (#114)

- Add --antigravity flag to installer CLI (interactive and non-interactive)
- Configure opencode.json with Google Provider and all models
- Generate mixed presets with intelligent agent mapping:
  * antigravity-mixed-both: Kimi orchestrator + GPT oracle + Antigravity workers
  * antigravity-mixed-kimi: Kimi orchestrator + Antigravity oracle/workers
  * antigravity-mixed-openai: Antigravity orchestrator + GPT oracle + Antigravity workers
  * antigravity: Pure Antigravity across all agents
- Support both Antigravity and Gemini CLI models (9 total)
- Update all documentation with native installation method
- Remove deprecated cliproxy references
- Add comprehensive test coverage (7 new tests)
- Maintain full backward compatibility

The installer automatically:
- Adds opencode-antigravity-auth@latest plugin
- Configures Google provider with 5 Antigravity + 4 Gemini CLI models
- Sets up optimal agent mapping based on available providers
Gabriel Rodrigues 2 months ago
parent
commit
f602e0a156
10 changed files with 721 additions and 386 deletions
  1. 2 1
      README.md
  2. 130 308
      docs/antigravity.md
  3. 30 6
      docs/installation.md
  4. 24 60
      docs/quick-reference.md
  5. 157 1
      src/cli/config-io.ts
  6. 7 1
      src/cli/index.ts
  7. 36 3
      src/cli/install.ts
  8. 189 1
      src/cli/providers.test.ts
  9. 143 5
      src/cli/providers.ts
  10. 3 0
      src/cli/types.ts

+ 2 - 1
README.md

@@ -1,7 +1,7 @@
 <div align="center">
   <img src="img/team.png" alt="Pantheon agents" width="420">
   <p><i>Six divine beings emerged from the dawn of code, each an immortal master of their craft await your command to forge order from chaos and build what was once thought impossible.</i></p>
-  <p><b>Multi Agent Suite</b> · Mix any models · Auto delegate tasks</p>
+  <p><b>Multi Agent Suite</b> · Mix any models · Auto delegate tasks · Now with native Antigravity support</p>
 </div>
 
 ---
@@ -22,6 +22,7 @@ opencode auth login
 
 Run `ping all agents` to verify everything works.
 
+> **💡 Models are fully customizable.** Edit `~/.config/opencode/oh-my-opencode-slim.json` to assign any model to any agent. Supports Kimi, OpenAI, and Antigravity (Google) providers.
 > **💡 Models are fully customizable.** Edit `~/.config/opencode/oh-my-opencode-slim.json` (or `.jsonc` for comments support) to assign any model to any agent.
 
 ### For LLM Agents

+ 130 - 308
docs/antigravity.md

@@ -1,157 +1,150 @@
-# Antigravity Provider Setup Guide
+# Antigravity Setup Guide
 
-Complete guide for configuring Antigravity provider with oh-my-opencode-slim to access Claude and Gemini models through the "google" provider configuration.
+## Quick Setup
 
-## Table of Contents
+1. Install with Antigravity support:
+   ```bash
+   bunx oh-my-opencode-slim install --antigravity=yes
+   ```
 
-- [Overview](#overview)
-- [Installation](#installation)
-- [Configuration](#configuration)
-- [Provider Setup](#provider-setup)
-- [Agent Model Assignment](#agent-model-assignment)
-- [Usage Examples](#usage-examples)
-- [Troubleshooting](#troubleshooting)
+2. Authenticate:
+   ```bash
+   opencode auth login
+   # Select "google" provider
+   ```
 
----
+3. Start using:
+   ```bash
+   opencode
+   ```
 
-## Overview
+## How It Works
 
-Antigravity provides access to high-quality Claude and Gemini models through a unified interface. This guide shows you how to configure oh-my-opencode-slim to use Antigravity via the "google" provider configuration.
+The installer automatically:
+- Adds `opencode-antigravity-auth@latest` plugin
+- Configures Google provider with all Antigravity and Gemini CLI models
+- Sets up agent mapping (Kimi/GPT for Orchestrator/Oracle, Antigravity for others)
 
-**Benefits:**
-- Access to Claude Opus 4.5 Thinking and Sonnet 4.5 Thinking models
-- Gemini 3 Pro High and Flash models
-- Unified configuration through OpenCode
-- Excellent for complex reasoning tasks (Claude) and fast responses (Gemini)
+## Models Available
 
----
+### Antigravity Models (via Google Infrastructure)
 
-## Installation
+1. **antigravity-gemini-3-pro**
+   - Name: Gemini 3 Pro (Antigravity)
+   - Context: 1M tokens, Output: 65K tokens
+   - Variants: low, high thinking levels
+   - Best for: Complex reasoning, high-quality outputs
 
-### Prerequisites
+2. **antigravity-gemini-3-flash**
+   - Name: Gemini 3 Flash (Antigravity)
+   - Context: 1M tokens, Output: 65K tokens
+   - Variants: minimal, low, medium, high thinking levels
+   - Best for: Fast responses, efficient agent tasks
 
-1. **Install oh-my-opencode-slim:**
-   ```bash
-   bunx oh-my-opencode-slim@latest install
-   ```
+3. **antigravity-claude-sonnet-4-5**
+   - Name: Claude Sonnet 4.5 (Antigravity)
+   - Context: 200K tokens, Output: 64K tokens
+   - Best for: Balanced performance
 
-2. **Set up Antigravity/LLM-Mux:**
-   Follow the installation guide at https://nghyane.github.io/llm-mux/#/installation
+4. **antigravity-claude-sonnet-4-5-thinking**
+   - Name: Claude Sonnet 4.5 Thinking (Antigravity)
+   - Context: 200K tokens, Output: 64K tokens
+   - Variants: low (8K budget), max (32K budget)
+   - Best for: Deep reasoning tasks
 
-3. **Start the Antigravity service:**
-   Ensure your Antigravity service is running on `http://127.0.0.1:8317`
+5. **antigravity-claude-opus-4-5-thinking**
+   - Name: Claude Opus 4.5 Thinking (Antigravity)
+   - Context: 200K tokens, Output: 64K tokens
+   - Variants: low (8K budget), max (32K budget)
+   - Best for: Most complex reasoning
 
----
+### Gemini CLI Models (Fallback)
 
-## Configuration
+6. **gemini-2.5-flash**
+   - Name: Gemini 2.5 Flash (Gemini CLI)
+   - Context: 1M tokens, Output: 65K tokens
+   - Requires: Gemini CLI authentication
 
-### Step 1: Configure Provider in OpenCode
+7. **gemini-2.5-pro**
+   - Name: Gemini 2.5 Pro (Gemini CLI)
+   - Context: 1M tokens, Output: 65K tokens
+   - Requires: Gemini CLI authentication
 
-Edit `~/.config/opencode/opencode.json` and add the "google" provider configuration:
+8. **gemini-3-flash-preview**
+   - Name: Gemini 3 Flash Preview (Gemini CLI)
+   - Context: 1M tokens, Output: 65K tokens
+   - Requires: Gemini CLI authentication
 
-```json
-{
-  "provider": {
-    "google": {
-      "options": {
-        "baseURL": "http://127.0.0.1:8317/v1beta",
-        "apiKey": "sk-dummy"
-      },
-      "models": {
-        "gemini-3-pro-high": {
-          "name": "Gemini 3 Pro High",
-          "attachment": true,
-          "limit": {
-            "context": 1048576,
-            "output": 65535
-          },
-          "modalities": {
-            "input": ["text", "image", "pdf"],
-            "output": ["text"]
-          }
-        },
-        "gemini-3-flash": {
-          "name": "Gemini 3 Flash",
-          "attachment": true,
-          "limit": {
-            "context": 1048576,
-            "output": 65536
-          },
-          "modalities": {
-            "input": ["text", "image", "pdf"],
-            "output": ["text"]
-          }
-        },
-        "claude-opus-4-5-thinking": {
-          "name": "Claude Opus 4.5 Thinking",
-          "attachment": true,
-          "limit": {
-            "context": 200000,
-            "output": 32000
-          },
-          "modalities": {
-            "input": ["text", "image", "pdf"],
-            "output": ["text"]
-          }
-        },
-        "claude-sonnet-4-5-thinking": {
-          "name": "Claude Sonnet 4.5 Thinking",
-          "attachment": true,
-          "limit": {
-            "context": 200000,
-            "output": 32000
-          },
-          "modalities": {
-            "input": ["text", "image", "pdf"],
-            "output": ["text"]
-          }
-        }
-      }
-    }
-  }
-}
-```
+9. **gemini-3-pro-preview**
+   - Name: Gemini 3 Pro Preview (Gemini CLI)
+   - Context: 1M tokens, Output: 65K tokens
+   - Requires: Gemini CLI authentication
+
+## Agent Configuration
+
+When you install with `--antigravity=yes`, the preset depends on other providers:
+
+### antigravity-mixed-both (Kimi + OpenAI + Antigravity)
+- **Orchestrator**: Kimi k2p5
+- **Oracle**: GPT-5.2-codex
+- **Explorer/Librarian/Designer/Fixer**: Gemini 3 Flash (Antigravity)
+
+### antigravity-mixed-kimi (Kimi + Antigravity)
+- **Orchestrator**: Kimi k2p5
+- **Oracle**: Gemini 3 Pro (Antigravity)
+- **Explorer/Librarian/Designer/Fixer**: Gemini 3 Flash (Antigravity)
 
-### Step 2: Configure Agent Models
+### antigravity-mixed-openai (OpenAI + Antigravity)
+- **Orchestrator**: Gemini 3 Flash (Antigravity)
+- **Oracle**: GPT-5.2-codex
+- **Explorer/Librarian/Designer/Fixer**: Gemini 3 Flash (Antigravity)
 
+### antigravity (Pure Antigravity)
+- **Orchestrator**: Gemini 3 Flash (Antigravity)
+- **Oracle**: Gemini 3 Pro (Antigravity)
+- **Explorer/Librarian/Designer/Fixer**: Gemini 3 Flash (Antigravity)
+
+## Manual Configuration
+
+If you prefer to configure manually, edit `~/.config/opencode/oh-my-opencode-slim.json`:
 Edit `~/.config/opencode/oh-my-opencode-slim.json` (or `.jsonc`) and add the Antigravity preset:
 
 ```json
 {
-  "preset": "antigravity",
+  "preset": "antigravity-mixed-both",
   "presets": {
-    "antigravity": {
+    "antigravity-mixed-both": {
       "orchestrator": {
-        "model": "google/claude-opus-4-5-thinking",
+        "model": "kimi-for-coding/k2p5",
         "skills": ["*"],
         "mcps": ["websearch"]
       },
       "oracle": {
-        "model": "google/gemini-3-pro-high",
+        "model": "openai/gpt-5.2-codex",
         "variant": "high",
         "skills": [],
         "mcps": []
       },
-      "librarian": {
-        "model": "google/gemini-3-flash",
+      "explorer": {
+        "model": "google/antigravity-gemini-3-flash",
         "variant": "low",
         "skills": [],
-        "mcps": ["websearch", "context7", "grep_app"]
+        "mcps": []
       },
-      "explorer": {
-        "model": "google/gemini-3-flash",
+      "librarian": {
+        "model": "google/antigravity-gemini-3-flash",
         "variant": "low",
         "skills": [],
-        "mcps": []
+        "mcps": ["websearch", "context7", "grep_app"]
       },
       "designer": {
-        "model": "google/gemini-3-flash",
+        "model": "google/antigravity-gemini-3-flash",
         "variant": "medium",
         "skills": ["agent-browser"],
         "mcps": []
       },
       "fixer": {
-        "model": "google/gemini-3-flash",
+        "model": "google/antigravity-gemini-3-flash",
         "variant": "low",
         "skills": [],
         "mcps": []
@@ -161,222 +154,51 @@ Edit `~/.config/opencode/oh-my-opencode-slim.json` (or `.jsonc`) and add the Ant
 }
 ```
 
----
-
-## Provider Setup
-
-### Available Models
-
-| Model | Type | Context Window | Output Limit | Best For |
-|-------|------|----------------|--------------|----------|
-| `claude-opus-4-5-thinking` | Claude | 200K tokens | 32K tokens | Complex reasoning, orchestrator |
-| `claude-sonnet-4-5-thinking` | Claude | 200K tokens | 32K tokens | Balanced reasoning and speed |
-| `gemini-3-pro-high` | Gemini | 1M tokens | 65K tokens | High-quality responses |
-| `gemini-3-flash` | Gemini | 1M tokens | 65K tokens | Fast responses, cost-effective |
-
-### Model Recommendations
-
-**For Orchestrator:** Use `claude-opus-4-5-thinking`
-- Best reasoning capabilities for multi-agent coordination
-- Excellent at planning complex workflows
-- Can handle large context windows
-
-**For Oracle:** Use `gemini-3-pro-high`  
-- Strategic thinking and debugging
-- High-quality architectural advice
-
-**For Support Agents:** Use `gemini-3-flash`
-- Fast and cost-effective for routine tasks
-- Good for librarian, explorer, designer, and fixer roles
-
----
-
-## Agent Model Assignment
-
-### Basic Configuration
+## Troubleshooting
 
-The preset assigns models based on their strengths:
+### Authentication Failed
+```bash
+# Ensure Antigravity service is running
+# Check service status
+curl http://127.0.0.1:8317/health
 
-```json
-{
-  "presets": {
-    "antigravity": {
-      "orchestrator": { "model": "google/claude-opus-4-5-thinking" },
-      "oracle": { "model": "google/gemini-3-pro-high", "variant": "high" },
-      "librarian": { "model": "google/gemini-3-flash", "variant": "low" },
-      "explorer": { "model": "google/gemini-3-flash", "variant": "low" },
-      "designer": { "model": "google/gemini-3-flash", "variant": "medium" },
-      "fixer": { "model": "google/gemini-3-flash", "variant": "low" }
-    }
-  }
-}
+# Re-authenticate
+opencode auth login
 ```
 
-### Custom Assignments
-
-You can customize which model each agent uses:
-
-**Example: All Claude for reasoning-heavy work:**
-```json
-{
-  "presets": {
-    "claude-heavy": {
-      "orchestrator": { "model": "google/claude-opus-4-5-thinking" },
-      "oracle": { "model": "google/claude-sonnet-4-5-thinking", "variant": "high" },
-      "librarian": { "model": "google/claude-sonnet-4-5-thinking", "variant": "low" },
-      "explorer": { "model": "google/claude-sonnet-4-5-thinking", "variant": "low" },
-      "designer": { "model": "google/claude-sonnet-4-5-thinking", "variant": "medium" },
-      "fixer": { "model": "google/claude-sonnet-4-5-thinking", "variant": "low" }
-    }
-  }
-}
-```
+### Models Not Available
+```bash
+# Verify plugin is installed
+cat ~/.config/opencode/opencode.json | grep antigravity
 
-**Example: Mixed setup with cost optimization:**
-```json
-{
-  "presets": {
-    "cost-optimized": {
-      "orchestrator": { "model": "google/claude-sonnet-4-5-thinking" },
-      "oracle": { "model": "google/gemini-3-pro-high", "variant": "high" },
-      "librarian": { "model": "google/gemini-3-flash", "variant": "low" },
-      "explorer": { "model": "google/gemini-3-flash", "variant": "low" },
-      "designer": { "model": "google/gemini-3-flash", "variant": "low" },
-      "fixer": { "model": "google/gemini-3-flash", "variant": "low" }
-    }
-  }
-}
+# Reinstall plugin
+bunx oh-my-opencode-slim install --antigravity=yes --no-tui --kimi=no --openai=no --tmux=no --skills=no
 ```
 
----
-
-## Usage Examples
-
-### Switching to Antigravity Preset
-
+### Wrong Model Selected
 ```bash
-# Edit the preset in your config
+# Check current preset
+echo $OH_MY_OPENCODE_SLIM_PRESET
+
+# Change preset
 export OH_MY_OPENCODE_SLIM_PRESET=antigravity
 opencode
 ```
 
-### Testing Configuration
-
-1. **Verify provider connection:**
-   ```bash
-   opencode auth status
-   ```
-
-2. **Test agent responses:**
-   ```bash
-   opencode
-   # In OpenCode, run: ping all agents
-   ```
-
-3. **Check logs for any connection issues:**
-   ```bash
-   tail -f ~/.config/opencode/logs/opencode.log
-   ```
-
-### Example Workflow
-
-Once configured, you can ask the orchestrator to handle complex tasks:
-
-```
-Orchestrator, please analyze this codebase and create a comprehensive refactoring plan.
-Use your team to:
-1. Map the current architecture
-2. Identify bottlenecks and issues  
-3. Create a detailed implementation plan
-4. Estimate effort and risks
-```
-
-The orchestrator will delegate to specialists using the configured Antigravity models.
-
----
-
-## Troubleshooting
-
-### Provider Connection Issues
-
-**Problem:** Agents not responding or showing connection errors
-
-**Solutions:**
-1. Verify Antigravity service is running:
-   ```bash
-   curl http://127.0.0.1:8317/v1beta/models
-   ```
-
-2. Check the baseURL in your config matches your service:
-   ```json
-   {
-     "options": {
-       "baseURL": "http://127.0.0.1:8317/v1beta"
-     }
-   }
-   ```
-
-3. Verify your API key (can be dummy value like "sk-dummy")
-
-### Model Not Found Errors
-
-**Problem:** "Model not found" or similar errors
-
-**Solutions:**
-1. Ensure the model names match exactly:
-   - `claude-opus-4-5-thinking` (not `claude-opus-4.5-thinking`)
-   - `gemini-3-flash` (not `gemini-3-flash-preview`)
-
-2. Check your provider configuration includes all required fields:
-   ```json
-   {
-     "models": {
-       "model-name": {
-         "name": "Display Name",
-         "attachment": true,
-         "limit": { "context": 1048576, "output": 65535 },
-         "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }
-       }
-     }
-   }
-   ```
-
-### Authentication Issues
-
-**Problem:** 401 Unauthorized or similar auth errors
-
-**Solutions:**
-1. The `apiKey` can be any dummy value for Antigravity
-2. Ensure the baseURL is correct and accessible
-3. Restart OpenCode after changing configuration
-
-### Performance Issues
-
-**Problem:** Slow responses or timeouts
-
-**Solutions:**
-1. Use `gemini-3-flash` for faster responses on support agents
-2. Check your Antigravity service performance
-3. Consider reducing context sizes for large files
-
-### Switching Between Presets
-
-To test different configurations:
-
+### Service Connection Issues
 ```bash
-# Use environment variable for quick testing
-export OH_MY_OPENCODE_SLIM_PRESET=openai
-opencode
+# Check if Antigravity service is running on correct port
+lsof -i :8317
 
+# Restart the service
+# (Follow your Antigravity/LLM-Mux restart procedure)
 # Or edit ~/.config/opencode/oh-my-opencode-slim.json (or .jsonc)
 # Change the "preset" field and restart OpenCode
 ```
 
----
-
-## Additional Resources
+## Notes
 
-- **LLM-Mux Installation:** https://nghyane.github.io/llm-mux/#/installation
-- **OpenCode Documentation:** https://opencode.ai/docs
-- **Quick Reference:** [docs/quick-reference.md](quick-reference.md)
-- **Installation Guide:** [docs/installation.md](installation.md)
+- **Terms of Service**: Using Antigravity may violate Google's ToS. Use at your own risk.
+- **Performance**: Antigravity models typically have lower latency than direct API calls
+- **Fallback**: Gemini CLI models require separate authentication but work as fallback
+- **Customization**: You can mix and match any models across agents by editing the config

+ 30 - 6
docs/installation.md

@@ -24,7 +24,19 @@ bunx oh-my-opencode-slim@latest install
 Or use non-interactive mode:
 
 ```bash
-bunx oh-my-opencode-slim@latest install --no-tui --kimi=yes --openai=yes --tmux=no
+bunx oh-my-opencode-slim@latest install --no-tui --kimi=yes --openai=yes --antigravity=yes --tmux=no
+```
+
+### Provider Options
+
+The installer supports multiple providers:
+- **Kimi For Coding**: High-performance coding models
+- **OpenAI**: GPT-4 and GPT-3.5 models
+- **Antigravity (Google)**: Claude 4.5 and Gemini 3 models via Google's infrastructure
+
+Enable during installation:
+```bash
+bunx oh-my-opencode-slim install --kimi=yes --openai=yes --antigravity=yes
 ```
 
 ### After Installation
@@ -70,9 +82,13 @@ Ask these questions **one at a time**, waiting for responses:
 
 1. "Do you have access to **Kimi For Coding**?" *(Provides Kimi k1.5 models)*
 2. "Do you have access to **OpenAI** API?" *(Enables `openai/` models)*
+3. "Do you have access to **Antigravity (Google)**?" *(Enables `google/` models via Antigravity)*
 
 Help the user understand the tradeoffs:
 - Kimi For Coding provides powerful k1.5 models for coding tasks.
+- OpenAI enables `openai/` models.
+- Antigravity (Google) provides Claude 4.5 and Gemini 3 models.
+- If the user has **no providers**, the plugin still works using **OpenCode Zen** free models (`opencode/big-pickle`). They can switch to paid providers later by editing `~/.config/opencode/oh-my-opencode-slim.json`.
 - OpenAI is optional; it enables `openai/` models.
 - If the user has **no providers**, the plugin still works using **OpenCode Zen** free models (`opencode/big-pickle`). They can switch to paid providers later by editing `~/.config/opencode/oh-my-opencode-slim.json` (or `.jsonc`).
 
@@ -81,19 +97,19 @@ Help the user understand the tradeoffs:
 Based on answers, run:
 
 ```bash
-bunx oh-my-opencode-slim@latest install --no-tui --kimi=<yes|no> --openai=<yes|no>
+bunx oh-my-opencode-slim@latest install --no-tui --kimi=<yes|no> --openai=<yes|no> --antigravity=<yes|no>
 ```
 
 **Examples:**
 ```bash
-# Kimi + OpenAI
-bunx oh-my-opencode-slim@latest install --no-tui --kimi=yes --openai=yes --tmux=no
+# Kimi + OpenAI + Antigravity
+bunx oh-my-opencode-slim@latest install --no-tui --kimi=yes --openai=yes --antigravity=yes --tmux=no
 
 # OpenAI only
-bunx oh-my-opencode-slim@latest install --no-tui --kimi=no --openai=yes --tmux=no
+bunx oh-my-opencode-slim@latest install --no-tui --kimi=no --openai=yes --antigravity=no --tmux=no
 
 # No providers (Zen free models only)
-bunx oh-my-opencode-slim@latest install --no-tui --kimi=no --openai=no --tmux=no
+bunx oh-my-opencode-slim@latest install --no-tui --kimi=no --openai=no --antigravity=no --tmux=no
 ```
 
 The installer automatically:
@@ -123,6 +139,14 @@ opencode auth login
 # Select your provider and complete OAuth flow
 ```
 
+**For Antigravity (if enabled):**
+Ask user to run the following command.
+Don't run it yourself, it requires user interaction.
+```bash
+opencode auth login
+# Select "Antigravity (Google)" provider and complete OAuth flow
+```
+
 ---
 
 ## Troubleshooting

+ 24 - 60
docs/quick-reference.md

@@ -60,72 +60,36 @@ Uses OpenAI models exclusively:
 }
 ```
 
-### Antigravity via CLIProxy Preset
+### Google Provider (Antigravity)
 
-Routes through Antigravity's CLIProxy for Claude + Gemini models:
+Access Claude 4.5 and Gemini 3 models through Google's Antigravity infrastructure.
 
-```json
-{
-  "preset": "cliproxy",
-  "presets": {
-    "cliproxy": {
-      "orchestrator": { "model": "cliproxy/gemini-claude-opus-4-5-thinking", "skills": ["*"], "mcps": ["websearch"] },
-      "oracle": { "model": "cliproxy/gemini-3-pro-preview", "variant": "high", "skills": [], "mcps": [] },
-      "librarian": { "model": "cliproxy/gemini-3-flash-preview", "variant": "low", "skills": [], "mcps": ["websearch", "context7", "grep_app"] },
-      "explorer": { "model": "cliproxy/gemini-3-flash-preview", "variant": "low", "skills": [], "mcps": [] },
-      "designer": { "model": "cliproxy/gemini-3-flash-preview", "variant": "medium", "skills": ["agent-browser"], "mcps": [] },
-      "fixer": { "model": "cliproxy/gemini-3-flash-preview", "variant": "low", "skills": [], "mcps": [] }
-    }
-  }
-}
+**Installation:**
+```bash
+bunx oh-my-opencode-slim install --antigravity=yes
 ```
 
-<details>
-<summary>Verify provider configuration in ~/.config/opencode/opencode.json</summary>
+**Agent Mapping:**
+- Orchestrator: Kimi (if available)
+- Oracle: GPT (if available)
+- Explorer/Librarian/Designer/Fixer: Gemini 3 Flash via Antigravity
 
-```json
-{
-  "provider": {
-    "cliproxy": {
-      "npm": "@ai-sdk/openai-compatible",
-      "name": "CliProxy",
-      "options": {
-        "baseURL": "http://127.0.0.1:8317/v1",
-        "apiKey": "your-api-key-1"
-      },
-      "models": {
-        "gemini-3-pro-high": {
-          "name": "Gemini 3 Pro High",
-          "thinking": true,
-          "attachment": true,
-          "limit": { "context": 1048576, "output": 65535 },
-          "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] }
-        },
-        "gemini-3-flash-preview": {
-          "name": "Gemini 3 Flash",
-          "attachment": true,
-          "limit": { "context": 1048576, "output": 65536 },
-          "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] }
-        },
-        "gemini-claude-opus-4-5-thinking": {
-          "name": "Claude Opus 4.5 Thinking",
-          "attachment": true,
-          "limit": { "context": 200000, "output": 32000 },
-          "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] }
-        },
-        "gemini-claude-sonnet-4-5-thinking": {
-          "name": "Claude Sonnet 4.5 Thinking",
-          "attachment": true,
-          "limit": { "context": 200000, "output": 32000 },
-          "modalities": { "input": [ "text", "image", "pdf" ], "output": [ "text" ] }
-        }
-      }
-    }
-  }
-}
+**Authentication:**
+```bash
+opencode auth login
+# Select "google" provider
 ```
 
-</details>
+**Available Models:**
+- `google/antigravity-gemini-3-flash`
+- `google/antigravity-gemini-3-pro`
+- `google/antigravity-claude-sonnet-4-5`
+- `google/antigravity-claude-sonnet-4-5-thinking`
+- `google/antigravity-claude-opus-4-5-thinking`
+- `google/gemini-2.5-flash` (Gemini CLI)
+- `google/gemini-2.5-pro` (Gemini CLI)
+- `google/gemini-3-flash-preview` (Gemini CLI)
+- `google/gemini-3-pro-preview` (Gemini CLI)
 
 ### Author's Preset
 
@@ -500,7 +464,7 @@ The installer generates this file based on your providers. You can manually cust
 
 | Option | Type | Default | Description |
 |--------|------|---------|-------------|
-| `preset` | string | - | Name of the preset to use (e.g., `"openai"`, `"cliproxy"`) |
+| `preset` | string | - | Name of the preset to use (e.g., `"openai"`, `"antigravity"`) |
 | `presets` | object | - | Named preset configurations containing agent mappings |
 | `presets.<name>.<agent>.model` | string | - | Model ID for the agent (e.g., `"google/claude-opus-4-5-thinking"`) |
 | `presets.<name>.<agent>.temperature` | number | - | Temperature setting (0-2) for the agent |

+ 157 - 1
src/cli/config-io.ts

@@ -203,11 +203,160 @@ export function disableDefaultAgents(): ConfigMergeResult {
   }
 }
 
+export function canModifyOpenCodeConfig(): boolean {
+  try {
+    const configPath = getExistingConfigPath();
+    if (!existsSync(configPath)) return true; // Will be created
+    const stat = statSync(configPath);
+    // Check if writable - simple check for now
+    return !!(stat.mode & 0o200);
+  } catch {
+    return false;
+  }
+}
+
+export function addAntigravityPlugin(): ConfigMergeResult {
+  const configPath = getExistingConfigPath();
+  try {
+    const { config: parsedConfig, error } = parseConfig(configPath);
+    if (error) {
+      return {
+        success: false,
+        configPath,
+        error: `Failed to parse config: ${error}`,
+      };
+    }
+    const config = parsedConfig ?? {};
+    const plugins = config.plugin ?? [];
+
+    const pluginName = 'opencode-antigravity-auth@latest';
+    if (!plugins.includes(pluginName)) {
+      plugins.push(pluginName);
+    }
+    config.plugin = plugins;
+
+    writeConfig(configPath, config);
+    return { success: true, configPath };
+  } catch (err) {
+    return {
+      success: false,
+      configPath,
+      error: `Failed to add antigravity plugin: ${err}`,
+    };
+  }
+}
+
+export function addGoogleProvider(): ConfigMergeResult {
+  const configPath = getExistingConfigPath();
+  try {
+    const { config: parsedConfig, error } = parseConfig(configPath);
+    if (error) {
+      return {
+        success: false,
+        configPath,
+        error: `Failed to parse config: ${error}`,
+      };
+    }
+    const config = parsedConfig ?? {};
+    const providers = (config.provider ?? {}) as Record<string, unknown>;
+
+    providers.google = {
+      models: {
+        'antigravity-gemini-3-pro': {
+          name: 'Gemini 3 Pro (Antigravity)',
+          limit: { context: 1048576, output: 65535 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+          variants: {
+            low: { thinkingLevel: 'low' },
+            high: { thinkingLevel: 'high' },
+          },
+        },
+        'antigravity-gemini-3-flash': {
+          name: 'Gemini 3 Flash (Antigravity)',
+          limit: { context: 1048576, output: 65536 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+          variants: {
+            minimal: { thinkingLevel: 'minimal' },
+            low: { thinkingLevel: 'low' },
+            medium: { thinkingLevel: 'medium' },
+            high: { thinkingLevel: 'high' },
+          },
+        },
+        'antigravity-claude-sonnet-4-5': {
+          name: 'Claude Sonnet 4.5 (Antigravity)',
+          limit: { context: 200000, output: 64000 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+        },
+        'antigravity-claude-sonnet-4-5-thinking': {
+          name: 'Claude Sonnet 4.5 Thinking (Antigravity)',
+          limit: { context: 200000, output: 64000 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+          variants: {
+            low: { thinkingConfig: { thinkingBudget: 8192 } },
+            max: { thinkingConfig: { thinkingBudget: 32768 } },
+          },
+        },
+        'antigravity-claude-opus-4-5-thinking': {
+          name: 'Claude Opus 4.5 Thinking (Antigravity)',
+          limit: { context: 200000, output: 64000 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+          variants: {
+            low: { thinkingConfig: { thinkingBudget: 8192 } },
+            max: { thinkingConfig: { thinkingBudget: 32768 } },
+          },
+        },
+        'gemini-2.5-flash': {
+          name: 'Gemini 2.5 Flash (Gemini CLI)',
+          limit: { context: 1048576, output: 65536 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+        },
+        'gemini-2.5-pro': {
+          name: 'Gemini 2.5 Pro (Gemini CLI)',
+          limit: { context: 1048576, output: 65536 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+        },
+        'gemini-3-flash-preview': {
+          name: 'Gemini 3 Flash Preview (Gemini CLI)',
+          limit: { context: 1048576, output: 65536 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+        },
+        'gemini-3-pro-preview': {
+          name: 'Gemini 3 Pro Preview (Gemini CLI)',
+          limit: { context: 1048576, output: 65535 },
+          modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
+        },
+      },
+    };
+    config.provider = providers;
+
+    writeConfig(configPath, config);
+    return { success: true, configPath };
+  } catch (err) {
+    return {
+      success: false,
+      configPath,
+      error: `Failed to add google provider: ${err}`,
+    };
+  }
+}
+
+export function detectAntigravityConfig(): boolean {
+  const { config } = parseConfig(getExistingConfigPath());
+  if (!config) return false;
+
+  const providers = config.provider as Record<string, unknown> | undefined;
+  if (providers?.google) return true;
+
+  const plugins = config.plugin ?? [];
+  return plugins.some((p) => p.startsWith('opencode-antigravity-auth'));
+}
+
 export function detectCurrentConfig(): DetectedConfig {
   const result: DetectedConfig = {
     isInstalled: false,
     hasKimi: false,
     hasOpenAI: false,
+    hasAntigravity: false,
     hasOpencodeZen: false,
     hasTmux: false,
   };
@@ -217,10 +366,14 @@ export function detectCurrentConfig(): DetectedConfig {
 
   const plugins = config.plugin ?? [];
   result.isInstalled = plugins.some((p) => p.startsWith(PACKAGE_NAME));
+  result.hasAntigravity = plugins.some((p) =>
+    p.startsWith('opencode-antigravity-auth'),
+  );
 
-  // Check for kimi provider
+  // Check for providers
   const providers = config.provider as Record<string, unknown> | undefined;
   result.hasKimi = !!providers?.kimi;
+  if (providers?.google) result.hasAntigravity = true;
 
   // Try to detect from lite config
   const { config: liteConfig } = parseConfig(getLiteConfig());
@@ -238,6 +391,9 @@ export function detectCurrentConfig(): DetectedConfig {
         .filter(Boolean);
       result.hasOpenAI = models.some((m) => m?.startsWith('openai/'));
       result.hasOpencodeZen = models.some((m) => m?.startsWith('opencode/'));
+      if (models.some((m) => m?.startsWith('google/'))) {
+        result.hasAntigravity = true;
+      }
     }
 
     if (configObj.tmux && typeof configObj.tmux === 'object') {

+ 7 - 1
src/cli/index.ts

@@ -14,8 +14,12 @@ function parseArgs(args: string[]): InstallArgs {
       result.kimi = arg.split('=')[1] as BooleanArg;
     } else if (arg.startsWith('--openai=')) {
       result.openai = arg.split('=')[1] as BooleanArg;
+    } else if (arg.startsWith('--antigravity=')) {
+      result.antigravity = arg.split('=')[1] as BooleanArg;
     } else if (arg.startsWith('--tmux=')) {
       result.tmux = arg.split('=')[1] as BooleanArg;
+    } else if (arg.startsWith('--skills=')) {
+      result.skills = arg.split('=')[1] as BooleanArg;
     } else if (arg === '-h' || arg === '--help') {
       printHelp();
       process.exit(0);
@@ -34,13 +38,15 @@ Usage: bunx oh-my-opencode-slim install [OPTIONS]
 Options:
   --kimi=yes|no          Kimi API access (yes/no)
   --openai=yes|no        OpenAI API access (yes/no)
+  --antigravity=yes|no   Antigravity/Google models (yes/no)
   --tmux=yes|no          Enable tmux integration (yes/no)
+  --skills=yes|no        Install recommended skills (yes/no)
   --no-tui               Non-interactive mode (requires all flags)
   -h, --help             Show this help message
 
 Examples:
   bunx oh-my-opencode-slim install
-  bunx oh-my-opencode-slim install --no-tui --kimi=yes --openai=yes --tmux=no
+  bunx oh-my-opencode-slim install --no-tui --kimi=yes --openai=yes --antigravity=yes --tmux=no --skills=yes
 `);
 }
 

+ 36 - 3
src/cli/install.ts

@@ -1,5 +1,7 @@
 import * as readline from 'node:readline/promises';
 import {
+  addAntigravityPlugin,
+  addGoogleProvider,
   addPluginToOpenCodeConfig,
   detectCurrentConfig,
   disableDefaultAgents,
@@ -110,6 +112,9 @@ function formatConfigSummary(config: InstallConfig): string {
   lines.push(
     `  ${config.hasOpenAI ? SYMBOLS.check : `${DIM}○${RESET}`} OpenAI`,
   );
+  lines.push(
+    `  ${config.hasAntigravity ? SYMBOLS.check : `${DIM}○${RESET}`} Antigravity (Google)`,
+  );
   lines.push(`  ${SYMBOLS.check} Opencode Zen (Big Pickle)`); // Always enabled
   lines.push(
     `  ${config.hasTmux ? SYMBOLS.check : `${DIM}○${RESET}`} Tmux Integration`,
@@ -152,6 +157,7 @@ function argsToConfig(args: InstallArgs): InstallConfig {
   return {
     hasKimi: args.kimi === 'yes',
     hasOpenAI: args.openai === 'yes',
+    hasAntigravity: args.antigravity === 'yes',
     hasOpencodeZen: true, // Always enabled - free models available to all users
     hasTmux: args.tmux === 'yes',
     installSkills: args.skills === 'yes',
@@ -185,7 +191,7 @@ async function runInteractiveMode(
   // TODO: tmux has a bug, disabled for now
   // const tmuxInstalled = await isTmuxInstalled()
   // const totalQuestions = tmuxInstalled ? 3 : 2
-  const totalQuestions = 2;
+  const totalQuestions = 3;
 
   try {
     console.log(`${BOLD}Question 1/${totalQuestions}:${RESET}`);
@@ -204,6 +210,14 @@ async function runInteractiveMode(
     );
     console.log();
 
+    console.log(`${BOLD}Question 3/${totalQuestions}:${RESET}`);
+    const antigravity = await askYesNo(
+      rl,
+      'Enable Antigravity authentication for Google models?',
+      detected.hasAntigravity ? 'yes' : 'no',
+    );
+    console.log();
+
     // TODO: tmux has a bug, disabled for now
     // let tmux: BooleanArg = "no"
     // if (tmuxInstalled) {
@@ -239,6 +253,7 @@ async function runInteractiveMode(
     return {
       hasKimi: kimi === 'yes',
       hasOpenAI: openai === 'yes',
+      hasAntigravity: antigravity === 'yes',
       hasOpencodeZen: true,
       hasTmux: false,
       installSkills: skills === 'yes',
@@ -257,6 +272,7 @@ async function runInstall(config: InstallConfig): Promise<number> {
 
   // Calculate total steps dynamically
   let totalSteps = 4; // Base: check opencode, add plugin, disable default agents, write lite config
+  if (config.hasAntigravity) totalSteps += 2; // antigravity plugin + google provider
   if (config.installSkills) totalSteps += 1; // skills installation
   if (config.installCustomSkills) totalSteps += 1; // custom skills installation
 
@@ -270,6 +286,19 @@ async function runInstall(config: InstallConfig): Promise<number> {
   const pluginResult = await addPluginToOpenCodeConfig();
   if (!handleStepResult(pluginResult, 'Plugin added')) return 1;
 
+  // Add Antigravity support if requested
+  if (config.hasAntigravity) {
+    printStep(step++, totalSteps, 'Adding Antigravity plugin...');
+    const antigravityPluginResult = addAntigravityPlugin();
+    if (!handleStepResult(antigravityPluginResult, 'Antigravity plugin added'))
+      return 1;
+
+    printStep(step++, totalSteps, 'Configuring Google Provider...');
+    const googleProviderResult = addGoogleProvider();
+    if (!handleStepResult(googleProviderResult, 'Google Provider configured'))
+      return 1;
+  }
+
   printStep(step++, totalSteps, 'Disabling OpenCode default agents...');
   const agentResult = disableDefaultAgents();
   if (!handleStepResult(agentResult, 'Default agents disabled')) return 1;
@@ -321,7 +350,7 @@ async function runInstall(config: InstallConfig): Promise<number> {
 
   printAgentModels(config);
 
-  if (!config.hasKimi && !config.hasOpenAI) {
+  if (!config.hasKimi && !config.hasOpenAI && !config.hasAntigravity) {
     printWarning(
       'No providers configured. Zen Big Pickle models will be used as fallback.',
     );
@@ -336,13 +365,17 @@ async function runInstall(config: InstallConfig): Promise<number> {
 
   let nextStep = 1;
 
-  if (config.hasKimi || config.hasOpenAI) {
+  if (config.hasKimi || config.hasOpenAI || config.hasAntigravity) {
     console.log(`  ${nextStep++}. Authenticate with your providers:`);
     console.log(`     ${BLUE}$ opencode auth login${RESET}`);
     if (config.hasKimi) {
       console.log();
       console.log(`     Then select ${BOLD}Kimi For Coding${RESET} provider.`);
     }
+    if (config.hasAntigravity) {
+      console.log();
+      console.log(`     Then select ${BOLD}google${RESET} provider.`);
+    }
     console.log();
   }
 

+ 189 - 1
src/cli/providers.test.ts

@@ -1,11 +1,16 @@
 /// <reference types="bun-types" />
 
 import { describe, expect, test } from 'bun:test';
-import { generateLiteConfig, MODEL_MAPPINGS } from './providers';
+import {
+  generateAntigravityMixedPreset,
+  generateLiteConfig,
+  MODEL_MAPPINGS,
+} from './providers';
 
 describe('providers', () => {
   test('generateLiteConfig generates kimi config when only kimi selected', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: true,
       hasOpenAI: false,
       hasOpencodeZen: false,
@@ -28,6 +33,7 @@ describe('providers', () => {
 
   test('generateLiteConfig generates kimi-openai preset when both selected', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: true,
       hasOpenAI: true,
       hasOpencodeZen: false,
@@ -51,6 +57,7 @@ describe('providers', () => {
 
   test('generateLiteConfig generates openai preset when only openai selected', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: false,
       hasOpenAI: true,
       hasOpencodeZen: false,
@@ -73,6 +80,7 @@ describe('providers', () => {
 
   test('generateLiteConfig generates zen-free preset when no providers selected', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: false,
       hasOpenAI: false,
       hasOpencodeZen: false,
@@ -93,6 +101,7 @@ describe('providers', () => {
 
   test('generateLiteConfig uses zen-free big-pickle models', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: false,
       hasOpenAI: false,
       hasOpencodeZen: true,
@@ -112,6 +121,7 @@ describe('providers', () => {
 
   test('generateLiteConfig enables tmux when requested', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: false,
       hasOpenAI: false,
       hasOpencodeZen: false,
@@ -126,6 +136,7 @@ describe('providers', () => {
 
   test('generateLiteConfig includes default skills', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: true,
       hasOpenAI: false,
       hasOpencodeZen: false,
@@ -147,6 +158,7 @@ describe('providers', () => {
 
   test('generateLiteConfig includes mcps field', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: true,
       hasOpenAI: false,
       hasOpencodeZen: false,
@@ -164,6 +176,7 @@ describe('providers', () => {
 
   test('generateLiteConfig zen-free includes correct mcps', () => {
     const config = generateLiteConfig({
+      hasAntigravity: false,
       hasKimi: false,
       hasOpenAI: false,
       hasOpencodeZen: false,
@@ -179,4 +192,179 @@ describe('providers', () => {
     expect(agents.librarian.mcps).toContain('grep_app');
     expect(agents.designer.mcps).toEqual([]);
   });
+
+  // Antigravity tests
+  describe('Antigravity presets', () => {
+    test('generateLiteConfig generates antigravity-mixed-both preset when all providers selected', () => {
+      const config = generateLiteConfig({
+        hasKimi: true,
+        hasOpenAI: true,
+        hasAntigravity: true,
+        hasOpencodeZen: false,
+        hasTmux: false,
+        installSkills: false,
+        installCustomSkills: false,
+      });
+
+      expect(config.preset).toBe('antigravity-mixed-both');
+      const agents = (config.presets as any)['antigravity-mixed-both'];
+      expect(agents).toBeDefined();
+
+      // Orchestrator should use Kimi
+      expect(agents.orchestrator.model).toBe('kimi-for-coding/k2p5');
+
+      // Oracle should use OpenAI
+      expect(agents.oracle.model).toBe('openai/gpt-5.2-codex');
+      expect(agents.oracle.variant).toBe('high');
+
+      // Others should use Antigravity Flash
+      expect(agents.explorer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.explorer.variant).toBe('low');
+      expect(agents.librarian.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.librarian.variant).toBe('low');
+      expect(agents.designer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.designer.variant).toBe('medium');
+      expect(agents.fixer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.fixer.variant).toBe('low');
+    });
+
+    test('generateLiteConfig generates antigravity-mixed-kimi preset when Kimi + Antigravity', () => {
+      const config = generateLiteConfig({
+        hasKimi: true,
+        hasOpenAI: false,
+        hasAntigravity: true,
+        hasOpencodeZen: false,
+        hasTmux: false,
+        installSkills: false,
+        installCustomSkills: false,
+      });
+
+      expect(config.preset).toBe('antigravity-mixed-kimi');
+      const agents = (config.presets as any)['antigravity-mixed-kimi'];
+      expect(agents).toBeDefined();
+
+      // Orchestrator should use Kimi
+      expect(agents.orchestrator.model).toBe('kimi-for-coding/k2p5');
+
+      // Oracle should use Antigravity (no OpenAI)
+      expect(agents.oracle.model).toBe('google/antigravity-gemini-3-pro');
+
+      // Others should use Antigravity Flash
+      expect(agents.explorer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.librarian.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.designer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.fixer.model).toBe('google/antigravity-gemini-3-flash');
+    });
+
+    test('generateLiteConfig generates antigravity-mixed-openai preset when OpenAI + Antigravity', () => {
+      const config = generateLiteConfig({
+        hasKimi: false,
+        hasOpenAI: true,
+        hasAntigravity: true,
+        hasOpencodeZen: false,
+        hasTmux: false,
+        installSkills: false,
+        installCustomSkills: false,
+      });
+
+      expect(config.preset).toBe('antigravity-mixed-openai');
+      const agents = (config.presets as any)['antigravity-mixed-openai'];
+      expect(agents).toBeDefined();
+
+      // Orchestrator should use Antigravity (no Kimi)
+      expect(agents.orchestrator.model).toBe(
+        'google/antigravity-gemini-3-flash',
+      );
+
+      // Oracle should use OpenAI
+      expect(agents.oracle.model).toBe('openai/gpt-5.2-codex');
+      expect(agents.oracle.variant).toBe('high');
+
+      // Others should use Antigravity Flash
+      expect(agents.explorer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.librarian.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.designer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.fixer.model).toBe('google/antigravity-gemini-3-flash');
+    });
+
+    test('generateLiteConfig generates pure antigravity preset when only Antigravity', () => {
+      const config = generateLiteConfig({
+        hasKimi: false,
+        hasOpenAI: false,
+        hasAntigravity: true,
+        hasOpencodeZen: false,
+        hasTmux: false,
+        installSkills: false,
+        installCustomSkills: false,
+      });
+
+      expect(config.preset).toBe('antigravity');
+      const agents = (config.presets as any).antigravity;
+      expect(agents).toBeDefined();
+
+      // All agents should use Antigravity
+      expect(agents.orchestrator.model).toBe(
+        'google/antigravity-gemini-3-flash',
+      );
+      expect(agents.oracle.model).toBe('google/antigravity-gemini-3-pro');
+      expect(agents.explorer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.librarian.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.designer.model).toBe('google/antigravity-gemini-3-flash');
+      expect(agents.fixer.model).toBe('google/antigravity-gemini-3-flash');
+    });
+
+    test('generateAntigravityMixedPreset respects Kimi for orchestrator', () => {
+      const preset = generateAntigravityMixedPreset({
+        hasKimi: true,
+        hasOpenAI: false,
+        hasAntigravity: true,
+        hasOpencodeZen: false,
+        hasTmux: false,
+        installSkills: false,
+        installCustomSkills: false,
+      });
+
+      expect((preset.orchestrator as any).model).toBe('kimi-for-coding/k2p5');
+    });
+
+    test('generateAntigravityMixedPreset respects OpenAI for oracle', () => {
+      const preset = generateAntigravityMixedPreset({
+        hasKimi: false,
+        hasOpenAI: true,
+        hasAntigravity: true,
+        hasOpencodeZen: false,
+        hasTmux: false,
+        installSkills: false,
+        installCustomSkills: false,
+      });
+
+      expect((preset.oracle as any).model).toBe('openai/gpt-5.2-codex');
+      expect((preset.oracle as any).variant).toBe('high');
+    });
+
+    test('generateAntigravityMixedPreset always uses Antigravity for explorer/librarian/designer/fixer', () => {
+      const preset = generateAntigravityMixedPreset({
+        hasKimi: true,
+        hasOpenAI: true,
+        hasAntigravity: true,
+        hasOpencodeZen: false,
+        hasTmux: false,
+        installSkills: false,
+        installCustomSkills: false,
+      });
+
+      expect((preset.explorer as any).model).toBe(
+        'google/antigravity-gemini-3-flash',
+      );
+      expect((preset.librarian as any).model).toBe(
+        'google/antigravity-gemini-3-flash',
+      );
+      expect((preset.designer as any).model).toBe(
+        'google/antigravity-gemini-3-flash',
+      );
+      expect((preset.fixer as any).model).toBe(
+        'google/antigravity-gemini-3-flash',
+      );
+    });
+  });
 });

+ 143 - 5
src/cli/providers.ts

@@ -20,6 +20,23 @@ export const MODEL_MAPPINGS = {
     designer: { model: 'openai/gpt-5.1-codex-mini', variant: 'medium' },
     fixer: { model: 'openai/gpt-5.1-codex-mini', variant: 'low' },
   },
+  antigravity: {
+    orchestrator: { model: 'google/antigravity-gemini-3-flash' },
+    oracle: { model: 'google/antigravity-gemini-3-pro' },
+    librarian: {
+      model: 'google/antigravity-gemini-3-flash',
+      variant: 'low',
+    },
+    explorer: {
+      model: 'google/antigravity-gemini-3-flash',
+      variant: 'low',
+    },
+    designer: {
+      model: 'google/antigravity-gemini-3-flash',
+      variant: 'medium',
+    },
+    fixer: { model: 'google/antigravity-gemini-3-flash', variant: 'low' },
+  },
   'zen-free': {
     orchestrator: { model: 'opencode/big-pickle' },
     oracle: { model: 'opencode/big-pickle', variant: 'high' },
@@ -30,6 +47,91 @@ export const MODEL_MAPPINGS = {
   },
 } as const;
 
+export function generateAntigravityMixedPreset(
+  config: InstallConfig,
+  existingPreset?: Record<string, unknown>,
+): Record<string, unknown> {
+  const result: Record<string, unknown> = existingPreset
+    ? { ...existingPreset }
+    : {};
+
+  const createAgentConfig = (
+    agentName: string,
+    modelInfo: { model: string; variant?: string },
+  ) => {
+    const isOrchestrator = agentName === 'orchestrator';
+
+    // Skills: orchestrator gets "*", others get recommended skills for their role
+    const skills = isOrchestrator
+      ? ['*']
+      : RECOMMENDED_SKILLS.filter(
+          (s) =>
+            s.allowedAgents.includes('*') ||
+            s.allowedAgents.includes(agentName),
+        ).map((s) => s.skillName);
+
+    // Special case for designer and agent-browser skill
+    if (agentName === 'designer' && !skills.includes('agent-browser')) {
+      skills.push('agent-browser');
+    }
+
+    return {
+      model: modelInfo.model,
+      variant: modelInfo.variant,
+      skills,
+      mcps:
+        DEFAULT_AGENT_MCPS[agentName as keyof typeof DEFAULT_AGENT_MCPS] ?? [],
+    };
+  };
+
+  const antigravityFlash = {
+    model: 'google/antigravity-gemini-3-flash',
+  };
+
+  // Orchestrator: Kimi if hasKimi, else keep existing if exists, else antigravity
+  if (config.hasKimi) {
+    result.orchestrator = createAgentConfig(
+      'orchestrator',
+      MODEL_MAPPINGS.kimi.orchestrator,
+    );
+  } else if (!result.orchestrator) {
+    result.orchestrator = createAgentConfig(
+      'orchestrator',
+      MODEL_MAPPINGS.antigravity.orchestrator,
+    );
+  }
+
+  // Oracle: GPT if hasOpenAI, else keep existing if exists, else antigravity
+  if (config.hasOpenAI) {
+    result.oracle = createAgentConfig('oracle', MODEL_MAPPINGS.openai.oracle);
+  } else if (!result.oracle) {
+    result.oracle = createAgentConfig(
+      'oracle',
+      MODEL_MAPPINGS.antigravity.oracle,
+    );
+  }
+
+  // Explorer, Librarian, Designer, Fixer: Always use Antigravity Flash
+  result.explorer = createAgentConfig('explorer', {
+    ...antigravityFlash,
+    variant: 'low',
+  });
+  result.librarian = createAgentConfig('librarian', {
+    ...antigravityFlash,
+    variant: 'low',
+  });
+  result.designer = createAgentConfig('designer', {
+    ...antigravityFlash,
+    variant: 'medium',
+  });
+  result.fixer = createAgentConfig('fixer', {
+    ...antigravityFlash,
+    variant: 'low',
+  });
+
+  return result;
+}
+
 export function generateLiteConfig(
   installConfig: InstallConfig,
 ): Record<string, unknown> {
@@ -39,9 +141,33 @@ export function generateLiteConfig(
   };
 
   // Determine active preset name
-  let activePreset: 'kimi' | 'openai' | 'zen-free' = 'zen-free';
-  if (installConfig.hasKimi) activePreset = 'kimi';
-  else if (installConfig.hasOpenAI) activePreset = 'openai';
+  let activePreset:
+    | 'kimi'
+    | 'openai'
+    | 'antigravity'
+    | 'antigravity-mixed-both'
+    | 'antigravity-mixed-kimi'
+    | 'antigravity-mixed-openai'
+    | 'zen-free' = 'zen-free';
+
+  // Antigravity mixed presets have priority
+  if (
+    installConfig.hasAntigravity &&
+    installConfig.hasKimi &&
+    installConfig.hasOpenAI
+  ) {
+    activePreset = 'antigravity-mixed-both';
+  } else if (installConfig.hasAntigravity && installConfig.hasKimi) {
+    activePreset = 'antigravity-mixed-kimi';
+  } else if (installConfig.hasAntigravity && installConfig.hasOpenAI) {
+    activePreset = 'antigravity-mixed-openai';
+  } else if (installConfig.hasAntigravity) {
+    activePreset = 'antigravity';
+  } else if (installConfig.hasKimi) {
+    activePreset = 'kimi';
+  } else if (installConfig.hasOpenAI) {
+    activePreset = 'openai';
+  }
 
   config.preset = activePreset;
 
@@ -94,8 +220,20 @@ export function generateLiteConfig(
     );
   };
 
-  (config.presets as Record<string, unknown>)[activePreset] =
-    buildPreset(activePreset);
+  // Build preset based on type
+  if (
+    activePreset === 'antigravity-mixed-both' ||
+    activePreset === 'antigravity-mixed-kimi' ||
+    activePreset === 'antigravity-mixed-openai'
+  ) {
+    // Use dedicated mixed preset generator
+    (config.presets as Record<string, unknown>)[activePreset] =
+      generateAntigravityMixedPreset(installConfig);
+  } else {
+    // Use standard buildPreset for pure presets
+    (config.presets as Record<string, unknown>)[activePreset] =
+      buildPreset(activePreset);
+  }
 
   if (installConfig.hasTmux) {
     config.tmux = {

+ 3 - 0
src/cli/types.ts

@@ -4,6 +4,7 @@ export interface InstallArgs {
   tui: boolean;
   kimi?: BooleanArg;
   openai?: BooleanArg;
+  antigravity?: BooleanArg;
   tmux?: BooleanArg;
   skills?: BooleanArg;
 }
@@ -18,6 +19,7 @@ export interface OpenCodeConfig {
 export interface InstallConfig {
   hasKimi: boolean;
   hasOpenAI: boolean;
+  hasAntigravity: boolean;
   hasOpencodeZen: boolean;
   hasTmux: boolean;
   installSkills: boolean;
@@ -34,6 +36,7 @@ export interface DetectedConfig {
   isInstalled: boolean;
   hasKimi: boolean;
   hasOpenAI: boolean;
+  hasAntigravity: boolean;
   hasOpencodeZen: boolean;
   hasTmux: boolean;
 }