@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 +52 -55
- package/dist/context/index.d.ts +9 -0
- package/dist/context/markers.d.ts +19 -0
- package/dist/extraction/tree-sitter.d.ts +26 -0
- package/dist/index.d.ts +7 -1
- package/dist/mcp/server-instructions.d.ts +1 -1
- package/dist/mcp/tools.d.ts +41 -51
- package/dist/search/query-utils.d.ts +18 -0
- package/dist/types.d.ts +8 -0
- package/package.json +7 -7
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
|
-
**~
|
|
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-
|
|
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:
|
|
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 |
|
|
93
|
-
| **Excalidraw** | TypeScript · ~640 |
|
|
94
|
-
| **Django** | Python · ~3k |
|
|
95
|
-
| **Tokio** | Rust · ~790 |
|
|
96
|
-
| **OkHttp** | Java · ~645 |
|
|
97
|
-
| **Gin** | Go · ~110 |
|
|
98
|
-
| **Alamofire** | Swift · ~110 |
|
|
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 **
|
|
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
|
|
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 |
|
|
112
|
-
| Total tokens |
|
|
113
|
-
| Cost | $0.
|
|
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
|
|
118
|
+
| Time | 1m 32s | 2m 6s | 27% faster |
|
|
119
119
|
| File Reads | 0 | 7 | −7 |
|
|
120
|
-
| Grep/Bash |
|
|
121
|
-
| Tool calls |
|
|
122
|
-
| Total tokens |
|
|
123
|
-
| Cost | $0.
|
|
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
|
|
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 |
|
|
133
|
-
| Cost | $0.
|
|
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
|
|
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 |
|
|
142
|
-
| Total tokens |
|
|
143
|
-
| Cost | $0.
|
|
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
|
|
149
|
-
| File Reads |
|
|
150
|
-
| Grep/Bash |
|
|
151
|
-
| Tool calls |
|
|
152
|
-
| Total tokens |
|
|
153
|
-
| Cost | $0.
|
|
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
|
|
159
|
-
| File Reads |
|
|
160
|
-
| Grep/Bash |
|
|
161
|
-
| Tool calls | 5 | 9 |
|
|
162
|
-
| Total tokens |
|
|
163
|
-
| Cost | $0.
|
|
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 |
|
|
169
|
-
| File Reads |
|
|
170
|
-
| Grep/Bash |
|
|
171
|
-
| Tool calls |
|
|
172
|
-
| Total tokens |
|
|
173
|
-
| Cost | $0.
|
|
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-
|
|
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 —
|
|
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
|
-
"
|
|
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:** `
|
|
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
|
-
│
|
|
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
|
|
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
|
|
package/dist/context/index.d.ts
CHANGED
|
@@ -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
|
-
* `
|
|
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
|
|
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
|
package/dist/mcp/tools.d.ts
CHANGED
|
@@ -105,8 +105,9 @@ export interface ToolResult {
|
|
|
105
105
|
/**
|
|
106
106
|
* All CodeGraph MCP tools
|
|
107
107
|
*
|
|
108
|
-
* Designed for minimal context usage - use
|
|
109
|
-
* and only use other tools for
|
|
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 "
|
|
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
|
-
|
|
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.
|
|
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.
|
|
19
|
-
"@colbymchenry/codegraph-darwin-x64": "0.9.
|
|
20
|
-
"@colbymchenry/codegraph-linux-arm64": "0.9.
|
|
21
|
-
"@colbymchenry/codegraph-linux-x64": "0.9.
|
|
22
|
-
"@colbymchenry/codegraph-win32-arm64": "0.9.
|
|
23
|
-
"@colbymchenry/codegraph-win32-x64": "0.9.
|
|
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",
|