diff --git a/.gitignore b/.gitignore
index d2a5cf8d..30c4bd74 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,6 @@ docs/
/.ripgreprc
/.zprofile
/.zshrc
+
+# Local runtime state from memory/sidecar processes (not source)
+/data/
diff --git a/README.md b/README.md
index fec233bd..be457922 100644
--- a/README.md
+++ b/README.md
@@ -115,10 +115,19 @@ When you're happy with the result, merge the branch back to main from the sideba
- **macOS** — `.dmg` (universal)
- **Linux** — `.AppImage` or `.deb`
-2. **Install at least one AI coding CLI:** [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Codex CLI](https://github.com/openai/codex), [Gemini CLI](https://github.com/google-gemini/gemini-cli), or [Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli)
+2. **Install at least one AI coding CLI:** [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Codex CLI](https://github.com/openai/codex), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Antigravity CLI](https://antigravity.google/), or [Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli)
3. **Open Parallel Code**, point it at a git repo, and start dispatching tasks.
+
+Antigravity CLI: run natively, not in Docker isolation
+
+Antigravity (`agy`) signs in interactively and caches credentials in your OS keyring (Keychain/libsecret). The keyring cannot be reached from inside a Linux container — it needs a secret-service daemon the agent container doesn't run — and `agy` has no API-key fallback, so **Docker-isolated Antigravity tasks cannot authenticate. Run Antigravity as a native (non-Docker) task.**
+
+The bundled image still ships the `agy` binary, and `~/.gemini/antigravity-cli` (settings/plugins) is shared when "Share agent auth" is enabled, so Docker support is forward-compatible if a file-based or API-key auth path appears later.
+
+
+
Build from source
diff --git a/docker/Dockerfile b/docker/Dockerfile
index a717cbb8..f775de19 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -52,6 +52,14 @@ RUN ln -sf "$(command -v fdfind)" /usr/local/bin/fd 2>/dev/null || true
# AI agent CLIs — must be present so Docker-mode tasks can execute them
RUN npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai
+# Antigravity CLI (agy) — distributed as a Go binary via the official installer
+# (not on npm). The installer's `--dir` flag drops the binary straight into a
+# system path on PATH, so the non-root `agent` user that runs containers resolves
+# it. A failed fetch makes the build step fail, surfacing the break at image build
+# time rather than at task launch.
+RUN curl -fsSL https://antigravity.google/cli/install.sh | bash -s -- --dir /usr/local/bin \
+ && agy --version
+
# Default git config so commits work out of the box inside containers
RUN git config --system init.defaultBranch main \
&& git config --system advice.detachedHead false
diff --git a/electron/ipc/agents.ts b/electron/ipc/agents.ts
index 8f17147d..44041a7b 100644
--- a/electron/ipc/agents.ts
+++ b/electron/ipc/agents.ts
@@ -66,6 +66,17 @@ const DEFAULT_AGENTS: AgentDef[] = [
// settle before sending, without being so long that the user notices the wait.
prompt_ready_delay_ms: 1_000,
},
+ {
+ id: 'antigravity',
+ name: 'Antigravity CLI',
+ command: 'agy',
+ args: [],
+ resume_args: ['-c'],
+ skip_permissions_args: ['--dangerously-skip-permissions'],
+ description: "Google's Antigravity CLI agent (successor to Gemini CLI)",
+ // Antigravity paints a TUI that needs a beat to settle before auto-send.
+ prompt_ready_delay_ms: 1_000,
+ },
];
async function isCommandAvailable(command: string): Promise {
diff --git a/electron/ipc/pty.test.ts b/electron/ipc/pty.test.ts
index 696fc32c..5655aa4f 100644
--- a/electron/ipc/pty.test.ts
+++ b/electron/ipc/pty.test.ts
@@ -352,6 +352,7 @@ describe('spawnAgent docker mode', () => {
['gemini', '.gemini'],
['opencode', '.config/opencode'],
['copilot', '.config/github-copilot'],
+ ['agy', '.gemini/antigravity-cli'],
])(
'%s bind-mounts a user-owned host directory when shareDockerAgentAuth is enabled',
(command, relDir) => {
diff --git a/electron/ipc/pty.ts b/electron/ipc/pty.ts
index 76423e12..5cf49440 100644
--- a/electron/ipc/pty.ts
+++ b/electron/ipc/pty.ts
@@ -710,6 +710,7 @@ const AGENT_CONFIG_DIRS: Record = {
gemini: ['.gemini'],
opencode: ['.config/opencode'],
copilot: ['.config/github-copilot'],
+ agy: ['.gemini/antigravity-cli'],
};
// Config files (not directories) each agent CLI uses for auth, relative to HOME.
diff --git a/electron/mcp/agent-args.test.ts b/electron/mcp/agent-args.test.ts
index c8e3a65d..d551a077 100644
--- a/electron/mcp/agent-args.test.ts
+++ b/electron/mcp/agent-args.test.ts
@@ -1,6 +1,11 @@
import { describe, expect, it } from 'vitest';
-import { buildCodexMcpConfigOverride, buildMcpLaunchArgs, isCodexCommand } from './agent-args.js';
+import {
+ buildCodexMcpConfigOverride,
+ buildMcpLaunchArgs,
+ isAntigravityCommand,
+ isCodexCommand,
+} from './agent-args.js';
const config = {
mcpServers: {
@@ -50,4 +55,14 @@ describe('MCP agent launch args', () => {
'/tmp/config.json',
]);
});
+
+ it('detects antigravity commands by executable name', () => {
+ expect(isAntigravityCommand('agy')).toBe(true);
+ expect(isAntigravityCommand('/home/agent/.local/bin/agy')).toBe(true);
+ expect(isAntigravityCommand('claude')).toBe(false);
+ });
+
+ it('emits no --mcp-config for Antigravity', () => {
+ expect(buildMcpLaunchArgs('agy', '/tmp/config.json', config)).toEqual([]);
+ });
});
diff --git a/electron/mcp/agent-args.ts b/electron/mcp/agent-args.ts
index 2f6153fa..195551f4 100644
--- a/electron/mcp/agent-args.ts
+++ b/electron/mcp/agent-args.ts
@@ -14,6 +14,10 @@ export function isCodexCommand(command: string): boolean {
return command.split('/').pop()?.includes('codex') === true;
}
+export function isAntigravityCommand(command: string): boolean {
+ return command.split('/').pop() === 'agy';
+}
+
function tomlString(value: string): string {
return JSON.stringify(value);
}
@@ -41,5 +45,9 @@ export function buildMcpLaunchArgs(
if (isCodexCommand(command)) {
return ['--config', buildCodexMcpConfigOverride(config)];
}
+ // Antigravity (agy) has no `--mcp-config` flag; emit nothing so launch is not broken.
+ if (isAntigravityCommand(command)) {
+ return [];
+ }
return configPath ? ['--mcp-config', configPath] : [];
}
diff --git a/openspec/changes/add-antigravity-agent/.openspec.yaml b/openspec/changes/add-antigravity-agent/.openspec.yaml
new file mode 100644
index 00000000..1194417e
--- /dev/null
+++ b/openspec/changes/add-antigravity-agent/.openspec.yaml
@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-05-29
diff --git a/openspec/changes/add-antigravity-agent/design.md b/openspec/changes/add-antigravity-agent/design.md
new file mode 100644
index 00000000..ebbb07db
--- /dev/null
+++ b/openspec/changes/add-antigravity-agent/design.md
@@ -0,0 +1,169 @@
+## Context
+
+parallel-code launches coding-agent CLIs in node-pty terminals, one per git
+worktree. The agent catalog is a static `DEFAULT_AGENTS` array in
+`electron/ipc/agents.ts`; each entry is an `AgentDef` (`{ id, name, command,
+args, resume_args, skip_permissions_args, description, prompt_ready_delay_ms?,
+mcp_config_flag? }`). `AgentDef` is **duplicated** — the canonical copy lives in
+`src/ipc/types.ts` and a structurally identical copy in `electron/ipc/agents.ts`.
+
+At launch the agent is started **interactively** with `args` (the initial prompt
+is typed into the TUI afterward via bracketed paste, not passed as a CLI argument).
+`buildTaskAgentArgs` appends `resume_args` on resume and `skip_permissions_args`
+when the task opts into skip-permissions. Availability is probed with `which
+` (TTL-cached). The renderer's `AgentSelector` renders each agent as a
+text button keyed off `agent.id` with **no per-agent icon or color map**, so a new
+agent needs no front-end asset.
+
+The Electron main process resolves the user's full login+interactive shell PATH
+(`zsh/bash -ilc`, `electron/main.ts:52`), so binaries on `~/.local/bin` are
+discoverable as long as the user's shell profile adds that directory.
+
+For Docker-isolated tasks, `AGENT_CONFIG_DIRS` (`electron/ipc/pty.ts:707`) maps a
+command basename to host config dirs that are bind-mounted into the container when
+"Share agent auth" is enabled. The bundled `docker/Dockerfile` installs the other
+agents via `npm install -g`.
+
+Ground truth for `agy` (verified against the installed binary, v1.0.3 — `agy
+--help`):
+
+- Interactive launch: `agy`
+- Resume most recent conversation: `-c` / `--continue`
+- Skip permissions: `--dangerously-skip-permissions`
+- Sandbox (`nsjail`/`sandbox-exec`) is **opt-in** via `--sandbox`; off by default.
+- Non-interactive print mode: `-p` / `--print` (not used by this app).
+- Config/app-data dir is `~/.gemini/antigravity-cli` (settings.json, mcp_config.json,
+ plugins/, conversations/) — verified against the installed binary; it is **not**
+ `~/.config/antigravity`. Interactive auth is OAuth cached in the OS keyring
+ (Keychain/libsecret); `agy` has **no** API-key environment fallback (the
+ `ANTIGRAVITY_API_KEY` variable is not consumed — confirmed behaviorally).
+
+## Goals / Non-Goals
+
+**Goals:**
+
+- Add `agy` as a built-in default agent with correct launch/resume/skip-permission
+ args, fully working on native (macOS/Linux) tasks.
+- Ship the Docker bits that are additive and forward-compatible (bundle the `agy`
+ binary, mount its config dir), while documenting clearly — in user-facing docs and
+ the PR — that Docker-isolated Antigravity cannot authenticate and must be run
+ natively.
+- Keep Gemini CLI fully intact.
+- Make the integration data-driven — no new IPC, no per-id special casing.
+
+**Non-Goals:**
+
+- Removing or deprecating Gemini CLI (separate future change).
+- Wiring `agy`'s OAuth keyring credentials into Docker containers (not file-mountable).
+- Supporting `agy --sandbox` inside Docker (nested sandbox; left off by default).
+- A custom agent-branding/icon system.
+
+## Decisions
+
+**1. Launch interactively with `command: "agy"`, `args: []`.**
+Matches every other agent: the app types the prompt into the live TUI rather than
+passing `-p`. `-p`/`--print` is one-shot and prints-then-exits, which would defeat
+the interactive session model. Rejected `-i`/`--prompt-interactive` because the app
+already delivers the prompt via terminal input after a readiness delay.
+
+**2. `resume_args: ["-c"]`, `skip_permissions_args: ["--dangerously-skip-permissions"]`.**
+Both verified against the installed binary. `--dangerously-skip-permissions` is
+real (it coincidentally matches Claude's flag); the Gemini `--yolo` flag does **not**
+carry over.
+
+**3. `prompt_ready_delay_ms` set to a modest stability delay (~1000 ms), mirroring
+Copilot.** `agy`'s first interactive run shows onboarding (Google sign-in, theme,
+file-permission prompts); steady-state runs still paint a TUI that needs a beat to
+settle before auto-send. This only tunes the readiness recheck; it does not bypass
+first-run OAuth, which is interactive regardless (same caveat as other agents).
+
+**4. Omit `mcp_config_flag` AND exclude `agy` from the `--mcp-config` paths.** `agy`
+has no `--mcp-config` flag (MCP is configured via plugins/config), so passing it would
+break launch. Two code paths can emit it and both must exclude `agy`:
+
+- `legacyMcpConfigArgs` (`src/lib/agent-args.ts`) injects `--mcp-config ` for any
+ non-Codex command when a task carries a legacy `mcpConfigPath` and no `mcpLaunchArgs`
+ — reachable only by older persisted tasks.
+- `buildMcpLaunchArgs` (`electron/mcp/agent-args.ts`, imported by `coordinator.ts`) is
+ the modern per-agent builder used by coordinator/MCP tasks.
+ Excluding `agy` (the same way Codex is excluded via `isCodexCommand`) is the safe
+ default: it guarantees `agy` is never handed an unsupported flag regardless of whether
+ a given task takes the legacy or modern path. Leaving `mcp_config_flag` unset keeps it
+ off the flag-driven path as well.
+
+**5. Mount the config dir; Docker auth is unsupported (native only).** Add
+`agy: ['.gemini/antigravity-cli']` to `AGENT_CONFIG_DIRS` so settings/plugins are
+shared. Auth, however, cannot work in Docker: login credentials live in the host OS
+keyring (Keychain/libsecret), which needs a secret-service daemon the agent container
+does not run, and `agy` has no API-key environment fallback (the `ANTIGRAVITY_API_KEY`
+claim was unverified and is false — behaviorally `agy` still enters OAuth with it set).
+So Antigravity is documented as a native-only agent. The mount + bundled binary are
+kept because they are additive and forward-compatible if a file-based or API-key auth
+path appears.
+
+**6. Install `agy` in the Docker image via the official installer, not npm.** `agy`
+ships as a Go binary from `https://antigravity.google/cli/install.sh`, so the existing
+`npm install -g` line cannot add it. The installer supports `-d|--dir`, so the step
+installs straight to a system PATH dir:
+`RUN curl -fsSL … | bash -s -- --dir /usr/local/bin && agy --version`. Verified the
+script runs non-interactively when piped and `mkdir -p`s its target. The trailing
+`agy --version` makes the build assert the install at image-build time.
+
+## Risks / Trade-offs
+
+- **Docker auth is impossible, not just limited** → `agy` login is keyring-only OAuth,
+ the container has no secret-service daemon, and there is no API-key fallback, so an
+ in-container `agy` cannot authenticate at all. Mitigation: native tasks work fully;
+ docs and PR state plainly that Antigravity is native-only and Docker isolation is
+ unsupported for it. The config-dir mount + bundled binary are kept as additive,
+ forward-compatible scaffolding, not a working auth path.
+- **PATH discovery** → If the user never ran the installer's PATH line, `~/.local/bin`
+ is absent from the resolved shell PATH and `agy` shows "(not installed)". Mitigation:
+ this is the same behavior as any un-PATHed agent; the availability probe degrades
+ gracefully. Document running `agy install`.
+- **`--mcp-config` injected by either MCP path** → `legacyMcpConfigArgs` (old tasks)
+ or `buildMcpLaunchArgs` (coordinator tasks) could hand `agy` an unknown flag and
+ break launch. Mitigation: exclude `agy` from both, the way Codex is excluded via
+ `isCodexCommand` — chosen as the safe default rather than relying on the legacy path
+ being unreachable. **Functional consequence (accepted):** `buildMcpLaunchArgs`
+ returning `[]` for `agy` means Antigravity tasks receive no parallel-code MCP
+ coordinator wiring — no in-`agy` subagent spawning. `agy` configures MCP via
+ plugins/config rather than a CLI flag, so coordinator integration is a separate
+ follow-up if desired; this change intentionally ships without it.
+- **Installer-script drift in Docker builds** → Piping a remote installer into the
+ image is less reproducible and could break builds if the URL/format changes.
+ Mitigation: pin behavior to the documented installer; treat a failed fetch as a
+ build error so it is caught at image-build time, not at task launch.
+- **Duplicate `AgentDef` definitions drift** → The entry and the type live in two
+ files. Mitigation: update both `electron/ipc/agents.ts` and `src/ipc/types.ts` in
+ lockstep; TypeScript strict build catches shape mismatches.
+
+## Migration Plan
+
+Additive and behind agent availability detection — no data migration. `agy` appears
+in the selector only when the binary is on PATH; existing Gemini tasks are untouched.
+Rollback is removing the `DEFAULT_AGENTS` entry (and the Dockerfile/ config-dir
+lines); no persisted state depends on it.
+
+## Resolved Decisions
+
+- **Antigravity is native-only; Docker isolation is unsupported for it.** The earlier
+ `ANTIGRAVITY_API_KEY` Docker auth path was an unverified claim and is false. We keep
+ the additive Docker scaffolding (bundled `agy` binary, mounted
+ `~/.gemini/antigravity-cli` config dir) but document Antigravity as native-only.
+ Decided with the user after the Codex review surfaced the wrong config path and the
+ non-functional env var.
+- **`agy` is excluded from both `--mcp-config` paths** (`legacyMcpConfigArgs` and
+ `buildMcpLaunchArgs`), as the safe default — no dependence on the legacy path being
+ unreachable.
+
+## Open Questions
+
+- In-container PATH is resolved: the installer's `--dir` flag installs `agy` to
+ `/usr/local/bin` (on PATH for the non-root `agent` user); the build-step
+ `agy --version` verifies it. A full `docker build` is the only step needing a Docker
+ daemon.
+- **Untested:** whether `agy` can read a file-based credential it shares with the
+ Gemini CLI (`~/.gemini/gemini-credentials.json` / `google_accounts.json` sit in the
+ parent dir). If it does, that could become a real Docker auth path later. Not claimed
+ or relied on here.
diff --git a/openspec/changes/add-antigravity-agent/proposal.md b/openspec/changes/add-antigravity-agent/proposal.md
new file mode 100644
index 00000000..f993ae28
--- /dev/null
+++ b/openspec/changes/add-antigravity-agent/proposal.md
@@ -0,0 +1,50 @@
+## Why
+
+Google is transitioning the Gemini CLI to the new **Antigravity CLI** (`agy`). On
+**June 18, 2026** Gemini CLI stops serving Google AI Pro/Ultra and free Code Assist
+users; it remains only on paid/enterprise API keys. Users who pick the "Gemini CLI"
+agent today will increasingly hit a dead end, while `agy` becomes the supported
+Google terminal agent. parallel-code should offer Antigravity CLI as a first-class
+agent so users have a working migration path — without yet removing Gemini CLI,
+which paid/enterprise users still rely on.
+
+## What Changes
+
+- Add **Antigravity CLI** (`agy`) as a built-in default agent alongside Claude Code,
+ Codex, Gemini CLI, OpenCode, and Copilot.
+- Register its launch contract: interactive launch (`agy`), resume (`-c`), and
+ skip-permissions (`--dangerously-skip-permissions`).
+- Add its config directory (`~/.gemini/antigravity-cli`) to the Docker shared-auth
+ mount map for settings/plugins, and document that Antigravity is **native-only**:
+ its login credentials live in the OS keyring (no secret-service daemon in the
+ container) and `agy` has no API-key env fallback, so Docker-isolated Antigravity
+ cannot authenticate.
+- Install `agy` in the bundled Docker agent image (via the official installer script,
+ not npm) so the binary is present and the integration is forward-compatible.
+- Keep Gemini CLI unchanged. **No removal, no breaking change.**
+
+## Capabilities
+
+### New Capabilities
+
+- `agent-cli-registry`: The set of coding-agent CLIs parallel-code can launch, and the
+ per-agent contract (command, launch/resume/skip-permission arguments, availability
+ detection, config-directory auth mounting for Docker isolation) that governs how each
+ agent is started, resumed, and authenticated.
+
+### Modified Capabilities
+
+
+
+## Impact
+
+- **Code:** `electron/ipc/agents.ts` (`DEFAULT_AGENTS`), `src/ipc/types.ts` +
+ `electron/ipc/agents.ts` (`AgentDef` — duplicated, both updated),
+ `electron/ipc/pty.ts` (`AGENT_CONFIG_DIRS`), `docker/Dockerfile` (install `agy`).
+- **No new IPC channels or payload-type changes** — Antigravity reuses the existing
+ data-driven `AgentDef` plumbing; the selector renders it from the agent list with no
+ per-id branding.
+- **Dependencies:** the Docker image gains the `agy` binary fetched from
+ `https://antigravity.google/cli/install.sh`.
+- **Tests:** agent-registry and persistence tests that enumerate agents may need the
+ new entry accounted for.
diff --git a/openspec/changes/add-antigravity-agent/specs/agent-cli-registry/spec.md b/openspec/changes/add-antigravity-agent/specs/agent-cli-registry/spec.md
new file mode 100644
index 00000000..d3c95d7c
--- /dev/null
+++ b/openspec/changes/add-antigravity-agent/specs/agent-cli-registry/spec.md
@@ -0,0 +1,78 @@
+## ADDED Requirements
+
+### Requirement: Antigravity CLI is an available built-in agent
+
+The application SHALL offer Antigravity CLI as a built-in default agent, identified
+by the command `agy`, alongside the existing Claude Code, Codex, Gemini CLI,
+OpenCode, and Copilot agents. Adding Antigravity SHALL NOT remove or alter the
+Gemini CLI agent.
+
+#### Scenario: Antigravity appears when its binary is installed
+
+- **WHEN** the application lists available agents and `agy` is resolvable on the
+ user's PATH
+- **THEN** an agent named "Antigravity CLI" is presented as available for selection
+
+#### Scenario: Antigravity is shown unavailable when its binary is missing
+
+- **WHEN** the application lists available agents and `agy` is not resolvable on the
+ user's PATH
+- **THEN** the Antigravity CLI agent is marked not installed and cannot be launched
+
+#### Scenario: Gemini CLI remains offered
+
+- **WHEN** the application lists available agents
+- **THEN** the Gemini CLI agent is still present and unchanged
+
+### Requirement: Antigravity launch, resume, and skip-permission arguments
+
+The application SHALL launch the Antigravity CLI interactively with no extra
+arguments, SHALL resume the most recent conversation using `-c` when a task is
+resumed, and SHALL pass `--dangerously-skip-permissions` only when the task opts
+into skipping permission prompts.
+
+#### Scenario: Fresh interactive launch
+
+- **WHEN** a new task starts with the Antigravity agent and skip-permissions is off
+- **THEN** the CLI is started as `agy` with no resume or skip-permission arguments
+
+#### Scenario: Resuming a previous session
+
+- **WHEN** a task using the Antigravity agent is resumed
+- **THEN** the CLI is started with its resume argument `-c`
+
+#### Scenario: Launch with permissions skipped
+
+- **WHEN** a task using the Antigravity agent is started with skip-permissions enabled
+- **THEN** `--dangerously-skip-permissions` is included in the launch arguments
+
+### Requirement: Antigravity config sharing for isolated tasks
+
+For Docker-isolated tasks, the application SHALL treat `~/.gemini/antigravity-cli` as
+the Antigravity config directory eligible for the shared-auth mount. The application
+SHALL NOT claim a working Docker authentication path for Antigravity: its login
+credentials live in the host OS keyring, which is not reachable from the container,
+and `agy` provides no API-key environment fallback, so Antigravity is supported only
+as a native (non-Docker) task.
+
+#### Scenario: Config directory is shared into the container
+
+- **WHEN** a Docker-isolated Antigravity task runs with shared agent auth enabled
+- **THEN** the host `~/.gemini/antigravity-cli` directory is bind-mounted into the
+ container's home so settings and plugins are available to the in-container agent
+
+#### Scenario: Docker isolation does not provide authentication
+
+- **WHEN** a Docker-isolated Antigravity task is launched without host keyring access
+- **THEN** the agent cannot authenticate inside the container, and the supported path
+ is to run the Antigravity task natively instead
+
+### Requirement: Antigravity is runnable in the bundled Docker image
+
+The bundled Docker agent image SHALL include the `agy` binary on its PATH so that
+Docker-isolated tasks can launch the Antigravity agent.
+
+#### Scenario: agy is present in the image
+
+- **WHEN** a Docker-isolated task selects the Antigravity agent using the bundled image
+- **THEN** `agy` resolves on the container PATH and the agent process starts
diff --git a/openspec/changes/add-antigravity-agent/tasks.md b/openspec/changes/add-antigravity-agent/tasks.md
new file mode 100644
index 00000000..ae4ff2af
--- /dev/null
+++ b/openspec/changes/add-antigravity-agent/tasks.md
@@ -0,0 +1,31 @@
+## 1. Register the agent
+
+- [x] 1.1 Add an `antigravity` entry to `DEFAULT_AGENTS` in `electron/ipc/agents.ts`: `id: 'antigravity'`, `name: 'Antigravity CLI'`, `command: 'agy'`, `args: []`, `resume_args: ['-c']`, `skip_permissions_args: ['--dangerously-skip-permissions']`, a description, and `prompt_ready_delay_ms: 1000`.
+- [x] 1.2 Confirm `AgentDef` in `src/ipc/types.ts` already covers every field used (it does today); update it only if a new field is introduced, keeping it in lockstep with the `electron/ipc/agents.ts` copy.
+- [x] 1.3 Do NOT set `mcp_config_flag` for the entry (agy has no `--mcp-config` flag).
+
+## 2. Docker isolation support
+
+- [x] 2.1 Add `agy: ['.gemini/antigravity-cli']` to `AGENT_CONFIG_DIRS` in `electron/ipc/pty.ts`. (Corrected from `.config/antigravity` — verified against the installed binary: `agy` v1.0.3 writes its app data to `~/.gemini/antigravity-cli`, and `~/.config/antigravity` does not exist.)
+- [x] 2.2 ~~Forward `ANTIGRAVITY_API_KEY` into the container.~~ **Dropped.** `agy` does not consume any API-key env var (the `ANTIGRAVITY_API_KEY` claim was unverified and is false — Codex confirmed `agy` still enters OAuth with it set). Docker-isolated `agy` cannot authenticate (keyring-only OAuth, no secret-service daemon in the container); Antigravity is native-only.
+- [x] 2.3 Add a Docker image step in `docker/Dockerfile` to install `agy` via `curl -fsSL https://antigravity.google/cli/install.sh | bash -s -- --dir /usr/local/bin` (separate from the `npm install -g` line). Ground-truthed the installer script: it supports `-d|--dir`, runs non-interactively when piped (no `read` prompts), and `mkdir -p`s the target; installing straight to `/usr/local/bin` puts `agy` on PATH for the non-root `agent` user.
+- [x] 2.4 Confirm `agy --version` resolves from the install. The Dockerfile RUN ends with `&& agy --version`, so the image build itself asserts the binary is installed and on PATH — a failed install fails the build. Full `docker build` run still pending Docker (this env has no daemon), but the verification is now baked into the build step.
+
+## 3. MCP-config guard (exclude agy from both paths)
+
+- [x] 3.1 Exclude `agy` from `legacyMcpConfigArgs` in `src/lib/agent-args.ts` so a task with only a legacy `mcpConfigPath` is not handed `--mcp-config` (same treatment as `isCodexCommand` for Codex).
+- [x] 3.2 Exclude `agy` from `buildMcpLaunchArgs` in `electron/mcp/agent-args.ts` (imported by `coordinator.ts`) so coordinator/MCP tasks never emit `--mcp-config` for `agy`.
+- [x] 3.3 Add/adjust a unit test asserting `buildTaskAgentArgs`/`buildMcpLaunchArgs` emit no `--mcp-config` for the `agy` command.
+
+## 4. Verification
+
+- [x] 4.1 `npm run typecheck` clean across renderer and electron targets — 0 errors (after restoring deps; see note below).
+- [x] 4.2 Run the agent-registry and persistence tests: `persistence.test.ts`, `agents.test.ts`, `src/lib/agent-args.test.ts`, `electron/mcp/agent-args.test.ts`, `pty.test.ts` — 111 tests pass. `pty.test.ts` config-dir-mount table extended with `agy`.
+- [ ] 4.3 Manual native smoke test: with `agy` installed, the selector shows "Antigravity CLI" available; start a task, confirm the prompt is delivered and the session runs; resume a task and confirm `-c` is used. **Pending** — needs the running app.
+- [ ] 4.4 Manual skip-permissions smoke test: start an Antigravity task with skip-permissions enabled and confirm `--dangerously-skip-permissions` is passed. **Pending** — needs the running app.
+- [x] 4.5 `openspec validate --all --strict` passes.
+
+## 5. Docs & PR
+
+- [x] 5.1 Document in user-facing docs that Antigravity is native-only: login is keyring-only OAuth, the container has no secret-service daemon, and `agy` has no API-key fallback, so Docker-isolated Antigravity cannot authenticate. Added to `README.md` (Antigravity in the CLI install list + a "run natively, not in Docker isolation" details block).
+- [x] 5.2 Call out the same native-only constraint in the PR description (works natively; Docker isolation unsupported for Antigravity), so reviewers and users see it up front. Drafted in `/tmp/pr-body.md` (use with `gh pr create --body-file`).
diff --git a/src/lib/agent-args.test.ts b/src/lib/agent-args.test.ts
index c4cc65fa..319bb18e 100644
--- a/src/lib/agent-args.test.ts
+++ b/src/lib/agent-args.test.ts
@@ -22,6 +22,16 @@ const claudeAgent = {
skip_permissions_args: ['--dangerously-skip-permissions'],
};
+const antigravityAgent = {
+ id: 'antigravity',
+ name: 'Antigravity CLI',
+ description: 'Antigravity agent',
+ command: 'agy',
+ args: [],
+ resume_args: ['-c'],
+ skip_permissions_args: ['--dangerously-skip-permissions'],
+};
+
describe('buildTaskAgentArgs', () => {
it('uses explicit MCP launch args when provided', () => {
expect(
@@ -68,4 +78,30 @@ describe('buildTaskAgentArgs', () => {
),
).toEqual(['--mcp-config', '/tmp/mcp.json']);
});
+
+ it('does not fall back to --mcp-config for Antigravity', () => {
+ expect(
+ buildTaskAgentArgs(
+ antigravityAgent,
+ {
+ skipPermissions: false,
+ mcpConfigPath: '/tmp/mcp.json',
+ },
+ false,
+ ),
+ ).toEqual([]);
+ });
+
+ it('passes the resume flag for Antigravity without --mcp-config', () => {
+ expect(
+ buildTaskAgentArgs(
+ antigravityAgent,
+ {
+ skipPermissions: false,
+ mcpConfigPath: '/tmp/mcp.json',
+ },
+ true,
+ ),
+ ).toEqual(['-c']);
+ });
});
diff --git a/src/lib/agent-args.ts b/src/lib/agent-args.ts
index 3474a9da..e1dd94e7 100644
--- a/src/lib/agent-args.ts
+++ b/src/lib/agent-args.ts
@@ -5,8 +5,13 @@ function isCodexCommand(command: string): boolean {
return command.split('/').pop()?.includes('codex') === true;
}
+function isAntigravityCommand(command: string): boolean {
+ return command.split('/').pop() === 'agy';
+}
+
function legacyMcpConfigArgs(command: string, mcpConfigPath: string | undefined): string[] {
- if (!mcpConfigPath || isCodexCommand(command)) return [];
+ // Codex and Antigravity have no `--mcp-config` flag; passing it would break launch.
+ if (!mcpConfigPath || isCodexCommand(command) || isAntigravityCommand(command)) return [];
return ['--mcp-config', mcpConfigPath];
}