Skip to content
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,18 @@ codegraph graph --root . ./src --dot --output graph.dot

## Agent setup

Using a skill-aware agent? Install the bundled skill so repo navigation, semantic references, dependency tracing, and PR impact questions route to Codegraph automatically. The installer uses safe per-agent defaults and creates the target skills directory as needed:
Using a local agent client? The top-level installer configures Codegraph-owned MCP entries, bundled skill payloads, and marker files for supported clients, while preserving existing user config:

```bash
codegraph install --target codex,claude --dry-run
codegraph install --target codex,claude --yes
codegraph install --print-config codex
codegraph uninstall --target codex --yes
```

Supported installer targets are `codex`, `claude`, `cursor`, `gemini`, `opencode`, and `agents`. Writes require `--yes`; `--dry-run` previews files, and `uninstall` removes only Codegraph-owned marker blocks, marker files, exact bundled skill payloads, or exact installer-owned MCP entries.

Using a skill-aware agent only? Install the bundled skill directly so repo navigation, semantic references, dependency tracing, and PR impact questions route to Codegraph automatically:

```bash
# Codex CLI: ${CODEX_HOME:-~/.codex}/skills/codegraph
Expand All @@ -340,7 +351,7 @@ codegraph skill install --agent gemini
codegraph skill install --agent opencode
```

For a custom location, use `codegraph skill install --target <path>/skills/codegraph`; the target must end with `skills/codegraph`, and the installer creates the directory as needed. Cursor CLI now supports native skills directories too, so `.cursor/skills/codegraph` works alongside the universal `~/.agents/skills/codegraph` location. To inspect the packaged skill paths and target health, run `codegraph skill doctor`.
For a custom skill location, use `codegraph skill install --target <path>/skills/codegraph`; the target must end with `skills/codegraph`, and the installer creates the directory as needed. Cursor CLI supports native skills directories too, so `.cursor/skills/codegraph` works alongside the universal `~/.agents/skills/codegraph` location. To inspect the packaged skill paths and target health, run `codegraph skill doctor`.

## Using as a library

Expand Down
2 changes: 2 additions & 0 deletions codegraph-skill/codegraph/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ Then choose the smallest useful follow-up:
- impact: `codegraph impact --base HEAD --head WORKTREE --pretty`
- review: `codegraph review --base HEAD --head WORKTREE --summary`
- drift: `codegraph drift ./src --base origin/main --head HEAD --pretty --graph-edges summary --public-api removals`
- installer: `codegraph install --target codex,claude --dry-run`

Use `--root` to define the project boundary for config lookup, cache scope, path confinement, and output normalization.
For `orient`, `drift`, and positional graph commands, positional paths are include roots inside that project.
Use `codegraph install --target <ids> --yes` to configure supported local agent clients with MCP entries, bundled skill payloads, and marker files. Use `--dry-run` or `--print-config <target>` first; uninstall removes only Codegraph-owned marker blocks, marker files, exact bundled skill payloads, or exact installer-owned MCP entries.

## Output Choice

Expand Down
12 changes: 12 additions & 0 deletions docs/agent-workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ codegraph drift ./src --base origin/main --head HEAD --compact-json

Drift compares structural signals over time: dependency cycles, hotspots, unresolved imports, API surface changes, duplicate group counts, and graph edges. It is review and CI evidence, not runtime validation or compiler diagnostics. Use compact JSON for CI or agent handoff, and use graph-edge/API filters to keep human review output bounded.

## Agent client installer

Use `install` when setting up Codegraph for supported local agent clients:

```bash
codegraph install --target codex,claude --dry-run
codegraph install --target codex,claude --yes
codegraph uninstall --target codex --yes
```

Writes require `--yes`, and `--print-config <target>` prints the MCP snippet without touching disk. `uninstall` removes only Codegraph-owned marker blocks, marker files, exact bundled skill payloads, or exact installer-owned MCP entries.

## MCP server

Use `codegraph mcp serve --root . --stdio` when an agent can spawn and own a stdio MCP subprocess.
Expand Down
14 changes: 14 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ codegraph mcp serve --root . --stdio --warmup
codegraph mcp serve --root . --port 7331 --warmup-symbols
codegraph mcp --help

# Install or preview agent client integration
codegraph install --target codex,claude --dry-run
codegraph install --target codex,claude --yes
codegraph install --print-config codex
codegraph uninstall --target codex --yes
codegraph install --help

