@colbymchenry/codegraph 0.9.8 → 0.9.9

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
@@ -4,7 +4,7 @@
4
4
 
5
5
  ### Supercharge Claude Code, Cursor, Codex, OpenCode, Hermes Agent, Gemini, Antigravity, and Kiro with Semantic Code Intelligence
6
6
 
7
- **~25% cheaper · ~62% fewer tool calls · 100% local**
7
+ **~16% cheaper · ~58% fewer tool calls · 100% local**
8
8
 
9
9
  ### [Documentation & Website →](https://colbymchenry.github.io/codegraph/)
10
10
 
@@ -83,21 +83,21 @@ When Claude Code explores a codebase, it spawns **Explore agents** that scan fil
83
83
 
84
84
  ### Benchmark Results
85
85
 
86
- Tested across **7 real-world open-source codebases** spanning 7 languages, comparing an agent (Claude Code, headless) answering one architecture question **with** and **without** CodeGraph. Each cell is the savings at the **median of 4 runs per arm**. _Re-validated on Opus 4.8 (2026-05-29), on the build with per-symbol adaptive `codegraph_explore` sizing._
86
+ Tested across **7 real-world open-source codebases** spanning 7 languages, comparing an agent (Claude Code, headless) answering one architecture question **with** and **without** CodeGraph. Each cell is the savings at the **median of 4 runs per arm**. _Re-validated on Opus 4.8 (2026-06-02), on the current build (`codegraph_explore` as the primary tool)._
87
87
 
88
- > **Average: 25% cheaper · 57% fewer tokens · 23% faster · 62% fewer tool calls**
88
+ > **Average: 16% cheaper · 47% fewer tokens · 22% faster · 58% fewer tool calls**
89
89
 
90
90
  | Codebase | Language | Cost | Tokens | Time | Tool calls |
91
91
  |----------|----------|------|--------|------|------------|
92
- | **VS Code** | TypeScript · ~10k files | 33% cheaper | 70% fewer | 27% faster | 80% fewer |
93
- | **Excalidraw** | TypeScript · ~640 | 27% cheaper | 61% fewer | 26% faster | 70% fewer |
94
- | **Django** | Python · ~3k | 23% cheaper | 70% fewer | 28% faster | 77% fewer |
95
- | **Tokio** | Rust · ~790 | 35% cheaper | 70% fewer | 37% faster | 79% fewer |
96
- | **OkHttp** | Java · ~645 | 11% cheaper | 48% fewer | 26% faster | 70% fewer |
97
- | **Gin** | Go · ~110 | 15% cheaper | 35% fewer | 9% faster | 47% fewer |
98
- | **Alamofire** | Swift · ~110 | 28% cheaper | 46% fewer | 7% faster | 13% fewer |
92
+ | **VS Code** | TypeScript · ~10k files | 18% cheaper | 64% fewer | 11% faster | 81% fewer |
93
+ | **Excalidraw** | TypeScript · ~640 | even | 25% fewer | 27% faster | 40% fewer |
94
+ | **Django** | Python · ~3k | 8% cheaper | 60% fewer | 13% faster | 77% fewer |
95
+ | **Tokio** | Rust · ~790 | even | 38% fewer | 18% faster | 57% fewer |
96
+ | **OkHttp** | Java · ~645 | 25% cheaper | 54% fewer | 31% faster | 50% fewer |
97
+ | **Gin** | Go · ~110 | 19% cheaper | 23% fewer | 24% faster | 44% fewer |
98
+ | **Alamofire** | Swift · ~110 | 40% cheaper | 64% fewer | 33% faster | 58% fewer |
99
99
 
100
- CodeGraph cuts **cost, tokens, tool calls, and time on every repo** — across small, medium, and large codebases — and answers most of them with **zero file reads**, while the no-CodeGraph agent spends its budget on grep/find/Read discovery. `codegraph_explore` shows the answer in full — the mechanism plus the exact methods you asked about, even when they're buried in a multi-thousand-line file — while collapsing redundant interchangeable implementations to signatures, so the response is sized to the *answer* rather than the file count. The cost margin is narrowest on the smallest repos, where a modern model's native search is already cheap, but it stays solidly positive across the board.
100
+ CodeGraph cuts **tokens, tool calls, and wall-clock time on every repo** — across small, medium, and large codebases — and answers them with **near-zero file reads**, while the no-CodeGraph agent spends its budget on grep/find/Read discovery. `codegraph_explore` shows the answer in full — the mechanism plus the exact methods you asked about, even when they're buried in a multi-thousand-line file — while collapsing redundant interchangeable implementations to signatures, so the response is sized to the *answer* rather than the file count. **Cost stays flat-to-cheaper everywhere** largest on the small repos (Alamofire, OkHttp), roughly break-even on the most response-heavy ones (Excalidraw, Tokio), where CodeGraph trades the no-CodeGraph agent's many small grep/read round-trips for a few large, cache-heavy tool responses.
101
101
 
102
102
  <details>
103
103
  <summary><strong>Per-repo breakdown — WITH vs WITHOUT (median of 4)</strong></summary>
@@ -105,79 +105,79 @@ CodeGraph cuts **cost, tokens, tool calls, and time on every repo** — across s
105
105
  **VS Code** · ~10k files
106
106
  | Metric | WITH cg | WITHOUT cg | Δ |
107
107
  |---|---|---|---|
108
- | Time | 1m 37s | 2m 13s | 27% faster |
108
+ | Time | 1m 59s | 2m 13s | 11% faster |
109
109
  | File Reads | 0 | 9 | −9 |
110
110
  | Grep/Bash | 0 | 11 | −11 |
