Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Defined in `src/types.ts`. Both extractors and resolvers must use these exact st

- `targets/registry.ts` lists every supported agent.
- `targets/types.ts` defines the `AgentTarget` interface — adding a 5th agent (Continue, Zed, Windsurf…) is **one new file in `targets/` + one entry in `registry.ts`**. Each target owns its config-file location, MCP-server JSON/TOML/JSONC writing, and instructions-file path.
- Current targets: `claude.ts`, `cursor.ts`, `codex.ts`, `opencode.ts`.
- Current targets: `claude.ts`, `cursor.ts`, `codex.ts`, `opencode.ts`, `pi.ts`.
- `targets/toml.ts` is a hand-rolled TOML serializer scoped to `[mcp_servers.codegraph]` (used by Codex). Sibling tables and `[[array_of_tables]]` are preserved verbatim. No new dependency.
- opencode reads `opencode.jsonc` by default; the installer prefers existing `.jsonc`, falls back to `.json`, and creates `.jsonc` for greenfield installs. Edits are surgical via `jsonc-parser` so user comments and formatting survive install/re-install/uninstall round-trips.
- `instructions-template.ts` is the agent-agnostic instructions file written to each target (e.g. `CLAUDE.md`, `.cursor/rules/codegraph.mdc`, `~/.codex/AGENTS.md`, `~/.config/opencode/AGENTS.md`). It explicitly says "trust codegraph results, don't re-verify with grep" — earlier versions prescribed Claude-specific "spawn an Explore agent" and confused other agents.
Expand Down
276 changes: 139 additions & 137 deletions README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions __tests__/installer-targets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,7 @@ describe('Installer targets — registry', () => {
expect(getTarget('gemini')?.id).toBe('gemini');
expect(getTarget('antigravity')?.id).toBe('antigravity');
expect(getTarget('kiro')?.id).toBe('kiro');
expect(getTarget('pi')?.id).toBe('pi');
expect(getTarget('not-a-real-target')).toBeUndefined();
});

Expand Down
30 changes: 15 additions & 15 deletions site/src/content/docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ title: Installation
description: Install CodeGraph and configure your AI coding agents.
---

## 1. Run the installer
## 1. Run the installer

```bash
npx @colbymchenry/codegraph
```

The installer will:

- Ask which agent(s) to configure — auto-detecting installed ones from **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, **Hermes Agent**, **Gemini CLI**, **Antigravity IDE**, and **Kiro**.
- Ask which agent(s) to configure — auto-detecting installed ones from **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, **Hermes Agent**, **Gemini CLI**, **Antigravity IDE**, **Kiro**, and **pi**.
- 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 plus an instructions file (e.g. `CLAUDE.md`, `.cursor/rules/codegraph.mdc`, `~/.codex/AGENTS.md`).
Expand All @@ -27,17 +27,17 @@ codegraph install --target=auto --location=local # detected agents, project-
codegraph install --print-config codex # print snippet, no file writes
```

| Flag | Values | Default |
|---|---|---|
| `--target` | `auto`, `all`, `none`, or csv (`claude,cursor,…`) | prompt |
| `--location` | `global`, `local` | prompt |
| `--yes` | (boolean) | prompt every step |
| `--no-permissions` | (boolean) skip Claude auto-allow list | permissions on |
| `--print-config <id>` | dump snippet for one agent and exit | — |
| Flag | Values | Default |
| --------------------- | ------------------------------------------------- | ----------------- |
| `--target` | `auto`, `all`, `none`, or csv (`claude,cursor,…`) | prompt |
| `--location` | `global`, `local` | prompt |
| `--yes` | (boolean) | prompt every step |
| `--no-permissions` | (boolean) skip Claude auto-allow list | permissions on |
| `--print-config <id>` | dump snippet for one agent and exit | — |

## 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 (Claude Code / Cursor / Codex CLI / opencode / Hermes Agent / Gemini CLI / Antigravity IDE / Kiro / pi) for the MCP server to load.

## 3. Initialize projects

Expand All @@ -52,11 +52,11 @@ This builds the per-project knowledge graph index and wires up any project-local

Every release ships a self-contained build (bundled Node runtime — nothing to compile) for all three desktop OSes, on both x64 and arm64:

| Platform | Architectures | Install |
|---|---|---|
| Windows | x64, arm64 | PowerShell installer or npm |
| macOS | x64, arm64 | shell installer or npm |
| Linux | x64, arm64 | shell installer or npm |
| Platform | Architectures | Install |
| -------- | ------------- | --------------------------- |
| Windows | x64, arm64 | PowerShell installer or npm |
| macOS | x64, arm64 | shell installer or npm |
| Linux | x64, arm64 | shell installer or npm |

## Uninstall

Expand Down
2 changes: 1 addition & 1 deletion site/src/content/docs/getting-started/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: What CodeGraph is, and why it makes AI coding agents faster and che

CodeGraph is a **local-first code-intelligence tool**. It parses your codebase with [tree-sitter](https://tree-sitter.github.io/), stores every symbol, edge, and file in a local SQLite database, and exposes the result as a queryable **knowledge graph** — over the [Model Context Protocol (MCP)](/codegraph/reference/mcp-server/), a CLI, and a TypeScript library.

It exists to make AI coding agents — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, and Kiro — **answer structural questions without scanning files**. Instead of fanning out across `grep`, `glob`, and `Read` to reconstruct how code fits together, an agent queries a pre-built index and gets the answer in a handful of calls.
It exists to make AI coding agents — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, Kiro and pi — **answer structural questions without scanning files**. Instead of fanning out across `grep`, `glob`, and `Read` to reconstruct how code fits together, an agent queries a pre-built index and gets the answer in a handful of calls.

## Why it matters

Expand Down
2 changes: 1 addition & 1 deletion site/src/content/docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,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, Gemini CLI, Antigravity IDE, Kiro.
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, pi.

## Initialize Projects

Expand Down
1 change: 1 addition & 0 deletions site/src/content/docs/reference/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The interactive installer auto-detects and configures each supported agent — w
- **Gemini CLI**
- **Antigravity IDE**
- **Kiro**
- **pi**

Run `npx @colbymchenry/codegraph` and pick your agent(s); see [Installation](/codegraph/getting-started/installation/) for the non-interactive flags.

Expand Down
214 changes: 214 additions & 0 deletions src/installer/targets/pi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/**
* pi agent target.
*
* pi (https://pi.dev) is a minimal terminal coding harness that reads
* `AGENTS.md` (or `CLAUDE.md`) from `~/.pi/agent/AGENTS.md` (global)
* and from parent directories / current directory (local). It does NOT
* natively support MCP servers — the "No MCP" design philosophy means
* there is no MCP-server config to write.
*
* What we DO write:
*
* - Instructions block with codegraph CLI usage guidance to
* `~/.pi/agent/AGENTS.md` (global) or `./AGENTS.md` (local).
* These instructions tell the pi agent to invoke codegraph via
* the CLI (`codegraph search`, `codegraph trace`, etc.) inline
* with pi's tool-use model.
* - No permissions / auto-allow concept — pi has none.
* - No MCP server config — pi doesn't support it.
*/

import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import {
AgentTarget,
DetectionResult,
InstallOptions,
Location,
WriteResult,
} from './types';
import {
removeMarkedSection,
replaceOrAppendMarkedSection,
} from './shared';
import {
CODEGRAPH_SECTION_END,
CODEGRAPH_SECTION_START,
} from '../instructions-template';

/**
* pi-specific instructions template.
*
* Since pi does not support MCP, codegraph tools are not available as
* typed tool calls. Instead, the agent invokes codegraph via its CLI
* using pi's `bash` tool. The guidance below mirrors
* `src/installer/instructions-template.ts` but adapted for CLI usage,
* and includes a note about the MCP-gap extension workaround.
*/
export const PI_INSTRUCTIONS_TEMPLATE = `${CODEGRAPH_SECTION_START}
## CodeGraph

