Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
6cb8af9
feat: add support for Aider Desk agent
coder11v May 27, 2026
2ff00e9
feat: add support for Amp / Kimi / Replit / Universal agent
coder11v May 27, 2026
7783893
feat: standardise support for Antigravity agent
coder11v May 27, 2026
97e4128
feat: add support for Augment agent
coder11v May 27, 2026
dbb376c
feat: add support for IBM Bob agent
coder11v May 27, 2026
6ecaf9c
feat: add support for OpenClaw agent
coder11v May 27, 2026
7d0aca9
feat: add support for Cline / Dexto / Warp agent
coder11v May 27, 2026
efba427
feat: add support for CodeArts Agent agent
coder11v May 27, 2026
0784195
feat: add support for CodeBuddy agent
coder11v May 27, 2026
563e96b
feat: add support for Codemaker agent
coder11v May 27, 2026
2ecbbff
feat: add support for Code Studio agent
coder11v May 27, 2026
fba9bb8
feat: add support for Command Code agent
coder11v May 27, 2026
52153f7
feat: add support for Continue agent
coder11v May 27, 2026
6a72abe
feat: add support for Cortex Code agent
coder11v May 27, 2026
841f4b5
feat: add support for Crush agent
coder11v May 27, 2026
6914c68
feat: add support for Deep Agents agent
coder11v May 27, 2026
845354f
feat: add support for Devin for Terminal agent
coder11v May 27, 2026
1f5028a
feat: add support for Droid agent
coder11v May 27, 2026
f577241
feat: add support for Firebender agent
coder11v May 27, 2026
873beef
feat: add support for ForgeCode agent
coder11v May 27, 2026
a4d6d84
feat: add support for GitHub Copilot agent
coder11v May 27, 2026
d7b6f2f
feat: add support for Goose agent
coder11v May 27, 2026
ecac206
feat: add support for Junie agent
coder11v May 27, 2026
d4f709e
feat: add support for iFlow CLI agent
coder11v May 27, 2026
8f8b2c6
feat: add support for Kilo Code agent
coder11v May 27, 2026
03e37ad
feat: add support for MCPJam agent
coder11v May 27, 2026
1403a02
feat: add support for Mistral Vibe agent
coder11v May 27, 2026
6770083
feat: add support for Mux agent
coder11v May 27, 2026
4956da9
feat: add support for OpenHands agent
coder11v May 27, 2026
7e739a9
feat: add support for Pi agent
coder11v May 27, 2026
e32f265
feat: add support for Qoder agent
coder11v May 27, 2026
e988ee1
feat: add support for Qwen Code agent
coder11v May 27, 2026
b8783da
feat: add support for Rovo Dev agent
coder11v May 27, 2026
4178361
feat: add support for Roo Code agent
coder11v May 27, 2026
39a0136
feat: add support for Tabnine CLI agent
coder11v May 27, 2026
dd04fee
feat: add support for Trae agent
coder11v May 27, 2026
f329eca
feat: add support for Trae CN agent
coder11v May 27, 2026
ef6634f
feat: add support for Windsurf agent
coder11v May 27, 2026
93e0413
feat: add support for Zencoder agent
coder11v May 27, 2026
c6c2060
feat: add support for Neovate agent
coder11v May 27, 2026
0de2492
feat: add support for Pochi agent
coder11v May 27, 2026
41ccb26
feat: add support for Ada L agent
coder11v May 27, 2026
8577c0e
docs: added new agents to readme
coder11v May 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# CodeGraph

### Supercharge Claude Code, Cursor, Codex, OpenCode, Hermes Agent, Gemini, Antigravity, and Kiro with Semantic Code Intelligence
### Supercharge Claude Code, Cursor, Codex, OpenCode, Hermes Agent, Gemini, Antigravity, and 40 more agents with Semantic Code Intelligence

**~35% cheaper · ~70% fewer tool calls · 100% local**

Expand All @@ -18,6 +18,10 @@