111
- | Tool calls | 4 | 21 | 80% fewer |
112
- | Total tokens | 545k | 1.79M | 70% fewer |
113
- | Cost | $0.55 | $0.83 | 33% cheaper |
111
+ | Tool calls | 4 | 21 | 81% fewer |
112
+ | Total tokens | 640k | 1.79M | 64% fewer |
113
+ | Cost | $0.68 | $0.83 | 18% cheaper |
114
114
 
115
115
  **Excalidraw** · ~640 files
116
116
  | Metric | WITH cg | WITHOUT cg | Δ |
117
117
  |---|---|---|---|
118
- | Time | 1m 34s | 2m 6s | 26% faster |
118
+ | Time | 1m 32s | 2m 6s | 27% faster |
119
119
  | File Reads | 0 | 7 | −7 |
120
- | Grep/Bash | 0 | 8 | −8 |
121
- | Tool calls | 5 | 15 | 70% fewer |
122
- | Total tokens | 651k | 1.69M | 61% fewer |
123
- | Cost | $0.57 | $0.78 | 27% cheaper |
120
+ | Grep/Bash | 1 | 8 | −7 |
121
+ | Tool calls | 9 | 15 | 40% fewer |
122
+ | Total tokens | 1.27M | 1.69M | 25% fewer |
123
+ | Cost | $0.78 | $0.78 | even |
124
124
 
125
125
  **Django** · ~3k files
126
126
  | Metric | WITH cg | WITHOUT cg | Δ |
127
127
  |---|---|---|---|
128
- | Time | 1m 25s | 1m 58s | 28% faster |
128
+ | Time | 1m 43s | 1m 58s | 13% faster |
129
129
  | File Reads | 0 | 9 | −9 |
130
130
  | Grep/Bash | 0 | 5 | −5 |
131
131
  | Tool calls | 3 | 13 | 77% fewer |
132
- | Total tokens | 419k | 1.41M | 70% fewer |
133
- | Cost | $0.48 | $0.62 | 23% cheaper |
132
+ | Total tokens | 559k | 1.41M | 60% fewer |
133
+ | Cost | $0.57 | $0.62 | 8% cheaper |
134
134
 
135
135
  **Tokio** · ~790 files
136
136
  | Metric | WITH cg | WITHOUT cg | Δ |
137
137
  |---|---|---|---|
138
- | Time | 1m 28s | 2m 20s | 37% faster |
138
+ | Time | 1m 55s | 2m 20s | 18% faster |
139
139
  | File Reads | 0 | 8 | −8 |
140
140
  | Grep/Bash | 0 | 6 | −6 |
141
- | Tool calls | 3 | 14 | 79% fewer |
142
- | Total tokens | 522k | 1.73M | 70% fewer |
143
- | Cost | $0.53 | $0.82 | 35% cheaper |
141
+ | Tool calls | 6 | 14 | 57% fewer |
142
+ | Total tokens | 1.08M | 1.73M | 38% fewer |
143
+ | Cost | $0.82 | $0.82 | even |
144
144
 
145
145
  **OkHttp** · ~645 files
146
146
  | Metric | WITH cg | WITHOUT cg | Δ |
147
147
  |---|---|---|---|
148
- | Time | 1m 6s | 1m 29s | 26% faster |
149
- | File Reads | 1 | 4 | −3 |
150
- | Grep/Bash | 0 | 6 | −6 |
151
- | Tool calls | 3 | 10 | 70% fewer |
152
- | Total tokens | 572k | 1.10M | 48% fewer |
153
- | Cost | $0.48 | $0.55 | 11% cheaper |
148
+ | Time | 1m 1s | 1m 29s | 31% faster |
149
+ | File Reads | 0 | 4 | −4 |
150
+ | Grep/Bash | 2 | 6 | −4 |
151
+ | Tool calls | 5 | 10 | 50% fewer |
152
+ | Total tokens | 502k | 1.10M | 54% fewer |
153
+ | Cost | $0.41 | $0.55 | 25% cheaper |
154
154
 
155
155
  **Gin** · ~110 files
156
156
  | Metric | WITH cg | WITHOUT cg | Δ |
157
157
  |---|---|---|---|
158
- | Time | 1m 28s | 1m 37s | 9% faster |
159
- | File Reads | 0 | 6 | −6 |
160
- | Grep/Bash | 0 | 2 | −2 |
161
- | Tool calls | 5 | 9 | 47% fewer |
162
- | Total tokens | 552k | 847k | 35% fewer |
163
- | Cost | $0.48 | $0.57 | 15% cheaper |
158
+ | Time | 1m 14s | 1m 37s | 24% faster |
159
+ | File Reads | 1 | 6 | −5 |
160
+ | Grep/Bash | 1 | 2 | −1 |
161
+ | Tool calls | 5 | 9 | 44% fewer |
162
+ | Total tokens | 651k | 847k | 23% fewer |
163
+ | Cost | $0.46 | $0.57 | 19% cheaper |
164
164
 
165
165
  **Alamofire** · ~110 files
166
166
  | Metric | WITH cg | WITHOUT cg | Δ |
167
167
  |---|---|---|---|
168
- | Time | 2m 11s | 2m 21s | 7% faster |
169
- | File Reads | 3 | 9 | −6 |
170
- | Grep/Bash | 2 | 4 | −2 |
171
- | Tool calls | 11 | 12 | 13% fewer |
172
- | Total tokens | 1.13M | 2.10M | 46% fewer |
173
- | Cost | $0.69 | $0.95 | 28% cheaper |
168
+ | Time | 1m 35s | 2m 21s | 33% faster |
169
+ | File Reads | 0 | 9 | −9 |
170
+ | Grep/Bash | 0 | 4 | −4 |
171
+ | Tool calls | 5 | 12 | 58% fewer |
172
+ | Total tokens | 766k | 2.10M | 64% fewer |
173
+ | Cost | $0.57 | $0.95 | 40% cheaper |
174
174
 
175
175
  </details>
176
176
 
177
177
  <details>