This project has a CodeGraph knowledge graph index (\`.codegraph/\`). CodeGraph is a tree-sitter-parsed database of every symbol, edge, and file. Reads are sub-millisecond and return structural information grep cannot.

> **Note:** pi does not natively support MCP servers, so codegraph's tools are not available as built-in tool calls. Use the \`codegraph\` CLI via \`bash\` as shown below. If you want MCP-backed tool access, install a pi extension that adds MCP support.

### CLI usage reference

| Question | Command |
|---|---|
| "Find a symbol by name" | \`codegraph search <name>\` |
| "Find callers of a function" | \`codegraph callers <symbol>\` |
| "Find callees a function calls" | \`codegraph callees <symbol>\` |
| "Trace flow from X to Y" | \`codegraph trace <from> <to>\` |
| "Impact analysis for symbol Z" | \`codegraph affected <symbol>\` |
| "Show a symbol's source location" | \`codegraph query 'select ...'\` or callers/callees |
| "What files exist under path/" | \`codegraph files <path>\` |
| "Full-text search in indexed code" | \`codegraph search --fts <query>\` |
| "Build context for a task" | \`codegraph context <topic>\` |
| "Is the index healthy?" | \`codegraph status\` |

### Rules of thumb

- **Use codegraph first** for structural questions (definitions, callers, callees, trace flows). It's faster and more accurate than grep.
- **Trust codegraph results** — they come from a full AST parse. Do NOT re-verify with grep.
- **When tracing a flow**, use \`codegraph trace <from> <to>\` — one call returns the whole path with dynamic hops bridged (callbacks, React re-render, JSX).
- **Index lag**: the file watcher debounces ~500ms behind writes. If you get stale results, run \`codegraph sync\` first, or check \`codegraph status\` for pending files.

### If \`.codegraph/\` doesn't exist

Run \`codegraph init -i\` to build the index.
${CODEGRAPH_SECTION_END}`;

function piAgentDir(): string {
const envDir = process.env.PI_CODING_AGENT_DIR;
if (envDir && envDir.trim().length > 0) {
return path.resolve(envDir.trim());
}
return path.join(os.homedir(), '.pi', 'agent');
}

function configBaseDir(loc: Location): string {
return loc === 'global' ? piAgentDir() : process.cwd();
}

function agentsMdPath(loc: Location): string {
return path.join(configBaseDir(loc), 'AGENTS.md');
}

class PiTarget implements AgentTarget {
readonly id = 'pi' as const;
readonly displayName = 'pi';
readonly docsUrl = 'https://pi.dev';

supportsLocation(_loc: Location): boolean {
return true;
}

detect(loc: Location): DetectionResult {
const file = agentsMdPath(loc);
// "Installed" means pi's agent directory exists (for global) or
// pi is available on the system (local). The existence of
// `~/.pi/agent/` is the signal for pi being present globally;
// for local we also check the pi binary to avoid false positives
// in `--target=auto` on systems without pi installed.
const piOnSystem = fs.existsSync(path.join(os.homedir(), '.pi'));
const installed = loc === 'global'
? fs.existsSync(piAgentDir())
: piOnSystem;
const alreadyConfigured = hasCodeGraphSection(file);
return { installed, alreadyConfigured, configPath: file };
}

install(loc: Location, _opts: InstallOptions): WriteResult {
const files: WriteResult['files'] = [];
files.push(writeInstructionsEntry(loc));
return {
files,
notes: ['Start a new pi session for instructions to take effect.'],
};
}

uninstall(loc: Location): WriteResult {
const files: WriteResult['files'] = [];
const instr = agentsMdPath(loc);
const action = removeMarkedSection(
instr,
CODEGRAPH_SECTION_START,
CODEGRAPH_SECTION_END,
);
files.push({ path: instr, action });
return { files };
}

printConfig(loc: Location): string {
const target = agentsMdPath(loc);
return `# Add to ${target}\n\n${PI_INSTRUCTIONS_TEMPLATE}`;
}

describePaths(loc: Location): string[] {
return [agentsMdPath(loc)];
}
}

/**
* Check whether the AGENTS.md file already contains our codegraph
* section (by marker presence).
*/
function hasCodeGraphSection(file: string): boolean {
try {
if (!fs.existsSync(file)) return false;
const content = fs.readFileSync(file, 'utf-8');
return content.includes(CODEGRAPH_SECTION_START);
} catch {
return false;
}
}

function writeInstructionsEntry(loc: Location): WriteResult['files'][number] {
const file = agentsMdPath(loc);
const dir = path.dirname(file);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}

// Migrate an unmarked `## CodeGraph` section (e.g. from a manual
// paste before markers existed) into the marker-delimited format.
// Without this, a bare heading would cause detection to miss
// alreadyConfigured and install would append a duplicate section.
if (fs.existsSync(file)) {
const content = fs.readFileSync(file, 'utf-8');
if (!content.includes(CODEGRAPH_SECTION_START)) {
const headerMatch = content.match(/\n## CodeGraph\n/);
if (headerMatch && headerMatch.index !== undefined) {
const sectionStart = headerMatch.index;
const after = content.substring(sectionStart + 1);
const nextHeader = after.match(/\n## (?!#)/);
const sectionEnd = nextHeader && nextHeader.index !== undefined
? sectionStart + 1 + nextHeader.index
: content.length;
const merged =
content.substring(0, sectionStart) +
'\n' + PI_INSTRUCTIONS_TEMPLATE +
content.substring(sectionEnd);
fs.writeFileSync(file, merged, 'utf-8');
return { path: file, action: 'updated' };
}
}
}

const action = replaceOrAppendMarkedSection(
file,
PI_INSTRUCTIONS_TEMPLATE,
CODEGRAPH_SECTION_START,
CODEGRAPH_SECTION_END,
);

const mapped: 'created' | 'updated' | 'unchanged' =
action === 'created' ? 'created'
: action === 'unchanged' ? 'unchanged'
: 'updated';
return { path: file, action: mapped };
}

export const piTarget: AgentTarget = new PiTarget();
2 changes: 2 additions & 0 deletions src/installer/targets/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { hermesTarget } from './hermes';
import { geminiTarget } from './gemini';
import { antigravityTarget } from './antigravity';
import { kiroTarget } from './kiro';
import { piTarget } from './pi';

export const ALL_TARGETS: readonly AgentTarget[] = Object.freeze([
claudeTarget,
Expand All @@ -26,6 +27,7 @@ export const ALL_TARGETS: readonly AgentTarget[] = Object.freeze([
geminiTarget,
antigravityTarget,
kiroTarget,
piTarget,
]);

export function getTarget(id: string): AgentTarget | undefined {
Expand Down
2 changes: 1 addition & 1 deletion src/installer/targets/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' | 'gemini' | 'antigravity' | 'kiro';
export type TargetId = 'claude' | 'cursor' | 'codex' | 'opencode' | 'hermes' | 'gemini' | 'antigravity' | 'kiro' | 'pi' ;

/**
* Result of `target.detect(location)`.
Expand Down