diff --git a/README.md b/README.md
index faf357bc..5d9ae8d2 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
# CodeGraph
-### Supercharge Claude Code, Cursor, Codex, OpenCode, and Hermes Agent with Semantic Code Intelligence
+### Supercharge Claude Code, Cursor, Codex, OpenCode, Hermes Agent, and Antigravity IDE with Semantic Code Intelligence
**~35% cheaper · ~70% fewer tool calls · 100% local**
@@ -19,6 +19,7 @@
[](#supported-agents)
[](#supported-agents)
[](#supported-agents)
+[](#supported-agents)
@@ -41,7 +42,7 @@ npx @colbymchenry/codegraph # zero-install, or:
npm i -g @colbymchenry/codegraph
```
-CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The interactive installer auto-configures your agent(s) — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent.
+CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The interactive installer auto-configures your agent(s) — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Antigravity IDE.
### Initialize Projects
@@ -171,7 +172,7 @@ npx @colbymchenry/codegraph
```
The installer will:
-- Ask which agent(s) to configure — auto-detects installed ones from: **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, **Hermes Agent**
+- Ask which agent(s) to configure — auto-detects installed ones from: **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, **Hermes Agent**, **Antigravity IDE**
- Prompt to install `codegraph` on your PATH (so agents can launch the MCP server)
- Ask whether configs apply to all your projects or just this one
- Write each chosen agent's MCP server config + an instructions file (e.g. `CLAUDE.md`, `.cursor/rules/codegraph.mdc`, `~/.codex/AGENTS.md`)
@@ -197,7 +198,7 @@ codegraph install --print-config codex # print snippet, no file wr
### 2. Restart Your Agent
-Restart your agent (Claude Code / Cursor / Codex CLI / opencode / Hermes Agent) for the MCP server to load.
+Restart your agent (Claude Code / Cursor / Codex CLI / opencode / Hermes Agent / Antigravity IDE) for the MCP server to load.
### 3. Initialize Projects
@@ -474,6 +475,7 @@ the MCP server and writing its instructions file:
- **Codex CLI**
- **opencode**
- **Hermes Agent**
+- **Antigravity IDE**
## Supported Languages
@@ -534,7 +536,7 @@ MIT
-**Made for AI coding agents — Claude Code, Cursor, Codex CLI, opencode, and Hermes Agent**
+**Made for AI coding agents — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, and Antigravity IDE**
[Report Bug](https://github.com/colbymchenry/codegraph/issues) · [Request Feature](https://github.com/colbymchenry/codegraph/issues)
diff --git a/package-lock.json b/package-lock.json
index 36c592b1..d9b3b484 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@colbymchenry/codegraph",
- "version": "0.9.3",
+ "version": "0.9.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@colbymchenry/codegraph",
- "version": "0.9.3",
+ "version": "0.9.4",
"license": "MIT",
"dependencies": {
"@clack/prompts": "^1.3.0",
@@ -1431,7 +1431,6 @@
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",
diff --git a/src/installer/targets/antigravity.ts b/src/installer/targets/antigravity.ts
new file mode 100644
index 00000000..2b2cb9be
--- /dev/null
+++ b/src/installer/targets/antigravity.ts
@@ -0,0 +1,256 @@
+/**
+ * Antigravity IDE target.
+ *
+ * Installs CodeGraph as an Antigravity Plugin, enabling support for
+ * both global (`~/.gemini/config/plugins/codegraph/`) and local
+ * (`./.agents/plugins/codegraph/`) deployments.
+ *
+ * The plugin bundles:
+ * - `plugin.json`
+ * - `mcp_config.json`
+ * - `skills/codegraph-instructions/SKILL.md` (Agent instructions)
+ */
+
+import * as fs from 'fs';
+import * as path from 'path';
+import * as os from 'os';
+import {
+ AgentTarget,
+ DetectionResult,
+ InstallOptions,
+ Location,
+ WriteResult,
+} from './types';
+import {
+ getMcpServerConfig,
+ jsonDeepEqual,
+ readJsonFile,
+ writeJsonFile,
+} from './shared';
+import {
+ INSTRUCTIONS_TEMPLATE,
+} from '../instructions-template';
+
+function configDir(loc: Location): string {
+ return loc === 'global'
+ ? path.join(os.homedir(), '.gemini', 'config', 'plugins', 'codegraph')
+ : path.join(process.cwd(), '.agents', 'plugins', 'codegraph');
+}
+
+function pluginJsonPath(loc: Location): string {
+ return path.join(configDir(loc), 'plugin.json');
+}
+
+function mcpJsonPath(loc: Location): string {
+ return path.join(configDir(loc), 'mcp_config.json');
+}
+
+function instructionsPath(loc: Location): string {
+ return path.join(configDir(loc), 'skills', 'codegraph-instructions', 'SKILL.md');
+}
+
+function rulesPath(loc: Location): string {
+ return path.join(configDir(loc), 'rules', 'codegraph-rules.md');
+}
+
+class AntigravityTarget implements AgentTarget {
+ readonly id = 'antigravity' as const;
+ readonly displayName = 'Antigravity IDE';
+ readonly docsUrl = '';
+
+ supportsLocation(_loc: Location): boolean {
+ return true;
+ }
+
+ detect(loc: Location): DetectionResult {
+ const dir = configDir(loc);
+ const installed = fs.existsSync(dir);
+ return { installed, alreadyConfigured: installed, configPath: dir };
+ }
+
+ install(loc: Location, _opts: InstallOptions): WriteResult {
+ const files: WriteResult['files'] = [];
+
+ // Cleanup legacy files from earlier flawed global install
+ if (loc === 'global') {
+ const legacyCleanup = cleanupLegacyFiles();
+ files.push(...legacyCleanup);
+ }
+
+ files.push(writePluginJson(loc));
+ files.push(writeMcpEntry(loc));
+ files.push(writeInstructionsEntry(loc));
+ files.push(writeRulesEntry(loc));
+
+ return { files };
+ }
+
+ uninstall(loc: Location): WriteResult {
+ const files: WriteResult['files'] = [];
+
+ const dir = configDir(loc);
+ if (fs.existsSync(dir)) {
+ try {
+ fs.rmSync(dir, { recursive: true, force: true });
+ files.push({ path: dir, action: 'removed' });
+ } catch {
+ // Ignore removal errors
+ }
+ } else {
+ files.push({ path: dir, action: 'not-found' });
+ }
+
+ if (loc === 'global') {
+ const legacyCleanup = cleanupLegacyFiles();
+ files.push(...legacyCleanup);
+ }
+
+ return { files };
+ }
+
+ printConfig(loc: Location): string {
+ const target = mcpJsonPath(loc);
+ const snippet = JSON.stringify({ mcpServers: { codegraph: getMcpServerConfig() } }, null, 2);
+ return `# Add to ${target}\n\n${snippet}\n`;
+ }
+
+ describePaths(loc: Location): string[] {
+ return [configDir(loc)];
+ }
+}
+
+function writePluginJson(loc: Location): WriteResult['files'][number] {
+ const file = pluginJsonPath(loc);
+ const dir = path.dirname(file);
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
+
+ const existing = fs.existsSync(file) ? readJsonFile(file) : null;
+ const after = { name: 'codegraph', description: 'CodeGraph Semantic Code Intelligence' };
+
+ if (existing && jsonDeepEqual(existing, after)) {
+ return { path: file, action: 'unchanged' };
+ }
+
+ writeJsonFile(file, after);
+ return { path: file, action: existing ? 'updated' : 'created' };
+}
+
+function writeMcpEntry(loc: Location): WriteResult['files'][number] {
+ const file = mcpJsonPath(loc);
+ const dir = path.dirname(file);
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
+
+ const existing = fs.existsSync(file) ? readJsonFile(file) : null;
+ const after = { mcpServers: { codegraph: getMcpServerConfig() } };
+
+ if (existing && jsonDeepEqual(existing, after)) {
+ return { path: file, action: 'unchanged' };
+ }
+
+ writeJsonFile(file, after);
+ return { path: file, action: existing ? 'updated' : 'created' };
+}
+
+function writeInstructionsEntry(loc: Location): WriteResult['files'][number] {
+ const file = instructionsPath(loc);
+ const dir = path.dirname(file);
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
+
+ const SKILL_CONTENT = `---
+name: codegraph-instructions
+description: Explains how to use the CodeGraph MCP server for semantic code intelligence, codebase graph queries, finding references, and understanding architecture. Use this whenever the codegraph_* tools are available or the user asks questions about code structure.
+---
+
+${INSTRUCTIONS_TEMPLATE}
+`;
+
+ let action: 'created' | 'updated' | 'unchanged' = 'created';
+ if (fs.existsSync(file)) {
+ const existing = fs.readFileSync(file, 'utf-8');
+ if (existing === SKILL_CONTENT) {
+ action = 'unchanged';
+ } else {
+ action = 'updated';
+ }
+ }
+
+ if (action !== 'unchanged') {
+ fs.writeFileSync(file, SKILL_CONTENT, 'utf-8');
+ }
+
+ return { path: file, action };
+}
+
+function writeRulesEntry(loc: Location): WriteResult['files'][number] {
+ const file = rulesPath(loc);
+ const dir = path.dirname(file);
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
+
+ const RULE_CONTENT = `---
+name: codegraph-rules
+description: Defines when to use CodeGraph over native grep search.
+trigger: always_on
+---
+
+${INSTRUCTIONS_TEMPLATE}
+`;
+
+ let action: 'created' | 'updated' | 'unchanged' = 'created';
+ if (fs.existsSync(file)) {
+ const existing = fs.readFileSync(file, 'utf-8');
+ if (existing === RULE_CONTENT) {
+ action = 'unchanged';
+ } else {
+ action = 'updated';
+ }
+ }
+
+ if (action !== 'unchanged') {
+ fs.writeFileSync(file, RULE_CONTENT, 'utf-8');
+ }
+
+ return { path: file, action };
+}
+
+function cleanupLegacyFiles(): WriteResult['files'] {
+ const files: WriteResult['files'] = [];
+
+ // Cleanup wrong mcp config file
+ const oldMcpPath = path.join(os.homedir(), '.gemini', 'config', 'mcp_config.json');
+ if (fs.existsSync(oldMcpPath)) {
+ try {
+ const config = readJsonFile(oldMcpPath);
+ if (config?.mcpServers?.codegraph) {
+ delete config.mcpServers.codegraph;
+ if (Object.keys(config.mcpServers).length === 0) {
+ delete config.mcpServers;
+ }
+ writeJsonFile(oldMcpPath, config);
+ files.push({ path: oldMcpPath, action: 'updated' });
+ }
+ } catch {
+ // ignore
+ }
+ }
+
+ // Cleanup wrong instructions file
+ const oldInstrDir = path.join(os.homedir(), '.gemini', 'antigravity-ide', 'mcp', 'codegraph');
+ const oldInstr = path.join(oldInstrDir, 'instructions.md');
+ if (fs.existsSync(oldInstr)) {
+ try {
+ fs.unlinkSync(oldInstr);
+ files.push({ path: oldInstr, action: 'removed' });
+
+ // Cleanup empty dirs up to .gemini/antigravity-ide
+ if (fs.readdirSync(oldInstrDir).length === 0) fs.rmdirSync(oldInstrDir);
+ const parentDir = path.dirname(oldInstrDir);
+ if (fs.readdirSync(parentDir).length === 0) fs.rmdirSync(parentDir);
+ } catch {
+ // ignore
+ }
+ }
+
+ return files;
+}
+
+export const antigravityTarget: AgentTarget = new AntigravityTarget();
diff --git a/src/installer/targets/registry.ts b/src/installer/targets/registry.ts
index 0091ab64..102ecd54 100644
--- a/src/installer/targets/registry.ts
+++ b/src/installer/targets/registry.ts
@@ -13,6 +13,7 @@ import { cursorTarget } from './cursor';
import { codexTarget } from './codex';
import { opencodeTarget } from './opencode';
import { hermesTarget } from './hermes';
+import { antigravityTarget } from './antigravity';
export const ALL_TARGETS: readonly AgentTarget[] = Object.freeze([
claudeTarget,
@@ -20,6 +21,7 @@ export const ALL_TARGETS: readonly AgentTarget[] = Object.freeze([
codexTarget,
opencodeTarget,
hermesTarget,
+ antigravityTarget,
]);
export function getTarget(id: string): AgentTarget | undefined {
diff --git a/src/installer/targets/types.ts b/src/installer/targets/types.ts
index 290f13ce..158a1e8d 100644
--- a/src/installer/targets/types.ts
+++ b/src/installer/targets/types.ts
@@ -19,7 +19,7 @@ export type Location = 'global' | 'local';
* lookup. New targets add a value here when they're added to the
* registry. Keep these short and lowercase.
*/
-export type TargetId = 'claude' | 'cursor' | 'codex' | 'opencode' | 'hermes';
+export type TargetId = 'claude' | 'cursor' | 'codex' | 'opencode' | 'hermes' | 'antigravity';
/**
* Result of `target.detect(location)`.