178
178
  <summary><strong>Full benchmark details</strong></summary>
179
179
 
180
- **Methodology.** Each arm is `claude -p` (Claude Opus 4.8) run headlessly against the repo with `--strict-mcp-config`: **WITH** = CodeGraph's MCP server enabled, **WITHOUT** = an empty MCP config. Built-in Read/Grep/Bash stay available to both. Same question per repo, **4 runs per arm, median reported**. Cost = the run's `total_cost_usd`; Tokens = total tokens processed (input incl. cached + output); Time = wall-clock; Tool calls = every tool invocation, including those inside any sub-agents the model spawns. Repos cloned at `--depth 1` and indexed by the same CodeGraph build that served them. Re-validated 2026-05-29 on the build with per-symbol adaptive `codegraph_explore` sizing. These numbers are lower than the prior Opus 4.7 validation — not a CodeGraph regression but a stronger native baseline: Opus 4.8 greps/reads efficiently on the main thread instead of fanning out into large Explore-subagent sweeps, so the no-CodeGraph arm is leaner than it used to be. Per-repo numbers move run-to-run with how hard the without-arm thrashes (the median-of-4 smooths it, but tails remain — e.g. Django's without-arm hit $2.71/14m one batch).
180
+ **Methodology.** Each arm is `claude -p` (Claude Opus 4.8) run headlessly against the repo with `--strict-mcp-config`: **WITH** = CodeGraph's MCP server enabled, **WITHOUT** = an empty MCP config. Built-in Read/Grep/Bash stay available to both. Same question per repo, **4 runs per arm, median reported**. Cost = the run's `total_cost_usd`; Tokens = total tokens processed (input incl. cached + output); Time = wall-clock; Tool calls = every tool invocation, including those inside any sub-agents the model spawns. Repos cloned at `--depth 1` and indexed by the same CodeGraph build that served them. Re-validated 2026-06-02 on the current build. These numbers are lower than the prior Opus 4.7 validation — not a CodeGraph regression but a stronger native baseline: Opus 4.8 greps/reads efficiently on the main thread instead of fanning out into large Explore-subagent sweeps, so the no-CodeGraph arm is leaner than it used to be. Per-repo numbers move run-to-run with how hard the without-arm thrashes (the median-of-4 smooths it, but tails remain — e.g. Django's without-arm hit $2.71/14m one batch).
181
181
 
182
182
  **Queries:**
183
183
  | Codebase | Query |
@@ -190,7 +190,7 @@ CodeGraph cuts **cost, tokens, tool calls, and time on every repo** — across s
190
190
  | Gin | "How does gin route requests through its middleware chain?" |
191
191
  | Alamofire | "How does Alamofire build, send, and validate a request?" |
192
192
 
193
- **Why CodeGraph wins:** with the index available, the agent answers directly — `codegraph_context` to map the area, then one `codegraph_explore` for the relevant source — and stops, usually with zero file reads. Without it, the agent spends most of its budget on discovery (find/ls/grep) before reading the right code. CodeGraph only helps when queried *directly*, so its instructions steer agents to answer directly rather than delegate exploration to file-reading sub-agents — otherwise a sub-agent reads files regardless and CodeGraph becomes overhead.
193
+ **Why CodeGraph wins:** with the index available, the agent answers directly — usually one `codegraph_explore` returns the relevant source — and stops, usually with zero file reads. Without it, the agent spends most of its budget on discovery (find/ls/grep) before reading the right code. CodeGraph only helps when queried *directly*, so its instructions steer agents to answer directly rather than delegate exploration to file-reading sub-agents — otherwise a sub-agent reads files regardless and CodeGraph becomes overhead.
194
194
 
195
195
  </details>
196
196
 
@@ -365,7 +365,7 @@ npm install -g @colbymchenry/codegraph
365
365
  "permissions": {
366
366
  "allow": [
367
367
  "mcp__codegraph__codegraph_search",
368
- "mcp__codegraph__codegraph_context",
368
+ "mcp__codegraph__codegraph_explore",
369
369
  "mcp__codegraph__codegraph_callers",
370
370
  "mcp__codegraph__codegraph_callees",
371
371
  "mcp__codegraph__codegraph_impact",
@@ -385,7 +385,7 @@ npm install -g @colbymchenry/codegraph
385
385
  CodeGraph's MCP server delivers its usage guidance to your agent **automatically**, in the MCP `initialize` response — there's no instructions file to manage and nothing is added to your `CLAUDE.md` / `AGENTS.md` / `GEMINI.md`. In short, it tells the agent to:
386
386
 
387
387
  - **Answer structural questions directly with CodeGraph** — it *is* the pre-built index, so a grep/read loop just repeats work it already did. Treat the returned source as already read.
388
- - **Pick the tool by intent:** `codegraph_context` to map an area, `codegraph_trace` for "how does X reach Y", `codegraph_explore` to survey several symbols, `codegraph_search` to find a symbol, `codegraph_callers`/`codegraph_callees` to walk call flow, `codegraph_impact` before editing, `codegraph_node` for one symbol's source.
388
+ - **Pick the tool by intent:** `codegraph_explore` for almost anything "how does X work", a flow/"how does X reach Y", or surveying an area (one call returns the relevant symbols' source grouped by file); `codegraph_search` to just locate a symbol; `codegraph_callers`/`codegraph_callees` to walk call flow; `codegraph_impact` before editing; `codegraph_node` for one specific symbol's full source (it returns every overload for an ambiguous name).
389
389
  - **Trust the results — don't re-verify with grep**, and check the staleness banner after edits.
390
390
  - If `.codegraph/` doesn't exist yet, offer to run `codegraph init -i`.
391
391
 
@@ -410,7 +410,7 @@ The exact text is `src/mcp/server-instructions.ts` — the single source of trut
410
410
  ┌───────────────────────────────────────────────────────────────────┐
411
411
  │ CodeGraph MCP Server │
412
412
  │ │
413
- context · trace · explore · callers · callees · impact
413
+ explore · search · callers · callees · impact · node
414
414
  │ │ │
415
415
  │ ▼ │
416
416
  │ SQLite knowledge graph │
@@ -441,7 +441,6 @@ codegraph sync [path] # Incremental update
441
441
  codegraph status [path] # Show statistics
442
442
  codegraph query <search> # Search symbols (--kind, --limit, --json)
443
443
  codegraph files [path] # Show file structure (--format, --filter, --max-depth, --json)
444
- codegraph context <task> # Build context for AI (--format, --max-nodes)
445
444
  codegraph callers <symbol> # Find what calls a function/method (--limit, --json)
446
445
  codegraph callees <symbol> # Find what a function/method calls (--limit, --json)
447
446
  codegraph impact <symbol> # Analyze what code is affected by changing a symbol (--depth, --json)
@@ -485,14 +484,12 @@ When running as an MCP server, CodeGraph exposes these tools to Claude Code:
485
484
 
486
485
  | Tool | Purpose |
487
486
  |------|---------|
487
+ | `codegraph_explore` | **Primary.** Answer almost any question in one call — "how does X work", a flow ("how does X reach Y"), or surveying an area — returning the relevant symbols' verbatim source grouped by file, plus a relationship map and blast radius. Surfaces dynamic-dispatch hops (callbacks, React re-render, interface→impl) grep can't follow. |
488
488
  | `codegraph_search` | Find symbols by name across the codebase |
489
- | `codegraph_context` | Build relevant code context for a task |
490
- | `codegraph_trace` | Trace the call path between two symbols ("how does X reach Y") in one call — each hop with its body inline, following dynamic-dispatch hops (callbacks, React re-render, interface→impl) that grep can't |
491
489
  | `codegraph_callers` | Find what calls a function |
492
490
  | `codegraph_callees` | Find what a function calls |
493
491
  | `codegraph_impact` | Analyze what code is affected by changing a symbol |
494
- | `codegraph_node` | Get details about a specific symbol (optionally with source code) |
495
- | `codegraph_explore` | Return source for several related symbols grouped by file, plus a relationship map, in one call |
492
+ | `codegraph_node` | Get one specific symbol's details + full source (returns every overload for an ambiguous name) |
496
493
  | `codegraph_files` | Get indexed file structure (faster than filesystem scanning) |
497
494
  | `codegraph_status` | Check index health and statistics |
498
495
 
@@ -7,6 +7,7 @@
7
7
  import { Subgraph, TaskContext, TaskInput, BuildContextOptions, FindRelevantContextOptions } from '../types';
8
8
  import { QueryBuilder } from '../db/queries';
9
9
  import { GraphTraverser } from '../graph';
10
+ export { LOW_CONFIDENCE_MARKER } from './markers';
10
11
  /**
11
12
  * Context Builder
12
13
  *
@@ -33,6 +34,14 @@ export declare class ContextBuilder {
33
34
  * @returns TaskContext (structured) or formatted string
34
35
  */
35
36
  buildContext(input: TaskInput, options?: BuildContextOptions): Promise<TaskContext | string>;
37
+ /**
38
+ * Honest handoff appended when retrieval confidence is low (the query matched
39
+ * mostly common words). Instead of the usual "this covers the surface" framing
40
+ * — which, when wrong, sends the agent off to Read/Grep — it admits the
41
+ * uncertainty and routes the agent to the precise tools (explore with real
42
+ * symbol names, search, or files to browse the closest areas we *did* surface).
43
+ */
44
+ private buildLowConfidenceNote;
36
45
  /**
37
46
  * Surface short call-paths among the symbols this context already found,
38
47
  * derived in-memory from the subgraph's `calls` edges (no extra queries).
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Stable sentinel strings shared between the context builder (which emits them
3
+ * into its markdown) and the MCP layer (which detects them to adjust framing).
4
+ *
5
+ * Intentionally a dependency-free leaf module: the MCP tool layer imports this
6
+ * to recognise a low-confidence response, and routing that recognition through
7
+ * the full context module would drag its dependencies onto the cold-start path.
8
+ * Keep this file import-free.
9
+ */
10
+ /**
11
+ * Heading that leads the honest low-confidence handoff appended to a context
12
+ * response when the query resolved only to weak/isolated matches. The MCP layer
13
+ * checks for it to suppress the contradictory "this is comprehensive, don't call
14
+ * explore" small-repo footer. Changing the text is a breaking sentinel change —
15
+ * both the emitter (`ContextBuilder`) and the detector (`src/mcp/tools.ts`)
16
+ * import this constant, so they stay in sync automatically.
17
+ */
18
+ export declare const LOW_CONFIDENCE_MARKER = "### \u26A0\uFE0F Low-confidence match";
19
+ //# sourceMappingURL=markers.d.ts.map
@@ -97,6 +97,32 @@ export declare class TreeSitterExtractor {
97
97
  * Extracts each declarator as a 'field' kind node inside the owning class.
98
98
  */
99
99
  private extractField;
100
+ /**
101
+ * Extract function-valued properties of an object literal as named function
102
+ * nodes (named by their property key). Shared by the two object-of-functions
103
+ * shapes in extractVariable: the object as a direct const value, and the
104
+ * object returned by a store-initializer call. Handles both `key: () => {}` /
105
+ * `key: function() {}` pairs and method shorthand `key() {}`.
106
+ */
107
+ private extractObjectLiteralFunctions;
108
+ /** Property-key text with surrounding quotes stripped (`'foo'` → `foo`). */
109
+ private objectKeyName;
110
+ /**
111
+ * Given a `call_expression` initializer (`create((set, get) => ({...}))`),
112
+ * find the object literal RETURNED by a function argument — descending through
113
+ * nested call_expression arguments so middleware wrappers are unwrapped
114
+ * (`create(persist((set, get) => ({...}), {...}))`, devtools, immer,
115
+ * subscribeWithSelector). Returns null when no such object is found — the
116
+ * common case for ordinary call initializers — so this stays cheap and silent
117
+ * rather than guessing. Keyed purely on AST shape; no library names.
118
+ */
119
+ private findInitializerReturnedObject;
120
+ /**
121
+ * The object literal a function expression returns — either the `=> ({...})`
122
+ * arrow form (a parenthesized_expression wrapping an object) or a
123
+ * `=> { return {...} }` block. Returns null for any other body shape.
124
+ */
125
+ private functionReturnedObject;
100
126
  /**
101
127
  * Extract a variable declaration (const, let, var, etc.)
102
128
  *
package/dist/index.d.ts CHANGED
@@ -227,6 +227,12 @@ export declare class CodeGraph {
227
227
  * Get all nodes of a specific kind
228
228
  */
229
229
  getNodesByKind(kind: Node['kind']): Node[];
230
+ /**
231
+ * Get ALL nodes with an exact name (direct index lookup, not FTS-ranked/capped).
232
+ * Used to enumerate every overload of a heavily-overloaded name so the specific
233
+ * definition the caller wants is never dropped below a search cut.
234
+ */
235
+ getNodesByName(name: string): Node[];
230
236
  /**
231
237
  * Search nodes by text
232
238
  */
@@ -235,7 +241,7 @@ export declare class CodeGraph {
235
241
  * Find the project's "primary route file" — the file with the densest
236
242
  * concentration of framework-emitted `route` nodes (≥3 routes, ≥30%
237
243
  * of all non-test routes). Used to inline the routing config in
238
- * `codegraph_context` responses on small realworld template repos
244
+ * `codegraph_explore` responses on small realworld template repos
239
245
  * (rails-realworld, laravel-realworld, drupal-admintoolbar, …) where
240
246
  * Glob+Read of `routes.rb`/`urls.py`/etc. otherwise beats codegraph.
241
247
  */
@@ -15,5 +15,5 @@
15
15
  * burn tokens. Reference only tools that exist on `main`; gate any
16
16
  * conditional tools behind feature checks if/when they ship.
17
17
  */
18
- export declare const SERVER_INSTRUCTIONS = "# Codegraph \u2014 code intelligence over an indexed knowledge graph\n\nCodegraph is a SQLite knowledge graph of every symbol, edge, and file\nin the workspace. Reads are sub-millisecond; the index lags writes by\nabout a second through the file watcher. Consult it BEFORE writing or\nediting code, not during.\n\n## Answer directly \u2014 don't delegate exploration\n\nFor \"how does X work\", architecture, trace, or where-is-X questions,\nanswer DIRECTLY using 2-3 codegraph calls: `codegraph_context` first,\nthen ONE `codegraph_explore` for the source of the symbols it surfaces.\nCodegraph IS the pre-built search index \u2014 so delegating the lookup to a\nseparate file-reading sub-task/agent, or running your own grep + read\nloop, repeats work codegraph already did and costs more for the same\nanswer. Reach for raw Read/Grep only to confirm a specific detail\ncodegraph didn't cover. A direct codegraph answer is typically a handful\nof calls; a grep/read exploration is dozens.\n\n## Tool selection by intent\n\n- **\"What is the symbol named X?\"** \u2192 `codegraph_search`\n- **\"What's the deal with this task / feature / area?\"** \u2192 `codegraph_context` (PRIMARY \u2014 composes search + node + callers + callees in one call)\n- **\"How does X reach/become Y? / trace the flow / the path from X to Y\"** \u2192 `codegraph_trace` (ONE call returns the whole call path, including dynamic-dispatch hops \u2014 callbacks, React re-render, JSX children \u2014 that grep can't follow)\n- **\"What calls this?\"** \u2192 `codegraph_callers`\n- **\"What does this call?\"** \u2192 `codegraph_callees`\n- **\"What would changing this break?\"** \u2192 `codegraph_impact`\n- **\"Show me this symbol's source / signature / docstring.\"** \u2192 `codegraph_node`\n- **\"Show me several related symbols' source / survey an area.\"** \u2192 `codegraph_explore` (ONE capped call; prefer over many codegraph_node/Read)\n- **\"What's in directory X?\"** \u2192 `codegraph_files`\n- **\"Is the index ready / what's its size?\"** \u2192 `codegraph_status`\n\n## Common chains\n\n- **Flow / \"how does X reach Y\"**: `codegraph_trace` from\u2192to FIRST \u2014 one call returns the entire path with dynamic-dispatch hops bridged. Then ONE `codegraph_explore` for the hop bodies if you need them. Do NOT reconstruct the path with `codegraph_search` + `codegraph_callers` \u2014 that's exactly what trace does in a single call.\n- **Onboarding**: `codegraph_context` first. If still unclear, `codegraph_explore` for breadth, then `codegraph_node` on specific symbols.\n- **Refactor planning**: `codegraph_search` \u2192 `codegraph_callers` \u2192 `codegraph_impact`. The blast-radius answer comes from impact, not from walking callers manually.\n- **Debugging a regression**: `codegraph_callers` of the suspected symbol; widen with `codegraph_impact` if an unexpected call appears.\n\n## Anti-patterns\n\n- **Trust codegraph's results \u2014 don't re-verify them with grep.** They come from a full AST parse; re-checking with grep is slower, less accurate, and wastes context.\n- **Don't grep first** when looking up a symbol by name \u2014 `codegraph_search` is faster and returns kind + location + signature.\n- **Don't chain `codegraph_search` + `codegraph_node`** when you just want context \u2014 `codegraph_context` is one round-trip.\n- **Don't loop `codegraph_node` over many symbols** \u2014 one `codegraph_explore` call returns them all grouped by file, while each separate call re-reads the whole context and costs far more. Use `codegraph_node` for a single symbol.\n- **After editing, check the staleness banner.** When a tool response starts with \"\u26A0\uFE0F Some files referenced below were edited since the last index sync\u2026\", the listed files are pending re-index \u2014 Read those specific files for accurate content. Every file NOT in that banner is fresh, so still trust codegraph. `codegraph_status` also lists pending files under \"Pending sync\".\n\n## Limitations\n\n- If a tool reports the project isn't initialized, `.codegraph/` doesn't exist yet \u2014 offer to run `codegraph init -i` to build the index.\n- Index lags file writes by ~1 second.\n- Cross-file resolution is best-effort name matching; ambiguous calls may return multiple candidates.\n- No live correctness validation \u2014 that's still the TypeScript compiler / test suite / linter's job. Codegraph supplements those with structural context they don't have.\n";
18
+ export declare const SERVER_INSTRUCTIONS = "# Codegraph \u2014 code intelligence over an indexed knowledge graph\n\nCodegraph is a SQLite knowledge graph of every symbol, edge, and file\nin the workspace. Reads are sub-millisecond; the index lags writes by\nabout a second through the file watcher. Consult it BEFORE writing or\nediting code, not during.\n\n## Answer directly \u2014 don't delegate exploration\n\nFor \"how does X work\", architecture, trace, or where-is-X questions,\nanswer DIRECTLY \u2014 usually with ONE `codegraph_explore` call.\n`codegraph_explore` takes either a natural-language question or a bag of\nsymbol/file names and returns the verbatim source of the relevant symbols\ngrouped by file, so it is Read-equivalent and most often the ONLY\ncodegraph call you need. Codegraph IS the pre-built search index \u2014 so\ndelegating the lookup to a separate file-reading sub-task/agent, or\nrunning your own grep + read loop, repeats work codegraph already did and\ncosts more for the same answer. Reach for raw Read/Grep only to confirm a\nspecific detail codegraph didn't cover. A direct codegraph answer is\ntypically one to a few calls; a grep/read exploration is dozens.\n\n## Tool selection by intent\n\n- **Almost any question \u2014 \"how does X work\", architecture, a bug, \"what/where is X\", or surveying an area** \u2192 `codegraph_explore` (PRIMARY \u2014 call FIRST; ONE capped call returns the verbatim source of the relevant symbols grouped by file; most often the ONLY call you need)\n- **\"How does X reach/become Y? / the flow / the path from X to Y\"** \u2192 `codegraph_explore`, naming the symbols that span the flow (e.g. `mutateElement renderScene`) \u2014 it surfaces the call path among them, including dynamic-dispatch hops (callbacks, React re-render, JSX children) grep can't follow\n- **\"What is the symbol named X?\" (just its location)** \u2192 `codegraph_search`\n- **\"What calls this?\" / \"What does this call?\" / \"What would changing this break?\"** \u2192 `codegraph_callers` / `codegraph_callees` / `codegraph_impact`\n- **One specific symbol's full source (esp. a body `codegraph_explore` trimmed), or an OVERLOADED name** \u2192 `codegraph_node` (with `includeCode`): for an ambiguous name it returns EVERY matching definition's body in one call, so you never Read a file to find the right overload\n- **\"What's in directory X?\"** \u2192 `codegraph_files`\n- **\"Is the index ready / what's its size?\"** \u2192 `codegraph_status`\n\n## Common chains\n\n- **Flow / \"how does X reach Y\"**: ONE `codegraph_explore` with the symbol names spanning the flow \u2014 it surfaces the call path among them (riding dynamic-dispatch hops) AND returns their source. No need to reconstruct the path with `codegraph_search` + `codegraph_callers`.\n- **Onboarding / understanding any area**: ONE `codegraph_explore` is usually the whole answer. Only follow up \u2014 `codegraph_node` for a specific symbol \u2014 if something is still unclear.\n- **Refactor planning**: `codegraph_search` \u2192 `codegraph_callers` \u2192 `codegraph_impact`. The blast-radius answer comes from impact, not from walking callers manually.\n- **Debugging a regression**: `codegraph_callers` of the suspected symbol; widen with `codegraph_impact` if an unexpected call appears.\n\n## Anti-patterns\n\n- **Trust codegraph's results \u2014 don't re-verify them with grep.** They come from a full AST parse; re-checking with grep is slower, less accurate, and wastes context.\n- **Don't grep first** when looking up a symbol by name \u2014 `codegraph_search` is faster and returns kind + location + signature.\n- **Don't chain `codegraph_search` + `codegraph_node`** to understand an area \u2014 ONE `codegraph_explore` returns the relevant symbols' source together in a single round-trip.\n- **Don't loop `codegraph_node` over many symbols** \u2014 one `codegraph_explore` call returns them all grouped by file, while each separate call re-reads the whole context and costs far more. Use `codegraph_node` for a single symbol.\n- **After editing, check the staleness banner.** When a tool response starts with \"\u26A0\uFE0F Some files referenced below were edited since the last index sync\u2026\", the listed files are pending re-index \u2014 Read those specific files for accurate content. Every file NOT in that banner is fresh, so still trust codegraph. `codegraph_status` also lists pending files under \"Pending sync\".\n\n## Limitations\n\n- If a tool reports the project isn't initialized, `.codegraph/` doesn't exist yet \u2014 offer to run `codegraph init -i` to build the index.\n- Index lags file writes by ~1 second.\n- Cross-file resolution is best-effort name matching; ambiguous calls may return multiple candidates.\n- No live correctness validation \u2014 that's still the TypeScript compiler / test suite / linter's job. Codegraph supplements those with structural context they don't have.\n";
19
19
  //# sourceMappingURL=server-instructions.d.ts.map
@@ -105,8 +105,9 @@ export interface ToolResult {
105
105
  /**
106
106
  * All CodeGraph MCP tools
107
107
  *
108
- * Designed for minimal context usage - use codegraph_context as the primary tool,
109
- * and only use other tools for targeted follow-up queries.
108
+ * Designed for minimal context usage - use codegraph_explore as the primary tool
109
+ * (one call usually answers the whole question), and only use other tools for
110
+ * targeted follow-up queries.
110
111
  *
111
112
  * All tools support cross-project queries via the optional `projectPath` parameter.
112
113
  */
@@ -158,7 +159,7 @@ export declare class ToolHandler {
158
159
  * Unset/empty → every tool is exposed. Lets an operator (or an A/B harness)
159
160
  * trim the tool surface without rebuilding the client config; the ablated
160
161
  * tool is then truly absent from ListTools rather than merely denied on call.
161
- * Matching is on the short form, so "trace" and "codegraph_trace" both work.
162
+ * Matching is on the short form, so "node" and "codegraph_node" both work.
162
163
  */
163
164
  private toolAllowlist;
164
165
  /** Whether a tool name passes the CODEGRAPH_MCP_TOOLS allowlist (if any). */
@@ -240,27 +241,6 @@ export declare class ToolHandler {
240
241
  * Handle codegraph_search
241
242
  */
242
243
  private handleSearch;
243
- /**
244
- * Handle codegraph_context
245
- */
246
- private handleContext;
247
- /**
248
- * Detect a flow-style task ("how does X reach Y", "trace the path from A to B")
249
- * and pre-run trace between the most likely endpoints, returning the trace
250
- * body to splice into the context response. Returns '' for non-flow queries
251
- * or when no plausible endpoint pair can be extracted.
252
- *
253
- * Conservative by design: only fires when the task has both a clear flow
254
- * keyword AND at least two distinct PascalCase / camelCase identifiers.
255
- * False positives waste a graph query; false negatives just fall back to
256
- * the agent calling trace itself (existing path-proximity wiring handles
257
- * disambiguation either way).
258
- */
259
- private maybeInlineFlowTrace;
260
- /**
261
- * Heuristic to detect if a query looks like a feature request
262
- */
263
- private looksLikeFeatureRequest;
264
244
  /**
265
245
  * Handle codegraph_callers
266
246
  */
@@ -273,18 +253,6 @@ export declare class ToolHandler {
273
253
  * Handle codegraph_impact
274
254
  */
275
255
  private handleImpact;
276
- /**
277
- * Handle codegraph_trace — shortest CALL PATH between two symbols.
278
- *
279
- * Exposes GraphTraverser.findPath: the chain of functions from `from` to `to`,
280
- * each hop annotated with file:line and the call-site line. This is the
281
- * capability grep/Read structurally cannot provide. When no static path
282
- * exists, the chain has almost certainly broken at dynamic dispatch
283
- * (callbacks, descriptors, metaclasses) — we say so and surface the start
284
- * symbol's outgoing calls so the agent bridges the one missing hop with
285
- * codegraph_node rather than blindly reading.
286
- */
287
- private handleTrace;
288
256
  /**
289
257
  * Describe a synthesized (dynamic-dispatch) edge for human output: how the
290
258
  * callback was wired up — the bridge static parsing can't see. Returns null
@@ -292,19 +260,6 @@ export declare class ToolHandler {
292
260
  * hop reads as "registered via onUpdate at App.tsx:3148", not a bare arrow.
293
261
  */
294
262
  private synthEdgeNote;
295
- /**
296
- * Read one trimmed source line at "relpath:line" (relative to the project
297
- * root). `cache` holds split file contents so a multi-hop trace reads each
298
- * file at most once. Returns null if the file/line can't be resolved.
299
- */
300
- private sourceLineAt;
301
- /**
302
- * Read a hop's body — filePath lines [startLine..endLine] — for inlining into
303
- * a trace, capped (lines + chars) so the whole path stays path-scoped even on
304
- * a 7-hop chain. Dedents to the body's own indentation and marks truncation.
305
- * Shares `cache` with sourceLineAt so each file is read at most once per trace.
306
- */
307
- private sourceRangeAt;
308
263
  /**
309
264
  * Flow-from-named-symbols: an agent's codegraph_explore query is a bag of
310
265
  * symbol names that usually spans the flow it's investigating (e.g.
@@ -320,6 +275,32 @@ export declare class ToolHandler {
320
275
  * dropping unrelated `OmsOrderService::list`.
321
276
  */
322
277
  private buildFlowFromNamedSymbols;
278
+ /**
279
+ * Compact "blast radius" for the entry symbols of an explore result: who
280
+ * depends on each (callers) and which test files cover it — LOCATIONS ONLY,
281
+ * no source, so the agent knows what to update / re-verify before editing
282
+ * without reaching for a separate impact call. Always-on, but skips symbols
283
+ * that have no dependents (nothing to warn about), and returns '' when none
284
+ * qualify so a leaf-only exploration stays clean.
285
+ */
286
+ private buildBlastRadiusSection;
287
+ /**
288
+ * Graph-connectivity relevance via Random-Walk-with-Restart (personalized
289
+ * PageRank) from the query's matched SEED nodes over the call/reference graph.
290
+ *
291
+ * This is the ranking signal text search (FTS/bm25) CANNOT provide, and it's
292
+ * codegraph's home turf: relevance by STRUCTURE, not words. A file whose
293
+ * symbols are call-connected to the matched cluster accrues walk mass and
294
+ * ranks high; a lone TEXT match — e.g. `LensSwitcher.swift` matched the word
295
+ * "switch" from `switchOrganization`, but calls none of `setUser`/`fetchUser`
296
+ * — gets only its own restart probability and ranks ~0. Immune to the
297
+ * tokenization trap that fools term matching, deterministic, no embeddings.
298
+ *
299
+ * Undirected adjacency (reachability both ways), restart α=0.25 to the seeds,
300
+ * power iteration to convergence. Bounded to the already-relevant subgraph, so
301
+ * it's a few hundred nodes × ~25 iterations — negligible cost.
302
+ */
303
+ private computeGraphRelevance;
323
304
  /**
324
305
  * Handle codegraph_explore — deep exploration in a single call
325
306
  *
@@ -336,6 +317,8 @@ export declare class ToolHandler {
336
317
  * Handle codegraph_node
337
318
  */
338
319
  private handleNode;
320
+ /** Render one symbol: details + (optional) body/outline + its caller/callee trail. */
321
+ private renderNodeSection;
339
322
  /**
340
323
  * Build the "trail" for a symbol: its direct callees (what it calls) and
341
324
  * callers (what calls it), each with file:line — so codegraph_node doubles as
@@ -393,7 +376,15 @@ export declare class ToolHandler {
393
376
  * Python — `stage_apply::run` matches a `run` in `stage_apply.rs`)
394
377
  */
395
378
  private matchesSymbol;
396
- private findSymbol;
379
+ /**
380
+ * Find ALL definitions matching a name, ranked, so codegraph_node can return
381
+ * every overload instead of guessing one (the wrong guess → a Read). Keepers
382
+ * rank before generated stubs (.pb.go etc.); stable within a group preserves
383
+ * FTS order. Returns [] when nothing matches; a qualified lookup that finds no
384
+ * exact match returns [] rather than a misleading fuzzy file hit (#173); a
385
+ * bare name with no exact match falls back to the single top fuzzy result.
386
+ */
387
+ private findSymbolMatches;
397
388
  /**
398
389
  * Find ALL symbols matching a name. Used by callers/callees/impact to aggregate
399
390
  * results across all matching symbols (e.g., multiple classes with an `execute` method).
@@ -415,7 +406,6 @@ export declare class ToolHandler {
415
406
  */
416
407
  private buildContainerOutline;
417
408
  private formatNodeDetails;
418
- private formatTaskContext;
419
409
  private textResult;
420
410
  private errorResult;
421
411
  }
@@ -50,4 +50,22 @@ export declare function nameMatchBonus(nodeName: string, query: string): number;
50
50
  * Functions and classes are typically more relevant than variables/imports
51
51
  */
52
52
  export declare function kindBonus(kind: Node['kind']): number;
53
+ /**
54
+ * Whether a query token looks like a code identifier the user deliberately typed
55
+ * (camelCase / PascalCase-with-internal-caps / snake_case / has a digit) rather
56
+ * than a plain dictionary word ("flat", "object", "screen").
57
+ *
58
+ * Used to decide whether an EXACT name match earns the "the user named this
59
+ * symbol" exemption from single-term dampening. A common English word that
60
+ * happens to exact-match an unrelated symbol — the query "flat object" matching
61
+ * a constant named `FLAT` — must NOT get that exemption, or the +exact-name
62
+ * bonus floats it to the top of a prose query on its own.
63
+ *
64
+ * Classifies the token AS THE USER TYPED IT, not the matched symbol's name:
65
+ * "flat" (lowercase, descriptive) is non-distinctive even though it matches
66
+ * `FLAT`. A leading-capital-only word ("Screen", "Zustand") is also treated as
67
+ * a plain word — sentence-start capitalization and proper nouns aren't reliable
68
+ * identifier signals.
69
+ */
70
+ export declare function isDistinctiveIdentifier(token: string): boolean;
53
71
  //# sourceMappingURL=query-utils.d.ts.map
package/dist/types.d.ts CHANGED
@@ -169,6 +169,14 @@ export interface Subgraph {
169
169
  edges: Edge[];
170
170
  /** Root node IDs (entry points) */
171
171
  roots: string[];
172
+ /**
173
+ * Retrieval confidence for context-style queries. `'low'` means the query
174
+ * resolved only to isolated common-word matches (no entry point corroborated
175
+ * by 2+ distinct query terms) — callers should surface an honest handoff to
176
+ * explore/trace rather than present the results as comprehensive. Undefined
177
+ * for graph traversals that don't run the search-ranking path.
178
+ */
179
+ confidence?: 'high' | 'low';
172
180
  }
173
181
  /**
174
182
  * Options for graph traversal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colbymchenry/codegraph",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "description": "Local-first code intelligence for AI agents (MCP). Self-contained — bundles its own runtime.",
5
5
  "bin": {
6
6
  "codegraph": "npm-shim.js"
@@ -15,12 +15,12 @@
15
15
  "./package.json": "./package.json"
16
16
  },
17
17
  "optionalDependencies": {
18
- "@colbymchenry/codegraph-darwin-arm64": "0.9.8",
19
- "@colbymchenry/codegraph-darwin-x64": "0.9.8",
20
- "@colbymchenry/codegraph-linux-arm64": "0.9.8",
21
- "@colbymchenry/codegraph-linux-x64": "0.9.8",
22
- "@colbymchenry/codegraph-win32-arm64": "0.9.8",
23
- "@colbymchenry/codegraph-win32-x64": "0.9.8"
18
+ "@colbymchenry/codegraph-darwin-arm64": "0.9.9",
19
+ "@colbymchenry/codegraph-darwin-x64": "0.9.9",
20
+ "@colbymchenry/codegraph-linux-arm64": "0.9.9",
21
+ "@colbymchenry/codegraph-linux-x64": "0.9.9",
22
+ "@colbymchenry/codegraph-win32-arm64": "0.9.9",
23
+ "@colbymchenry/codegraph-win32-x64": "0.9.9"
24
24
  },
25
25
  "files": [
26
26
  "npm-shim.js",