# Chunk a file for LLM processing
codegraph chunk src/utils.js

Expand Down Expand Up @@ -264,6 +271,13 @@ For SQL, prefer handles or schema-qualified names when basenames may be ambiguou
- Use `--force` to replace recognizable stale Codegraph artifacts while preserving unrelated files.
- Artifact contents exclude their own output directory and linked outside-root files.

#### Agent client installer

- `install` configures Codegraph-owned MCP entries, bundled skill payloads, and marker files for supported local agent clients: `codex`, `claude`, `cursor`, `gemini`, `opencode`, and `agents`.
- Writes require `--yes`; use `--detect` to list discovered targets, `--dry-run` to preview changed file paths and actions, or `--print-config <target>` to print a copyable MCP snippet without writing.
- `uninstall` removes only Codegraph-owned marker blocks, marker files, exact bundled skill payloads, or exact installer-owned MCP entries.
- `skill install` remains the lower-level primitive when you only want to copy the bundled skill directly without MCP config.

#### MCP server

- `mcp serve` exposes explore, navigation, search, impact, review, SQLite query, session refresh, and artifact-build tools.
Expand Down
13 changes: 13 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ Explicit CLI, library, and tool `native` options take precedence over `CODEGRAPH

Reduced mode preserves graph-only and regex-backed recovery where available; it does not provide a non-native Tree-sitter parser.

## Agent client setup

After installing the CLI, `codegraph install` can configure Codegraph-owned MCP entries, bundled skill payloads, and marker files for supported agent clients:

```bash
codegraph install --target codex,claude --dry-run
codegraph install --target codex,claude --yes
codegraph install --print-config codex
```

Supported targets are `codex`, `claude`, `cursor`, `gemini`, `opencode`, and `agents`. Writes require `--yes`; `--dry-run` reports the files that would change, and `uninstall` removes only Codegraph-owned marker blocks, marker files, exact bundled skill payloads, or exact installer-owned MCP entries.
The lower-level `codegraph skill install --agent <name>` command remains available when you only want to copy the bundled skill.

## Next steps

- For CLI commands and examples, see [docs/cli.md](./cli.md).
Expand Down
12 changes: 12 additions & 0 deletions docs/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ Tool schemas are flat JSON objects for broad client compatibility; argument comb
- `query_sqlite` rejects mutating SQL, recursive queries, synthetic payload functions, and stale artifact queries it cannot refresh safely.
- SQLite responses are row- and byte-bounded.

## Installer

Use `codegraph install` to configure supported local clients without manually editing MCP config files:

```bash
codegraph install --target codex,claude --dry-run
codegraph install --target codex,claude --yes
codegraph install --print-config codex
```

The installer writes only Codegraph-owned marker blocks, marker files, bundled skill payloads, or exact installer-owned MCP entries. `codegraph uninstall --target <ids> --yes` removes only those owned entries.

## Client Configuration Examples

Use `command: "codegraph"` when the CLI is on `PATH`. Use the full executable path when the client runs with a narrower environment.
Expand Down
15 changes: 15 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { handleGraphQueryCommand } from "./cli/graphQueries.js";
import { handleGrepCommand } from "./cli/grep.js";
import { CLI_HELP_TEXT, helpTextForCommand, isKnownCliCommand } from "./cli/help.js";
import { handleImpactCommand } from "./cli/impact.js";
import { handleInstallerCommand } from "./cli/install.js";
import { handleIndexCommand } from "./cli/index.js";
import { handleHotspotsCommand, handleInspectCommand } from "./cli/inspect.js";
import { handleOrientCommand } from "./cli/orient.js";
Expand Down Expand Up @@ -285,6 +286,20 @@ async function runCliWithActiveRuntime(rawArgs: string[]) {
return;
}

if (cmd === "install" || cmd === "uninstall") {
await handleInstallerCommand({
command: cmd,
positionals: parsed.positionals,
getOpt,
hasFlag,
writeJSONLine,
writeStdoutLine,
writeStderrLine,
exit: exitCli,
});
return;
}

if (cmd === "sql") {
const { handleSqlCommand } = await import("./cli/sql.js");
await handleSqlCommand({
Expand Down
32 changes: 30 additions & 2 deletions src/cli/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Commands:
sql Query a SQLite graph export read-only
chunk Chunk file for embeddings
doctor Inspect backend/runtime state and local graph artifacts
install Configure Codegraph MCP and skill integration for agent clients
uninstall Remove Codegraph-owned installer configuration
skill Install or inspect the bundled agent skill
version Print the installed codegraph version

Expand All @@ -56,8 +58,8 @@ Build Options:
--cache-verify Re-stat cached files before trusting disk cache entries
--progress Show progress tracking during indexing

Output Options:
--json Output as JSON (default)
Analysis Output Options:
--json Output analysis commands as JSON (default where supported)
--mermaid Output as Mermaid diagram
--dot Output as DOT graph
--sqlite <path> Write to SQLite database
Expand Down Expand Up @@ -85,6 +87,9 @@ Examples:
codegraph packet get file:src%2Fcli.ts --json
codegraph artifact build --root . --out codegraph-out --json
codegraph mcp serve --root . --stdio
codegraph install --target codex,claude --yes
codegraph install --print-config codex
codegraph uninstall --target codex --yes
codegraph inspect ./src --limit 20
codegraph duplicates ./src --min-confidence medium
codegraph graph ./src
Expand Down Expand Up @@ -124,6 +129,7 @@ const knownCliCommands = new Set([
"hotspots",
"impact",
"index",
"install",
"inspect",
"mcp",
"orient",
Expand All @@ -137,12 +143,32 @@ const knownCliCommands = new Set([
"sql",
"unresolved",
"version",
"uninstall",
]);

export function isKnownCliCommand(command: string): boolean {
return knownCliCommands.has(command);
}

export const INSTALL_HELP_TEXT = `codegraph install - Configure Codegraph for supported agent clients

