@henryqw/pi-codegraph 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,57 +1,49 @@
1
- # pi-codegraph
1
+ # @henryqw/pi-codegraph
2
2
 
3
- Get a separate CodeGraph index when you start Pi in a new Git worktree. The package also supplies a lazy CodeGraph MCP server through **pi-mcp-adapter**, including the explore tool. It does not implement an MCP client or edit your MCP configuration.
3
+ Get a separate [CodeGraph](https://github.com/colbymchenry/codegraph) index when you start Pi in a new Git worktree. Use CodeGraph's explore tool through pi-mcp-adapter from Pi.
4
4
 
5
5
  ## Install
6
6
 
7
- Requirements: Pi 0.87.x, Node.js 22.19 or newer, Git, the `codegraph` CLI on `PATH`, and **pi-mcp-adapter 2.36.x or newer within 2.x installed and enabled in Pi**.
8
-
9
- ```sh
7
+ ```bash
10
8
  npm install -g @colbymchenry/codegraph
11
9
  pi install npm:pi-mcp-adapter
12
10
  pi install npm:@henryqw/pi-codegraph
13
11
  ```
14
12
 
15
- Installing an npm peer dependency alone does not enable the adapter's Pi extension. Install both packages with Pi, then restart Pi or run `/reload`.
13
+ Requires `codegraph` CLI on `PATH`, and [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter).
14
+
15
+ ## Use
16
16
 
17
- Opt a repository in by building its first index in the **primary checkout**:
17
+ From the primary checkout, initialize CodeGraph once:
18
18
 
19
- ```sh
20
- cd /path/to/primary-checkout
19
+ ```bash
21
20
  codegraph init --yes
22
21
  ```
23
22
 
24
- After that, launch `pi` in any linked worktree. The extension initializes when Pi starts, not when Git creates the worktree.
23
+ Then launch `pi` in a linked worktree. The adapter server is `henryqw_pi-codegraph__codegraph`. It discovers tools lazily; other CodeGraph tools remain available through `mcp`.
25
24
 
26
- ## What happens
25
+ ## Flow
27
26
 
28
27
  - A missing worktree index is built only when the primary checkout already has `.codegraph/codegraph.db`.
29
- - Launching from a subdirectory still initializes the worktree root. Each worktree keeps its own `.codegraph`; databases are never copied or shared between branches.
30
- - Existing indexes are left alone. CodeGraph owns synchronization when its MCP server runs.
31
- - Non-Git directories and repositories without a primary index are not initialized. A first index always requires your explicit `codegraph init`.
32
- - Pi shows initialization or waiting status. Initialization has a ten-minute timeout; concurrent sessions wait up to five minutes for the same worktree's initializer.
33
- - The adapter server is `henryqw_pi-codegraph__codegraph`. It discovers tools lazily and exposes `codegraph_explore` directly without an extra package prefix. Other CodeGraph tools remain available through `mcp`. On a cold connection, CodeGraph may require an explicit `projectPath`; pass the worktree root when its tool schema requests it.
34
-
35
- The MCP definition uses the adapter's native `pi.mcp` package discovery. Install this **package**, not just its extension `.ts` file. Loading a single file with `pi -e` does not discover its MCP manifest. When using the whole local harness as a Pi package, its server is instead `henryqw_pi-harness__codegraph`; do not install both forms together.
36
-
37
- ## Failures and limits
28
+ - Initialization happens when Pi launches, not when Git creates the worktree.
29
+ - Each linked worktree keeps its own `.codegraph`; databases are never copied or shared between branches.
30
+ - Non-Git directories and repositories without a primary index are not initialized.
31
+ - When loaded, the extension reports whether the local index is `indexed`, `missing`, or `indexing…` through Pi's status channel. The `pi-footer` extension places a compact `CG` badge first on its third line and temporarily shows `● CG` during direct CodeGraph tool calls.
38
32
 
39
- At startup, the extension checks for a loaded adapter and runs `codegraph --version`, even when an index already exists. If either prerequisite is unavailable, Pi warns with the installation command for each missing prerequisite and skips setup without creating a lock. Headless sessions print the same warning to stderr. A broken or timed-out CLI check includes its failure details; if CodeGraph is already installed, check Pi's `PATH`. Restart Pi or run `/reload` after fixing the prerequisites.
33
+ ## State and storage
40
34
 
41
- The `codegraph` executable must be available to both Pi and its MCP child process. The package never installs either prerequisite automatically.
35
+ The extension relies on CodeGraph's own state — each worktree maintains its own `.codegraph/codegraph.db`. The extension never copies, shares, or modifies this database. Existing indexes are left alone; CodeGraph owns synchronization when its MCP server runs.
42
36
 
43
- Initialization uses an exclusive `pi-codegraph-init.lock` directory inside the worktree's Git metadata. Failed or interrupted initialization keeps this lock so a partial database is not accepted on the next launch. Errors include the exact worktree and lock paths. To recover:
37
+ ## Limits and recovery
44
38
 
45
- 1. Confirm no initializer is still running.
46
- 2. Inspect the failed index and run `codegraph index` in that worktree.
47
- 3. Only after indexing succeeds, remove the reported empty lock directory with `rmdir`, then run `/reload`.
39
+ At startup, the extension checks for a loaded adapter and runs `codegraph --version`. If either prerequisite is unavailable, Pi warns, reports `prerequisites missing`, and skips setup. Restart Pi or run `/reload` after fixing prerequisites.
48
40
 
49
- Do not remove an active lock. Existing indexes without an extension-owned lock are not health-checked. The lock coordinates this extension's sessions, not manual `codegraph init` commands or unrelated clients; avoid running those during initialization. A setup error does not remove files or change adapter configuration.
41
+ Initialization uses an exclusive `pi-codegraph-init.lock` in the worktree's Git metadata. Failed or interrupted initialization keeps the lock so a partial database is not accepted. To recover: remove the lock directory with `rmdir` only after `codegraph index` succeeds, then run `/reload`.
50
42
 
51
- Only Git worktree-root indexes and the default `.codegraph` directory are supported. An alternate `CODEGRAPH_DIR` is rejected. Nested monorepo indexes are not initialized automatically. The primary checkout must remain present and indexed for automatic opt-in detection.
43
+ The package never installs prerequisites automatically. The `codegraph` executable must be available to both Pi and its MCP child process. Only Git worktree-root indexes using the default `.codegraph` directory are supported; nested monorepo indexes are not initialized automatically. The primary checkout must remain indexed for automatic opt-in detection.
52
44
 
53
- The extension does not add ignore rules, delete indexes, or prune worktrees. Add `.codegraph/` to your own ignore rules if needed. Pi Subagent and Pi Orchestrator conservatively treat ignored files as retained work: an indexed worker worktree may require manual cleanup. This package does not weaken those data-loss safeguards.
45
+ Do not remove an active lock. Existing indexes without an extension-owned lock are not health-checked. The lock coordinates this extension's sessions, not manual `codegraph init` commands; avoid running those during initialization.
54
46
 
55
- ## Existing MCP configuration
47
+ The extension does not add ignore rules, delete indexes, or prune worktrees — add `.codegraph/` to your own ignore rules if needed. Pi Subagent conservatively treats ignored files as retained work: an indexed worker worktree may require manual cleanup.
56
48
 
57
49
  If you already configured a `codegraph` server manually, remove that entry after confirming the package server works. Keeping both can expose duplicate servers/tools. The extension does not change your MCP configuration.
@@ -5,6 +5,8 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
5
5
 
6
6
  const LOCK_WAIT_MS = 5 * 60_000;
7
7
  const INIT_TIMEOUT_MS = 10 * 60_000;
8
+ const WIDGET_KEY = "pi-codegraph";
9
+ const SUCCESS_TTL_MS = 5000;
8
10
 
9
11
  async function hasIndex(root: string): Promise<boolean> {
10
12
  try {
@@ -35,12 +37,12 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
35
37
  }
36
38
  if (prerequisites.length) {
37
39
  const message = `pi-codegraph: setup skipped.\n${prerequisites.join("\n")}\nThen restart Pi or /reload.`;
38
- ctx.ui.setStatus("pi-codegraph", "CodeGraph: prerequisites missing");
40
+ ctx.ui.setStatus("pi-codegraph", "pi-codegraph: prerequisites missing");
39
41
  if (ctx.hasUI) ctx.ui.notify(message, "warning");
40
42
  else console.warn(message);
41
43
  return;
42
44
  }
43
- ctx.ui.setStatus("pi-codegraph", undefined);
45
+ ctx.ui.setStatus("pi-codegraph", "pi-codegraph: missing");
44
46
  const rootResult = await pi.exec("git", ["rev-parse", "--show-toplevel"], { cwd: ctx.cwd, timeout: 10_000 });
45
47
  if (rootResult.code !== 0 || rootResult.killed) {
46
48
  if (!rootResult.killed && rootResult.stderr.includes("not a git repository")) return;
@@ -57,7 +59,8 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
57
59
  // Check the lock before the database: an in-progress/failed init can leave a partial DB.
58
60
  const recovery = `Inspect CodeGraph in ${root}. If no initializer is running, run codegraph index in that directory, then remove ${lock} with rmdir and /reload.`;
59
61
  const deadline = Date.now() + LOCK_WAIT_MS;
60
- ctx.ui.setStatus("pi-codegraph", "CodeGraph: checking index…");
62
+ ctx.ui.setStatus("pi-codegraph", "pi-codegraph: checking index…");
63
+ let indexed = false;
61
64
  try {
62
65
  while (true) {
63
66
  try {
@@ -66,27 +69,36 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
66
69
  } catch (error) {
67
70
  if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
68
71
  if (Date.now() >= deadline) throw new Error(`Timed out waiting for CodeGraph initialization. ${recovery}`);
69
- ctx.ui.setStatus("pi-codegraph", "CodeGraph: waiting for initialization…");
72
+ ctx.ui.setStatus("pi-codegraph", "pi-codegraph: indexing…");
70
73
  await delay(250);
71
74
  }
72
75
  }
73
76
  let attempted = false;
74
77
  let succeeded = false;
75
78
  try {
76
- if (await hasIndex(root)) return;
79
+ if (await hasIndex(root)) {
80
+ indexed = true;
81
+ return;
82
+ }
77
83
  const worktrees = await git(pi, root, ["worktree", "list", "--porcelain", "-z"]);
78
84
  const first = worktrees.split("\0", 1)[0];
79
85
  if (!first?.startsWith("worktree ")) throw new Error("Git returned an invalid primary worktree.");
80
86
  const primary = first.slice("worktree ".length);
81
87
  if (!primary || primary === root || !(await hasIndex(primary))) return;
82
- ctx.ui.setStatus("pi-codegraph", "CodeGraph: building worktree index…");
88
+ ctx.ui.setStatus("pi-codegraph", "pi-codegraph: indexing…");
83
89
  attempted = true;
84
90
  const result = await pi.exec("codegraph", ["init", "--yes", root], { cwd: root, timeout: INIT_TIMEOUT_MS });
85
91
  if (result.code !== 0 || result.killed || !(await hasIndex(root))) {
86
92
  throw new Error(`CodeGraph init failed (${result.killed ? "timed out or killed" : `exit ${result.code}`}): ${(result.stderr || result.stdout).trim().slice(-2000)}`);
87
93
  }
88
94
  succeeded = true;
89
- ctx.ui.notify("CodeGraph worktree index ready.", "info");
95
+ indexed = true;
96
+ if (ctx.hasUI) {
97
+ ctx.ui.setWidget(WIDGET_KEY, ["pi-codegraph: index ready"]);
98
+ setTimeout(() => ctx.ui.setWidget(WIDGET_KEY, undefined), SUCCESS_TTL_MS);
99
+ } else {
100
+ ctx.ui.notify("CodeGraph worktree index ready.", "info");
101
+ }
90
102
  } catch (error) {
91
103
  if (attempted) throw new Error(`${error instanceof Error ? error.message : String(error)}\n${recovery}`, { cause: error });
92
104
  throw error;
@@ -95,7 +107,7 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
95
107
  if (!attempted || succeeded) await rmdir(lock);
96
108
  }
97
109
  } finally {
98
- ctx.ui.setStatus("pi-codegraph", undefined);
110
+ ctx.ui.setStatus("pi-codegraph", indexed ? "pi-codegraph: indexed" : "pi-codegraph: missing");
99
111
  }
100
112
  }
101
113
 
@@ -105,7 +117,7 @@ export default function codegraphExtension(pi: ExtensionAPI): void {
105
117
  await initialize(pi, ctx);
106
118
  } catch (error) {
107
119
  const message = `pi-codegraph: ${error instanceof Error ? error.message : String(error)}`;
108
- ctx.ui.setStatus("pi-codegraph", "CodeGraph: setup failed");
120
+ ctx.ui.setStatus("pi-codegraph", "pi-codegraph: setup failed");
109
121
  if (ctx.hasUI) ctx.ui.notify(message, "error");
110
122
  else throw new Error(message, { cause: error });
111
123
  }
package/package.json CHANGED
@@ -1,12 +1,25 @@
1
1
  {
2
2
  "name": "@henryqw/pi-codegraph",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Initialize CodeGraph indexes in opted-in Git worktrees and expose CodeGraph through pi-mcp-adapter.",
5
- "keywords": ["pi-package", "pi", "codegraph", "mcp", "worktree"],
5
+ "keywords": [
6
+ "pi-package",
7
+ "pi",
8
+ "codegraph",
9
+ "mcp",
10
+ "worktree"
11
+ ],
6
12
  "type": "module",
7
- "engines": { "node": ">=22.19.0" },
13
+ "engines": {
14
+ "node": ">=22.19.0"
15
+ },
8
16
  "license": "MIT",
9
- "files": ["LICENSE", "extensions", "mcp.json", "README.md"],
17
+ "files": [
18
+ "LICENSE",
19
+ "extensions",
20
+ "mcp.json",
21
+ "README.md"
22
+ ],
10
23
  "scripts": {
11
24
  "test": "node --test test/*.test.ts",
12
25
  "typecheck": "tsc --noEmit --allowImportingTsExtensions --target ES2024 --module NodeNext --moduleResolution NodeNext --skipLibCheck extensions/codegraph.ts test/*.test.ts",
@@ -16,16 +29,24 @@
16
29
  "@earendil-works/pi-coding-agent": ">=0.87.0 <0.88.0",
17
30
  "pi-mcp-adapter": ">=2.36.0 <3.0.0"
18
31
  },
19
- "devDependencies": { "@earendil-works/pi-coding-agent": "0.87.0" },
32
+ "devDependencies": {
33
+ "@earendil-works/pi-coding-agent": "0.87.0"
34
+ },
20
35
  "repository": {
21
36
  "type": "git",
22
37
  "url": "git+https://github.com/HenryQW/pi-harness.git",
23
38
  "directory": "extensions/pi-codegraph"
24
39
  },
25
- "bugs": { "url": "https://github.com/HenryQW/pi-harness/issues" },
26
- "publishConfig": { "access": "public" },
40
+ "bugs": {
41
+ "url": "https://github.com/HenryQW/pi-harness/issues"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
27
46
  "pi": {
28
- "extensions": ["./extensions/codegraph.ts"],
47
+ "extensions": [
48
+ "./extensions/codegraph.ts"
49
+ ],
29
50
  "mcp": "./mcp.json"
30
51
  }
31
52
  }