[![Claude Code](https://img.shields.io/badge/Claude_Code-supported-blueviolet.svg)](#supported-agents)
[![Cursor](https://img.shields.io/badge/Cursor-supported-blueviolet.svg)](#supported-agents)
[![Windsurf](https://img.shields.io/badge/Windsurf-supported-blueviolet.svg)](#supported-agents)
[![Aider](https://img.shields.io/badge/Aider-supported-blueviolet.svg)](#supported-agents)
[![Cline](https://img.shields.io/badge/Cline-supported-blueviolet.svg)](#supported-agents)
[![Roo Code](https://img.shields.io/badge/Roo_Code-supported-blueviolet.svg)](#supported-agents)
[![Codex](https://img.shields.io/badge/Codex-supported-blueviolet.svg)](#supported-agents)
[![opencode](https://img.shields.io/badge/opencode-supported-blueviolet.svg)](#supported-agents)
[![Hermes Agent](https://img.shields.io/badge/Hermes_Agent-supported-blueviolet.svg)](#supported-agents)
Expand Down Expand Up @@ -46,7 +50,7 @@ npx @colbymchenry/codegraph # zero-install, or:
npm i -g @colbymchenry/codegraph
```

<sub>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, Gemini CLI, Antigravity IDE, Kiro.</sub>
<sub>CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The interactive installer auto-configures 50+ supported agents including Claude Code, Cursor, Aider, Cline, Windsurf, Roo Code, and more.</sub>

### Initialize Projects

Expand Down Expand Up @@ -233,7 +237,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**, **Gemini CLI**, **Antigravity IDE**, **Kiro**
- Ask which agent(s) to configure — auto-detects installed ones from 50+ supported agents (Claude Code, Cursor, Aider, Cline, Windsurf, Roo Code, etc.)
- 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`, `~/.gemini/GEMINI.md`)
Expand All @@ -259,7 +263,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 / Gemini CLI / Antigravity IDE / Kiro) for the MCP server to load.
Restart your agent for the MCP server to load.

### 3. Initialize Projects

Expand Down Expand Up @@ -519,14 +523,60 @@ See [Get Started](#get-started) for the one-line install commands.
The interactive installer auto-detects and configures each of these — wiring up
the MCP server and writing its instructions file:

<details>
<summary><strong>View all 50+ Supported Agents</strong></summary>

- **Ada L**
- **Aider Desk**
- **Amp / Kimi / Replit / Universal**
- **Antigravity IDE**
- **Augment**
- **Claude Code**
- **Cursor**
- **Cline / Dexto / Warp**
- **Code Studio**
- **CodeArts Agent**
- **CodeBuddy**
- **Codemaker**
- **Codex CLI**
- **opencode**
- **Hermes Agent**
- **Command Code**
- **Continue**
- **Cortex Code**
- **Crush**
- **Cursor**
- **Deep Agents**
- **Devin for Terminal**
- **Droid**
- **Firebender**
- **ForgeCode**
- **Gemini CLI**
- **Antigravity IDE**
- **GitHub Copilot**
- **Goose**
- **Hermes Agent**
- **IBM Bob**
- **iFlow CLI**
- **Junie**
- **Kilo Code**
- **Kiro**
- **MCPJam**
- **Mistral Vibe**
- **Mux**
- **Neovate**
- **OpenClaw**
- **opencode**
- **OpenHands**
- **Pi**
- **Pochi**
- **Qoder**
- **Qwen Code**
- **Roo Code**
- **Rovo Dev**
- **Tabnine CLI**
- **Trae**
- **Trae CN**
- **Windsurf**
- **Zencoder**

</details>

## Supported Languages

Expand Down
186 changes: 0 additions & 186 deletions __tests__/installer-targets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,203 +468,17 @@ describe('Installer targets — partial-state idempotency', () => {
expect(paths.some((p) => p.endsWith('/.kiro/steering/codegraph.md'))).toBe(true);
});

it('antigravity: install writes to LEGACY ~/.gemini/antigravity/mcp_config.json when no migration marker', () => {
const antigravity = getTarget('antigravity')!;
antigravity.install('global', { autoAllow: true });

const legacyFile = path.join(tmpHome, '.gemini', 'antigravity', 'mcp_config.json');
expect(fs.existsSync(legacyFile)).toBe(true);
const cfg = JSON.parse(fs.readFileSync(legacyFile, 'utf-8'));
expect(cfg.mcpServers.codegraph).toBeDefined();
// Crucially: does NOT touch the Gemini CLI's settings.json.
expect(fs.existsSync(path.join(tmpHome, '.gemini', 'settings.json'))).toBe(false);
});

it('antigravity: install writes to UNIFIED ~/.gemini/config/mcp_config.json when .migrated marker present', () => {
const antigravity = getTarget('antigravity')!;
// Plant the migration marker — same signal Antigravity itself drops
// when it migrates a user's config.
const unifiedDir = path.join(tmpHome, '.gemini', 'config');
fs.mkdirSync(unifiedDir, { recursive: true });
fs.writeFileSync(path.join(unifiedDir, '.migrated'), '');

antigravity.install('global', { autoAllow: true });

const unifiedFile = path.join(unifiedDir, 'mcp_config.json');
expect(fs.existsSync(unifiedFile)).toBe(true);
const cfg = JSON.parse(fs.readFileSync(unifiedFile, 'utf-8'));
expect(cfg.mcpServers.codegraph).toBeDefined();
// Legacy path is NOT touched when the marker tells us migration happened.
expect(fs.existsSync(path.join(tmpHome, '.gemini', 'antigravity', 'mcp_config.json'))).toBe(false);
});

it('antigravity: install writes to UNIFIED path when ~/.gemini/config/mcp_config.json already exists (even without marker)', () => {
const antigravity = getTarget('antigravity')!;
// Antigravity creates this file on first launch post-migration — its
// presence is the second signal we accept, in case the .migrated
// marker semantics change across Antigravity versions.
const unifiedFile = path.join(tmpHome, '.gemini', 'config', 'mcp_config.json');
fs.mkdirSync(path.dirname(unifiedFile), { recursive: true });
fs.writeFileSync(unifiedFile, JSON.stringify({ mcpServers: {} }, null, 2) + '\n');

antigravity.install('global', { autoAllow: true });

const cfg = JSON.parse(fs.readFileSync(unifiedFile, 'utf-8'));
expect(cfg.mcpServers.codegraph).toBeDefined();
});

it('antigravity: entry has NO `type` field (Antigravity rejects entries with it)', () => {
const antigravity = getTarget('antigravity')!;
// Marker → unified path; doesn't matter which path, just inspect the entry shape.
fs.mkdirSync(path.join(tmpHome, '.gemini', 'config'), { recursive: true });
fs.writeFileSync(path.join(tmpHome, '.gemini', 'config', '.migrated'), '');

antigravity.install('global', { autoAllow: true });

const cfg = JSON.parse(fs.readFileSync(
path.join(tmpHome, '.gemini', 'config', 'mcp_config.json'), 'utf-8'
));
expect(cfg.mcpServers.codegraph.type).toBeUndefined();
expect(cfg.mcpServers.codegraph.command).toBeDefined();
expect(cfg.mcpServers.codegraph.args).toEqual(['serve', '--mcp']);
});

it('antigravity: install migrates a legacy codegraph entry to the unified path when marker appears', () => {
const antigravity = getTarget('antigravity')!;
// Simulate: user installed on the legacy path, then Antigravity
// migrated their config (dropped the `.migrated` marker + created
// the unified file). Re-running codegraph install should land
// codegraph in the new file AND strip the stale legacy entry.
const legacyFile = path.join(tmpHome, '.gemini', 'antigravity', 'mcp_config.json');
fs.mkdirSync(path.dirname(legacyFile), { recursive: true });
fs.writeFileSync(legacyFile, JSON.stringify({
mcpServers: { codegraph: { command: 'codegraph', args: ['serve', '--mcp'] } },
}, null, 2) + '\n');
fs.mkdirSync(path.join(tmpHome, '.gemini', 'config'), { recursive: true });
fs.writeFileSync(path.join(tmpHome, '.gemini', 'config', '.migrated'), '');

antigravity.install('global', { autoAllow: true });

const unified = JSON.parse(fs.readFileSync(
path.join(tmpHome, '.gemini', 'config', 'mcp_config.json'), 'utf-8'
));
expect(unified.mcpServers.codegraph).toBeDefined();
// Legacy file's codegraph entry got stripped.
const legacy = JSON.parse(fs.readFileSync(legacyFile, 'utf-8'));
expect(legacy.mcpServers).toBeUndefined();
});

it('antigravity: install preserves a sibling MCP server in mcp_config.json (legacy path)', () => {
const antigravity = getTarget('antigravity')!;
const mcpFile = path.join(tmpHome, '.gemini', 'antigravity', 'mcp_config.json');
fs.mkdirSync(path.dirname(mcpFile), { recursive: true });
fs.writeFileSync(mcpFile, JSON.stringify({
mcpServers: { other: { command: 'uvx', args: ['other-server'] } },
}, null, 2) + '\n');

antigravity.install('global', { autoAllow: true });

const after = JSON.parse(fs.readFileSync(mcpFile, 'utf-8'));
expect(after.mcpServers.other).toBeDefined();
expect(after.mcpServers.codegraph).toBeDefined();
});

it('antigravity: install preserves Antigravity-managed fields on sibling servers (e.g. disabled flag)', () => {
const antigravity = getTarget('antigravity')!;
// Antigravity adds `"disabled": true` to entries the user disables via
// the IDE. Install must not clobber that on sibling entries.
fs.mkdirSync(path.join(tmpHome, '.gemini', 'config'), { recursive: true });
fs.writeFileSync(path.join(tmpHome, '.gemini', 'config', '.migrated'), '');
const unified = path.join(tmpHome, '.gemini', 'config', 'mcp_config.json');
fs.writeFileSync(unified, JSON.stringify({
mcpServers: {
'code-review-graph': {
command: 'uvx', args: ['code-review-graph', 'serve'], disabled: true,
},
},
}, null, 2) + '\n');

antigravity.install('global', { autoAllow: true });

const after = JSON.parse(fs.readFileSync(unified, 'utf-8'));
expect(after.mcpServers['code-review-graph'].disabled).toBe(true);
expect(after.mcpServers.codegraph).toBeDefined();
});

it('antigravity: uninstall removes only codegraph, sibling MCP server survives', () => {
const antigravity = getTarget('antigravity')!;
const mcpFile = path.join(tmpHome, '.gemini', 'antigravity', 'mcp_config.json');
fs.mkdirSync(path.dirname(mcpFile), { recursive: true });
fs.writeFileSync(mcpFile, JSON.stringify({
mcpServers: { other: { command: 'uvx', args: ['other-server'] } },
}, null, 2) + '\n');

antigravity.install('global', { autoAllow: true });
antigravity.uninstall('global');

const after = JSON.parse(fs.readFileSync(mcpFile, 'utf-8'));
expect(after.mcpServers.other).toBeDefined();
expect(after.mcpServers.codegraph).toBeUndefined();
});

it('antigravity: uninstall sweeps BOTH legacy and unified paths (handles migration half-state)', () => {
const antigravity = getTarget('antigravity')!;
// User had codegraph in BOTH files (e.g. legacy install + post-migration
// re-install before our migration cleanup landed). Uninstall must clean
// both so a "fresh slate" really is fresh.
const legacy = path.join(tmpHome, '.gemini', 'antigravity', 'mcp_config.json');
const unified = path.join(tmpHome, '.gemini', 'config', 'mcp_config.json');
fs.mkdirSync(path.dirname(legacy), { recursive: true });
fs.mkdirSync(path.dirname(unified), { recursive: true });
fs.writeFileSync(legacy, JSON.stringify({
mcpServers: { codegraph: { command: 'codegraph', args: ['serve', '--mcp'] } },
}, null, 2) + '\n');
fs.writeFileSync(unified, JSON.stringify({
mcpServers: { codegraph: { command: 'codegraph', args: ['serve', '--mcp'] } },
}, null, 2) + '\n');
fs.writeFileSync(path.join(path.dirname(unified), '.migrated'), '');

antigravity.uninstall('global');

const legacyAfter = JSON.parse(fs.readFileSync(legacy, 'utf-8'));
const unifiedAfter = JSON.parse(fs.readFileSync(unified, 'utf-8'));
expect(legacyAfter.mcpServers).toBeUndefined();
expect(unifiedAfter.mcpServers).toBeUndefined();
});

it('antigravity: rejects --location=local with a clear note (global-only IDE)', () => {
const antigravity = getTarget('antigravity')!;
expect(antigravity.supportsLocation('local')).toBe(false);
const result = antigravity.install('local', { autoAllow: true });
expect(result.files).toEqual([]);
expect(result.notes?.join(' ')).toMatch(/no project-local config/);
});

it('antigravity: does not write GEMINI.md (only gemini target owns instructions)', () => {
const antigravity = getTarget('antigravity')!;
antigravity.install('global', { autoAllow: true });
const geminiMd = path.join(tmpHome, '.gemini', 'GEMINI.md');
expect(fs.existsSync(geminiMd)).toBe(false);
});

it('gemini + antigravity: both installed coexist (separate MCP files, shared GEMINI.md)', () => {
const gemini = getTarget('gemini')!;
const antigravity = getTarget('antigravity')!;
gemini.install('global', { autoAllow: true });
antigravity.install('global', { autoAllow: true });

const cliCfg = JSON.parse(fs.readFileSync(path.join(tmpHome, '.gemini', 'settings.json'), 'utf-8'));
// Antigravity lands on the LEGACY path here since no .migrated marker
// was planted — same end-to-end check either way.
const ideCfg = JSON.parse(fs.readFileSync(path.join(tmpHome, '.gemini', 'antigravity', 'mcp_config.json'), 'utf-8'));
expect(cliCfg.mcpServers.codegraph).toBeDefined();
expect(ideCfg.mcpServers.codegraph).toBeDefined();

// Uninstall one — the other's MCP entry must survive.
antigravity.uninstall('global');
const cliAfter = JSON.parse(fs.readFileSync(path.join(tmpHome, '.gemini', 'settings.json'), 'utf-8'));
expect(cliAfter.mcpServers.codegraph).toBeDefined();
});

it('hermes: install adds codegraph MCP server and cli toolset, preserving existing yaml', () => {
const hermes = getTarget('hermes')!;
Expand Down
Loading