Usage: codegraph install [target] [--target <codex,claude,cursor,gemini,opencode,agents>] [--yes | --dry-run] [--print-config <target>] [--detect]

Targets:
codex, claude, cursor, gemini, opencode, agents

Safety:
Writes require --yes. Use --dry-run to preview changed files or --print-config <target> to print the MCP snippet.
`;

export const UNINSTALL_HELP_TEXT = `codegraph uninstall - Remove Codegraph-owned installer configuration

Usage: codegraph uninstall [target] [--target <codex,claude,cursor,gemini,opencode,agents>] [--yes | --dry-run] [--detect]

Safety:
Removes only Codegraph-owned marker blocks, marker files, exact bundled skill payloads, or exact installer-owned MCP entries.
`;

export const EXPLORE_HELP_TEXT = `codegraph explore - Answer a broad repo question with bounded repo context

Usage: codegraph explore "<query>" [--root <path>] [--limit <n>] [--max-packets <n>] [--max-paths <n>] [--no-source] [--json | --pretty]
Expand Down Expand Up @@ -361,6 +387,8 @@ export function helpTextForCommand(command: string, positionals: readonly string
if (command === "orient") return ORIENT_HELP_TEXT;
if (command === "packet") return PACKET_HELP_TEXT;
if (command === "explain") return EXPLAIN_HELP_TEXT;
if (command === "install") return INSTALL_HELP_TEXT;
if (command === "uninstall") return UNINSTALL_HELP_TEXT;
if (command === "drift") return DRIFT_HELP_TEXT;
if (command === "duplicates") return DUPLICATES_HELP_TEXT;
if (command === "artifact") return ARTIFACT_HELP_TEXT;
Expand Down
103 changes: 103 additions & 0 deletions src/cli/install.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {
detectInstallTargets,
installCodegraphTargets,
parseInstallTargetId,
parseInstallTargetIds,
printInstallConfig,
uninstallCodegraphTargets,
type InstallTargetId,
} from "../installer/registry.js";

export type InstallerCommandContext = {
command: "install" | "uninstall";
positionals: string[];
getOpt: (name: string) => string | undefined;
hasFlag: (name: string) => boolean;
writeJSONLine: (value: unknown) => void;
writeStdoutLine: (message: string) => void;
writeStderrLine: (message: string) => void;
exit: (code: number) => never;
};

export async function handleInstallerCommand(context: InstallerCommandContext): Promise<void> {
const printConfigTarget = context.getOpt("--print-config");

if (printConfigTarget !== undefined) {
assertPrintConfigIsExclusive(context);
const targetId = parseInstallerTargetOrExit(context, printConfigTarget);
context.writeStdoutLine(printInstallConfig({ targetId }).trimEnd());
return;
}

const targetIds = parseInstallerTargets(context);
const options = {
...(targetIds !== undefined ? { targetIds } : {}),
yes: context.hasFlag("--yes"),
dryRun: context.hasFlag("--dry-run"),
};

if (context.hasFlag("--detect")) {
context.writeJSONLine({ targets: await detectInstallTargets(options) });
return;
}

if (context.command === "install") {
context.writeJSONLine(await installCodegraphTargets(options));
return;
Comment on lines +39 to +46

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 3697365. Installer commands no longer advertise or accept --json; help/docs/skill guidance now state installer reporting is text-only while analysis commands keep JSON output.

}

context.writeJSONLine(await uninstallCodegraphTargets(options));
}

function parseInstallerTargets(context: InstallerCommandContext): InstallTargetId[] | undefined {
const targetOpt = context.getOpt("--target");
const positionalTarget = context.positionals[0];
if (context.positionals.length > 1) {
context.writeStderrLine(`Unexpected positional argument for ${context.command}: ${context.positionals[1]!}`);
context.exit(2);
}
if (targetOpt !== undefined && positionalTarget !== undefined) {
failUsage(context, "Use either --target or a positional target, not both.");
}
return parseInstallerTargetIdsOrExit(context, targetOpt ?? positionalTarget);
}

function assertPrintConfigIsExclusive(context: InstallerCommandContext): void {
const conflicts: string[] = [];
if (context.getOpt("--target") !== undefined) conflicts.push("--target");
if (context.positionals.length) conflicts.push("positional targets");
if (context.hasFlag("--detect")) conflicts.push("--detect");
if (context.hasFlag("--yes")) conflicts.push("--yes");
if (context.hasFlag("--dry-run")) conflicts.push("--dry-run");
if (!conflicts.length) return;
failUsage(context, `--print-config cannot be combined with ${conflicts.join(", ")}.`);
}

function parseInstallerTargetOrExit(context: InstallerCommandContext, value: string): InstallTargetId {
try {
return parseInstallTargetId(value);
} catch (error) {
failUsage(context, errorMessage(error));
}
}

function parseInstallerTargetIdsOrExit(
context: InstallerCommandContext,
value: string | undefined,
): InstallTargetId[] | undefined {
try {
return parseInstallTargetIds(value);
} catch (error) {
failUsage(context, errorMessage(error));
}
}

function failUsage(context: InstallerCommandContext, message: string): never {
context.writeStderrLine(message);
context.exit(2);
}

function errorMessage(error: unknown): string {
if (error instanceof Error) return error.message;
return String(error);
}
18 changes: 18 additions & 0 deletions src/cli/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const CLI_VALUE_OPTIONS = new Set<string>([
"--duplicates",
"--agent",
"--target",
"--print-config",
"--limit",
"--fail-on",
"--hotspot-jump-threshold",
Expand Down Expand Up @@ -360,6 +361,23 @@ const CLI_COMMAND_SCHEMAS = new Map<string, CliCommandSchema>([
),
],
["index", graphCommandSchema({ kind: "any" })],
[
"install",
commandSchema(["--detect", "--dry-run", "--yes"], ["--print-config", "--target"], {
kind: "max",
max: 1,
usage:
"Usage: codegraph install [target] [--target <ids>] [--detect] [--yes | --dry-run] [--print-config <target>]",
}),
],
[
"uninstall",
commandSchema(["--detect", "--dry-run", "--yes"], ["--target"], {
kind: "max",
max: 1,
usage: "Usage: codegraph uninstall [target] [--target <ids>] [--detect] [--yes | --dry-run]",
}),
],
[
"inspect",
commandSchema([...SHARED_BUILD_FLAGS, ...JSON_OUTPUT_FLAGS], [...SHARED_BUILD_OPTIONS, "--limit"], { kind: "any" }),
Expand Down
3 changes: 2 additions & 1 deletion src/cli/skill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export function getSkillTargetDirForAgent(
return path.join(homeDir, ".gemini", "skills", "codegraph");
}
if (agent === "opencode") {
return path.join(homeDir, ".config", "opencode", "skills", "codegraph");
const configHome = env.XDG_CONFIG_HOME?.trim() || path.join(homeDir, ".config");
return path.join(configHome, "opencode", "skills", "codegraph");
}
const codexHome = env.CODEX_HOME?.trim();
if (codexHome) {
Expand Down
Loading