Implements the design from `docs/design/mixed-ios-and-react-native-bridging.md`.
Closes the cross-language flow gap so `trace` / `callers` / `callees` / `impact` connect end-to-end across language boundaries in real iOS, React Native, and Expo codebases.
## Bridges shipped
| Boundary | Mechanism | Real-codebase validation |
|---|---|---|
| **Swift ↔ Objective-C** | Resolver applying Apple's @objc auto-bridging name math + Cocoa preposition prefixes | Charts (S, 269) · realm-swift (M, 369) · wikipedia-ios (L, 1734) |
| **React Native legacy bridge** | Resolver parsing `RCT_EXPORT_MODULE` / `RCT_EXPORT_METHOD` / `RCT_REMAP_METHOD` (ObjC) + `@ReactMethod` (Java/Kotlin) | AsyncStorage (S, ~60) · react-native-svg (M, ~700) · react-native-firebase (L, ~1100) |
| **React Native TurboModules** | Resolver treating `Native<X>.ts` spec interface as ground truth | via RNSvg + RNFirebase subsets |
| **Native → JS events** | Synthesizer matching native `sendEventWithName:`/`emit(...)` to JS `addListener('e', handler)` keyed by literal event name; falls back to enclosing constant/variable for wrapper-API parameter handlers | RNGeolocation (S) · RNFirebase (L) |
| **Expo Modules** | Framework extract synthesizes `method` nodes from Swift/Kotlin `Module { Name("X"); Function("y") { ... } }` DSL | expo-haptics (S, 14) · expo-camera (M, 72) · ExpoSweep (L, 332, 7 packages) |
| **Fabric + legacy Paper view components** | Extract `component` + `property` nodes from Codegen `codegenNativeComponent<Props>('Name', ...)` specs AND legacy `RCT_EXPORT_VIEW_PROPERTY` / `@ReactProp` macros, then synthesize component → native class by name+suffix convention | react-native-segmented-control (S, legacy) · react-native-screens (M, Codegen) · react-native-skia (L, hybrid monorepo) |
## Bug fixes surfaced along the way
- `tree-sitter.ts` message_expression — multi-keyword ObjC call sites now reconstruct `a🅱️` selectors so they resolve to multi-part method definitions (gap discovered post-#165; 0 → 84 call edges to `GET:parameters:...` style methods on AFNetworking).
- `src/index.ts` resolver lifecycle — `indexAll()` now re-initializes the resolver after extraction so framework `detect()` sees the populated index. Pre-existing latent bug that affected UIKit and SwiftUI resolvers too.
- `src/extraction/index.ts` `buildDetectionContext` — added `listDirectories` so framework detect() can probe monorepo subpackages uniformly (fix needed for react-native-skia detection).
## Regression check on 5 control repos
| Repo | Result |
|---|---|
| Express (small JS) | ✅ unchanged — 266 routes, express framework detected |
| Excalidraw (medium TS/React) | ✅ 9284 nodes (CLAUDE.md baseline ~9290); canonical `trace(mutateElement, renderStaticScene)` returns the flow |
| Django realworld (Python) | ✅ django framework detected, 16 routes |
| Spring petclinic (Java) | ✅ spring framework detected, 17 routes |
| Texture (pure ObjC, large) | ✅ exactly matches #165 baseline: 4702 methods, 894 classes, 808/808 file coverage, 913 multi-keyword selectors, 55 protocols, 1036 properties |
## Tests
928 passing (+87 net new bridge tests across the 5 channels); 2 pre-existing skips. The mcp-staleness-banner / watcher parallel flakiness is unchanged by this work (different test fails each run, all pass in isolation; pre-existing on main).
## Documentation
- README: new 'Mixed iOS / React Native / Expo bridging' section with the per-boundary table and validation-corpus links.
- CHANGELOG `[Unreleased]`: full entry per bridge with measurements.
- `docs/design/mixed-ios-and-react-native-bridging.md`: the design doc (§8 measurements filled in across §8a-§8g).
- `docs/design/dynamic-dispatch-coverage-playbook.md` §6 coverage matrix: six new rows.
- `.claude/skills/agent-eval/corpus.json`: four new sections covering 15 real GitHub repos for the eval harness.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
563 lines
30 KiB
Markdown
563 lines
30 KiB
Markdown
<div align="center">
|
|
|
|
# CodeGraph
|
|
|
|
### Supercharge Claude Code, Cursor, Codex, OpenCode, and Hermes Agent with Semantic Code Intelligence
|
|
|
|
**~35% cheaper · ~70% fewer tool calls · 100% local**
|
|
|
|
### [Documentation & Website →](https://colbymchenry.github.io/codegraph/)
|
|
|
|
[](https://www.npmjs.com/package/@colbymchenry/codegraph)
|
|
[](https://opensource.org/licenses/MIT)
|
|
[](https://nodejs.org/)
|
|
|
|
[](#supported-platforms)
|
|
[](#supported-platforms)
|
|
[](#supported-platforms)
|
|
|
|
[](#supported-agents)
|
|
[](#supported-agents)
|
|
[](#supported-agents)
|
|
[](#supported-agents)
|
|
[](#supported-agents)
|
|
|
|
</div>
|
|
|
|
## Get Started
|
|
|
|
**No Node.js required** — one command grabs the right build for your OS:
|
|
|
|
```bash
|
|
# macOS / Linux
|
|
curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh
|
|
|
|
# Windows (PowerShell)
|
|
irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex
|
|
```
|
|
|
|
Already have Node? Use npm instead (works on any version):
|
|
|
|
```bash
|
|
npx @colbymchenry/codegraph # zero-install, or:
|
|
npm i -g @colbymchenry/codegraph
|
|
```
|
|
|
|
<sub>CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The interactive installer auto-configures your agent(s) — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent.</sub>
|
|
|
|
### Initialize Projects
|
|
|
|
```bash
|
|
cd your-project
|
|
codegraph init -i
|
|
```
|
|
|
|
<div align="center">
|
|
|
|

|
|
|
|
</div>
|
|
|
|
### Uninstall
|
|
|
|
Changed your mind? One command removes CodeGraph from every agent it configured:
|
|
|
|
```bash
|
|
codegraph uninstall
|
|
```
|
|
|
|
<sub>Reverses the installer — strips CodeGraph's MCP server config, instructions, and permissions from each configured agent. Your project indexes (`.codegraph/`) are left untouched; remove those per-project with `codegraph uninit`. Use `--target` to remove from specific agents, or `--yes` to run non-interactively.</sub>
|
|
|
|
---
|
|
|
|
## Why CodeGraph?
|
|
|
|
When Claude Code explores a codebase, it spawns **Explore agents** that scan files with grep, glob, and Read — consuming tokens on every tool call.
|
|
|
|
**CodeGraph gives those agents a pre-indexed knowledge graph** — symbol relationships, call graphs, and code structure. Agents query the graph instantly instead of scanning files.
|
|
|
|
### Benchmark Results
|
|
|
|
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 **v0.9.4** (2026-05-24)._
|
|
|
|
> **Average: 35% cheaper · 57% fewer tokens · 46% faster · 71% fewer tool calls**
|
|
|
|
| Codebase | Language | Cost | Tokens | Time | Tool calls |
|
|
|----------|----------|------|--------|------|------------|
|
|
| **VS Code** | TypeScript · ~10k files | 26% cheaper | 78% fewer | 52% faster | 85% fewer |
|
|
| **Excalidraw** | TypeScript · ~640 | 52% cheaper | 90% fewer | 73% faster | 96% fewer |
|
|
| **Django** | Python · ~3k | 12% cheaper | 36% fewer | 19% faster | 53% fewer |
|
|
| **Tokio** | Rust · ~790 | 82% cheaper | 86% fewer | 71% faster | 92% fewer |
|
|
| **OkHttp** | Java · ~645 | 2% cheaper | 13% fewer | 31% faster | 45% fewer |
|
|
| **Gin** | Go · ~110 | 21% cheaper | 34% fewer | 27% faster | 40% fewer |
|
|
| **Alamofire** | Swift · ~110 | 47% cheaper | 64% fewer | 48% faster | 83% fewer |
|
|
|
|
The gains scale with codebase size: on large repos the agent answers from the index in a handful of calls with **zero file reads**, while the no-CodeGraph agent fans out across grep/find/Read (and the sub-agents it spawns). On a small repo like Gin (~150 files) native search is already cheap, so the margin narrows.
|
|
|
|
<details>
|
|
<summary><strong>Full benchmark details</strong></summary>
|
|
|
|
**Methodology.** Each arm is `claude -p` (Claude Opus 4.7) 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 on codegraph **v0.9.4** (2026-05-24); 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. Tokio's without-arm hit $2.41/3m one batch).
|
|
|
|
**Queries:**
|
|
| Codebase | Query |
|
|
|----------|-------|
|
|
| VS Code | "How does the extension host communicate with the main process?" |
|
|
| Excalidraw | "How does Excalidraw render and update canvas elements?" |
|
|
| Django | "How does Django's ORM build and execute a query from a QuerySet?" |
|
|
| Tokio | "How does tokio schedule and run async tasks on its runtime?" |
|
|
| OkHttp | "How does OkHttp process a request through its interceptor chain?" |
|
|
| Gin | "How does gin route requests through its middleware chain?" |
|
|
| Alamofire | "How does Alamofire build, send, and validate a request?" |
|
|
|
|
**Raw medians — WITH → WITHOUT:**
|
|
| Codebase | Cost | Tokens | Time | Tool calls |
|
|
|----------|------|--------|------|------------|
|
|
| VS Code | $0.60 → $0.80 | 601k → 2.8M | 1m 10s → 2m 26s | 8 → 55 |
|
|
| Excalidraw | $0.43 → $0.90 | 344k → 3.5M | 48s → 2m 58s | 3 → 79 |
|
|
| Django | $0.59 → $0.67 | 739k → 1.2M | 1m 19s → 1m 38s | 9 → 19 |
|
|
| Tokio | $0.42 → $2.41 | 379k → 2.6M | 53s → 3m 2s | 4 → 53 |
|
|
| OkHttp | $0.47 → $0.47 | 636k → 730k | 42s → 1m 1s | 6 → 11 |
|
|
| Gin | $0.37 → $0.47 | 444k → 675k | 44s → 1m 0s | 6 → 10 |
|
|
| Alamofire | $0.61 → $1.14 | 1.0M → 2.8M | 1m 17s → 2m 27s | 12 → 69 |
|
|
|
|
**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 (and the Explore sub-agents it spawns) 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.
|
|
|
|
</details>
|
|
|
|
---
|
|
|
|
## Key Features
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Smart Context Building** | One tool call returns entry points, related symbols, and code snippets — no expensive exploration agents |
|
|
| **Full-Text Search** | Find code by name instantly across your entire codebase, powered by FTS5 |
|
|
| **Impact Analysis** | Trace callers, callees, and the full impact radius of any symbol before making changes |
|
|
| **Always Fresh** | File watcher uses native OS events (FSEvents/inotify/ReadDirectoryChangesW) with debounced auto-sync — the graph stays current as you code, zero config |
|
|
| **20+ Languages** | TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Objective-C, Swift, Kotlin, Dart, Lua, Luau, Svelte, Liquid, Pascal/Delphi |
|
|
| **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across 14 frameworks |
|
|
| **Mixed iOS / React Native / Expo** | Closes cross-language flows that static parsing misses: Swift ↔ ObjC bridging, React Native legacy bridge + TurboModules + Fabric view components, native → JS event emitters, Expo Modules |
|
|
| **100% Local** | No data leaves your machine. No API keys. No external services. SQLite database only |
|
|
|
|
---
|
|
|
|
## Framework-aware Routes
|
|
|
|
CodeGraph detects web-framework routing files and emits `route` nodes linked by `references` edges to their handler classes or functions. Querying callers of a view/controller now surfaces the URL pattern that binds it.
|
|
|
|
| Framework | Shapes recognized |
|
|
|---|---|
|
|
| **Django** | `path()`, `re_path()`, `url()`, `include()` in `urls.py` (CBV `.as_view()`, dotted paths) |
|
|
| **Flask** | `@app.route('/path', methods=[...])`, blueprint routes |
|
|
| **FastAPI** | `@app.get(...)`, `@router.post(...)`, all standard methods |
|
|
| **Express** | `app.get(...)`, `router.post(...)` with middleware chains |
|
|
| **NestJS** | `@Controller` + `@Get/@Post/...`, GraphQL `@Resolver` + `@Query/@Mutation`, `@MessagePattern`/`@EventPattern`, `@SubscribeMessage` |
|
|
| **Laravel** | `Route::get()`, `Route::resource()`, `Controller@action`, tuple syntax |
|
|
| **Drupal** | `*.routing.yml` routes (`_controller`, `_form`, entity handlers); `hook_*` implementations in `.module`/`.theme`/`.install`/`.inc` |
|
|
| **Rails** | `get '/x', to: 'users#index'`, hash-rocket `=>` syntax |
|
|
| **Spring** | `@GetMapping`, `@PostMapping`, `@RequestMapping` on methods |
|
|
| **Gin / chi / gorilla / mux** | `r.GET(...)`, `router.HandleFunc(...)` |
|
|
| **Axum / actix / Rocket** | `.route("/x", get(handler))` |
|
|
| **ASP.NET** | `[HttpGet("/x")]` attributes on action methods |
|
|
| **Vapor** | `app.get("x", use: handler)` |
|
|
| **React Router** / **SvelteKit** | Route component nodes |
|
|
|
|
---
|
|
|
|
## Mixed iOS / React Native / Expo bridging
|
|
|
|
Real iOS and React Native codebases live across multiple languages — a Swift caller invokes an Objective-C selector that's been auto-bridged, a JS file calls into a native module via the React Native bridge, a JSX component delegates to a native view manager. Static tree-sitter extraction stops at each language boundary. CodeGraph bridges them so `trace`, `callers`, `callees`, and `impact` connect end-to-end across the gap.
|
|
|
|
| Boundary | JS / Swift side | Native side | How |
|
|
|---|---|---|---|
|
|
| **Swift → ObjC** | Swift `obj.foo(bar:)` | ObjC selector `-fooWithBar:` | `@objc` auto-bridging rules (including init/property/protocol forms) + Cocoa preposition prefixes (`With`/`For`/`By`/`In`/`On`/`At`/…) |
|
|
| **ObjC → Swift** | ObjC `[obj fooWithBar:]` | Swift `@objc func foo(bar:)` | Reverse-bridge name candidates; verifies `@objc` exposure from source |
|
|
| **React Native legacy bridge** | JS `NativeModules.X.fn(...)` | ObjC `RCT_EXPORT_METHOD` / `RCT_REMAP_METHOD` · Java/Kotlin `@ReactMethod` | Parses macro/annotation declarations to build a JS-name → native-method map |
|
|
| **React Native TurboModules** | JS `import M from './NativeM'; M.fn(...)` | Native impl matching the Codegen spec | Treats the `Native<X>.ts` spec interface as ground truth |
|
|
| **RN native → JS events** | JS `new NativeEventEmitter(...).addListener('e', cb)` | ObjC `[self sendEventWithName:@"e" body:...]` · Swift `sendEvent(withName: "e", ...)` · Java/Kotlin `.emit("e", ...)` | Synthesized cross-language event channel keyed by literal event name |
|
|
| **Expo Modules** | JS `requireNativeModule('X').fn(...)` | Swift / Kotlin `Module { Name("X"); AsyncFunction("fn") { ... } }` | Parses the Expo DSL literals; synthetic method nodes resolve via existing name-match |
|
|
| **Fabric view components** | JSX `<MyView prop={v}/>` | TS Codegen spec + native impl class | Spec → `component` node; convention-based name+suffix lookup (`View`/`ComponentView`/`Manager`/`ViewManager`) bridges to native |
|
|
| **Legacy Paper view managers** | JSX `<MyView prop={v}/>` | ObjC `RCT_EXPORT_VIEW_PROPERTY` · Java/Kotlin `@ReactProp` | Same as Fabric — Paper-era declarations also produce `component` + `property` nodes |
|
|
|
|
**Validated on real codebases** (small + medium + large for each bridge):
|
|
|
|
| Bridge | Small | Medium | Large |
|
|
|---|---|---|---|
|
|
| Swift ↔ ObjC | [Charts](https://github.com/danielgindi/Charts) | [realm-swift](https://github.com/realm/realm-swift) | [Wikipedia-iOS](https://github.com/wikimedia/wikipedia-ios) |
|
|
| RN legacy bridge | [AsyncStorage](https://github.com/react-native-async-storage/async-storage) | [react-native-svg](https://github.com/software-mansion/react-native-svg) | [react-native-firebase](https://github.com/invertase/react-native-firebase) |
|
|
| RN native → JS events | [RNGeolocation](https://github.com/Agontuk/react-native-geolocation-service) | — | react-native-firebase |
|
|
| Expo Modules | expo-haptics | expo-camera | expo SDK sweep (7 packages) |
|
|
| Fabric / Paper views | [react-native-segmented-control](https://github.com/react-native-segmented-control/segmented-control) | [react-native-screens](https://github.com/software-mansion/react-native-screens) | [react-native-skia](https://github.com/Shopify/react-native-skia) |
|
|
|
|
Each bridge emits edges tagged `provenance:'heuristic'` with `metadata.synthesizedBy:` set to a stable channel name (e.g. `swift-objc-bridge`, `rn-event-channel`, `fabric-native-impl`, `expo-module-extract`), so the agent can tell at a glance how a hop got into the graph.
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### 1. Run the Installer
|
|
|
|
```bash
|
|
npx @colbymchenry/codegraph
|
|
```
|
|
|
|
The installer will:
|
|
- Ask which agent(s) to configure — auto-detects installed ones from: **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, **Hermes Agent**
|
|
- Prompt to install `codegraph` on your PATH (so agents can launch the MCP server)
|
|
- Ask whether configs apply to all your projects or just this one
|
|
- Write each chosen agent's MCP server config + an instructions file (e.g. `CLAUDE.md`, `.cursor/rules/codegraph.mdc`, `~/.codex/AGENTS.md`)
|
|
- Set up auto-allow permissions when Claude Code is one of the targets
|
|
- Initialize your current project (local installs only)
|
|
|
|
**Non-interactive (scripting / CI):**
|
|
|
|
```bash
|
|
codegraph install --yes # auto-detect agents, install global
|
|
codegraph install --target=cursor,claude --yes # explicit target list
|
|
codegraph install --target=auto --location=local # detected agents, project-local
|
|
codegraph install --print-config codex # print snippet, no file writes
|
|
```
|
|
|
|
| Flag | Values | Default |
|
|
|---|---|---|
|
|
| `--target` | `auto`, `all`, `none`, or csv (`claude,cursor,...`) | prompt |
|
|
| `--location` | `global`, `local` | prompt |
|
|
| `--yes` | (boolean) | prompt every step |
|
|
| `--no-permissions` | (boolean) skip Claude auto-allow list | permissions on |
|
|
| `--print-config <id>` | dump snippet for one agent and exit | — |
|
|
|
|
### 2. Restart Your Agent
|
|
|
|
Restart your agent (Claude Code / Cursor / Codex CLI / opencode / Hermes Agent) for the MCP server to load.
|
|
|
|
### 3. Initialize Projects
|
|
|
|
```bash
|
|
cd your-project
|
|
codegraph init -i
|
|
```
|
|
|
|
Builds the per-project knowledge graph index. Also wires up any project-local agent surfaces (e.g. Cursor's `.cursor/rules/codegraph.mdc`) so a single global `codegraph install` works in every project you open — no need to re-run the installer per project.
|
|
|
|
That's it — your agent will use CodeGraph tools automatically when a `.codegraph/` directory exists.
|
|
|
|
<details>
|
|
<summary><strong>Manual Setup (Alternative)</strong></summary>
|
|
|
|
**Install globally:**
|
|
```bash
|
|
npm install -g @colbymchenry/codegraph
|
|
```
|
|
|
|
**Add to `~/.claude.json`:**
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"codegraph": {
|
|
"type": "stdio",
|
|
"command": "codegraph",
|
|
"args": ["serve", "--mcp"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Add to `~/.claude/settings.json` (optional, for auto-allow):**
|
|
```json
|
|
{
|
|
"permissions": {
|
|
"allow": [
|
|
"mcp__codegraph__codegraph_search",
|
|
"mcp__codegraph__codegraph_context",
|
|
"mcp__codegraph__codegraph_callers",
|
|
"mcp__codegraph__codegraph_callees",
|
|
"mcp__codegraph__codegraph_impact",
|
|
"mcp__codegraph__codegraph_node",
|
|
"mcp__codegraph__codegraph_status",
|
|
"mcp__codegraph__codegraph_files"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary><strong>Global Instructions Reference</strong></summary>
|
|
|
|
The installer automatically adds these instructions to `~/.claude/CLAUDE.md`:
|
|
|
|
```markdown
|
|
## CodeGraph
|
|
|
|
CodeGraph builds a semantic knowledge graph of codebases for faster, smarter code exploration.
|
|
|
|
### If `.codegraph/` exists in the project
|
|
|
|
**Answer directly with CodeGraph — don't delegate exploration to a file-reading sub-agent or a grep/read loop.** CodeGraph *is* the pre-built search index; re-deriving its answers with grep + Read repeats work it already did and costs more for the same result. For "how does X work?", architecture, trace, or where-is-X questions, answer in a handful of CodeGraph calls and stop — typically with **zero file reads**. The returned source is complete and authoritative: treat it as already read and do not re-open those files. Reach for raw Read/Grep only to confirm a specific detail CodeGraph didn't cover.
|
|
|
|
**Tool selection by intent:**
|
|
|
|
| Tool | Use For |
|
|
|------|---------|
|
|
| `codegraph_context` | Map a task / feature / area first — composes search + node + callers + callees in one call |
|
|
| `codegraph_trace` | "How does X reach Y" — the call path, each hop's body inline (follows dynamic-dispatch hops grep can't) |
|
|
| `codegraph_explore` | Survey several related symbols' source in ONE budget-capped call |
|
|
| `codegraph_search` | Find a symbol by name |
|
|
| `codegraph_callers` / `codegraph_callees` | Walk call flow one hop at a time |
|
|
| `codegraph_impact` | Check what's affected before editing |
|
|
| `codegraph_node` | Get a single symbol's source / signature |
|
|
|
|
A direct CodeGraph answer is a handful of calls; a grep/read exploration is dozens.
|
|
|
|
### If `.codegraph/` does NOT exist
|
|
|
|
At the start of a session, ask the user if they'd like to initialize CodeGraph:
|
|
|
|
"I notice this project doesn't have CodeGraph initialized. Would you like me to run `codegraph init -i` to build a code knowledge graph?"
|
|
```
|
|
|
|
</details>
|
|
|
|
---
|
|
|
|
## How It Works
|
|
|
|
```
|
|
┌───────────────────────────────────────────────────────────────────┐
|
|
│ Claude Code │
|
|
│ │
|
|
│ "How does a request reach the database?" │
|
|
│ calls CodeGraph tools directly — no Explore sub-agent │
|
|
│ │ │
|
|
└─────────────────────────────────┬─────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────────────────────────────────────────────────┐
|
|
│ CodeGraph MCP Server │
|
|
│ │
|
|
│ context · trace · explore · callers · callees · impact │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ SQLite knowledge graph │
|
|
│ symbols · edges · files · FTS5 full-text search │
|
|
└───────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
1. **Extraction** — [tree-sitter](https://tree-sitter.github.io/) parses source code into ASTs. Language-specific queries extract nodes (functions, classes, methods) and edges (calls, imports, extends, implements).
|
|
|
|
2. **Storage** — Everything goes into a local SQLite database (`.codegraph/codegraph.db`) with FTS5 full-text search.
|
|
|
|
3. **Resolution** — After extraction, references are resolved: function calls → definitions, imports → source files, class inheritance, and framework-specific patterns.
|
|
|
|
4. **Auto-Sync** — The MCP server watches your project using native OS file events. Changes are debounced (2-second quiet window), filtered to source files only, and incrementally synced. The graph stays fresh as you code — no configuration needed.
|
|
|
|
---
|
|
|
|
## CLI Reference
|
|
|
|
```bash
|
|
codegraph # Run interactive installer
|
|
codegraph install # Run installer (explicit)
|
|
codegraph uninstall # Remove CodeGraph from your agents (inverse of install)
|
|
codegraph init [path] # Initialize in a project (--index to also index)
|
|
codegraph uninit [path] # Remove CodeGraph from a project (--force to skip prompt)
|
|
codegraph index [path] # Full index (--force to re-index, --quiet for less output)
|
|
codegraph sync [path] # Incremental update
|
|
codegraph status [path] # Show statistics
|
|
codegraph query <search> # Search symbols (--kind, --limit, --json)
|
|
codegraph files [path] # Show file structure (--format, --filter, --max-depth, --json)
|
|
codegraph context <task> # Build context for AI (--format, --max-nodes)
|
|
codegraph callers <symbol> # Find what calls a function/method (--limit, --json)
|
|
codegraph callees <symbol> # Find what a function/method calls (--limit, --json)
|
|
codegraph impact <symbol> # Analyze what code is affected by changing a symbol (--depth, --json)
|
|
codegraph affected [files...] # Find test files affected by changes (see below)
|
|
codegraph serve --mcp # Start MCP server
|
|
```
|
|
|
|
### `codegraph affected`
|
|
|
|
Traces import dependencies transitively to find which test files are affected by changed source files.
|
|
|
|
```bash
|
|
codegraph affected src/utils.ts src/api.ts # Pass files as arguments
|
|
git diff --name-only | codegraph affected --stdin # Pipe from git diff
|
|
codegraph affected src/auth.ts --filter "e2e/*" # Custom test file pattern
|
|
```
|
|
|
|
| Option | Description | Default |
|
|
|--------|-------------|---------|
|
|
| `--stdin` | Read file list from stdin | `false` |
|
|
| `-d, --depth <n>` | Max dependency traversal depth | `5` |
|
|
| `-f, --filter <glob>` | Custom glob to identify test files | auto-detect |
|
|
| `-j, --json` | Output as JSON | `false` |
|
|
| `-q, --quiet` | Output file paths only | `false` |
|
|
|
|
**CI/hook example:**
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
AFFECTED=$(git diff --name-only HEAD | codegraph affected --stdin --quiet)
|
|
if [ -n "$AFFECTED" ]; then
|
|
npx vitest run $AFFECTED
|
|
fi
|
|
```
|
|
|
|
---
|
|
|
|
## MCP Tools
|
|
|
|
When running as an MCP server, CodeGraph exposes these tools to Claude Code:
|
|
|
|
| Tool | Purpose |
|
|
|------|---------|
|
|
| `codegraph_search` | Find symbols by name across the codebase |
|
|
| `codegraph_context` | Build relevant code context for a task |
|
|
| `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 |
|
|
| `codegraph_callers` | Find what calls a function |
|
|
| `codegraph_callees` | Find what a function calls |
|
|
| `codegraph_impact` | Analyze what code is affected by changing a symbol |
|
|
| `codegraph_node` | Get details about a specific symbol (optionally with source code) |
|
|
| `codegraph_explore` | Return source for several related symbols grouped by file, plus a relationship map, in one call |
|
|
| `codegraph_files` | Get indexed file structure (faster than filesystem scanning) |
|
|
| `codegraph_status` | Check index health and statistics |
|
|
|
|
---
|
|
|
|
## Library Usage
|
|
|
|
```typescript
|
|
import CodeGraph from '@colbymchenry/codegraph';
|
|
|
|
const cg = await CodeGraph.init('/path/to/project');
|
|
// Or: const cg = await CodeGraph.open('/path/to/project');
|
|
|
|
await cg.indexAll({
|
|
onProgress: (p) => console.log(`${p.phase}: ${p.current}/${p.total}`)
|
|
});
|
|
|
|
const results = cg.searchNodes('UserService');
|
|
const callers = cg.getCallers(results[0].node.id);
|
|
const context = await cg.buildContext('fix login bug', { maxNodes: 20, includeCode: true, format: 'markdown' });
|
|
const impact = cg.getImpactRadius(results[0].node.id, 2);
|
|
|
|
cg.watch(); // auto-sync on file changes
|
|
cg.unwatch(); // stop watching
|
|
cg.close();
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
There isn't any — CodeGraph is zero-config, with **no config file** to write or
|
|
keep in sync. Language support is automatic from the file extension; there's
|
|
nothing to wire up per language.
|
|
|
|
What it skips out of the box:
|
|
|
|
- **Dependency, build, and cache directories** — `node_modules`, `vendor`,
|
|
`dist`, `build`, `target`, `.venv`, `Pods`, `.next`, and the like across every
|
|
[supported stack](#supported-languages) — so the graph is your code, not
|
|
third-party noise. This holds even with no `.gitignore`.
|
|
- **Anything in your `.gitignore`** — honored in git repos via git, and in
|
|
non-git projects by reading `.gitignore` directly (root and nested).
|
|
- **Files larger than 1 MB** — generated bundles, minified JS, vendored blobs.
|
|
|
|
To keep something else out, add it to `.gitignore`. To pull a default-excluded
|
|
directory back **in** (say you really do want a vendored dependency indexed),
|
|
add a negation — `!vendor/`. The defaults apply uniformly, so committing a
|
|
dependency or build directory doesn't force it into the graph; the `.gitignore`
|
|
negation is the explicit opt-in.
|
|
|
|
## Supported Platforms
|
|
|
|
Every release ships a self-contained build (bundled Node runtime — nothing to
|
|
compile) for all three desktop OSes, on both Intel/AMD (x64) and ARM (arm64):
|
|
|
|
| Platform | Architectures | Install |
|
|
|----------|---------------|---------|
|
|
| Windows | x64, arm64 | PowerShell installer or npm |
|
|
| macOS | x64, arm64 | shell installer or npm |
|
|
| Linux | x64, arm64 | shell installer or npm |
|
|
|
|
See [Get Started](#get-started) for the one-line install commands.
|
|
|
|
## Supported Agents
|
|
|
|
The interactive installer auto-detects and configures each of these — wiring up
|
|
the MCP server and writing its instructions file:
|
|
|
|
- **Claude Code**
|
|
- **Cursor**
|
|
- **Codex CLI**
|
|
- **opencode**
|
|
- **Hermes Agent**
|
|
|
|
## Supported Languages
|
|
|
|
| Language | Extension | Status |
|
|
|----------|-----------|--------|
|
|
| TypeScript | `.ts`, `.tsx` | Full support |
|
|
| JavaScript | `.js`, `.jsx`, `.mjs` | Full support |
|
|
| Python | `.py` | Full support |
|
|
| Go | `.go` | Full support |
|
|
| Rust | `.rs` | Full support |
|
|
| Java | `.java` | Full support |
|
|
| C# | `.cs` | Full support |
|
|
| PHP | `.php` | Full support |
|
|
| Ruby | `.rb` | Full support |
|
|
| C | `.c`, `.h` | Full support |
|
|
| C++ | `.cpp`, `.hpp`, `.cc` | Full support |
|
|
| Objective-C | `.m`, `.mm`, `.h` | Partial support (classes, protocols, methods, `@property`, `#import`, message sends; `.mm` ObjC++ may parse incompletely) |
|
|
| Swift | `.swift` | Full support |
|
|
| Kotlin | `.kt`, `.kts` | Full support |
|
|
| Scala | `.scala`, `.sc` | Full support (classes, traits, methods, type aliases, Scala 3 enums) |
|
|
| Dart | `.dart` | Full support |
|
|
| Svelte | `.svelte` | Full support (script extraction, Svelte 5 runes, SvelteKit routes) |
|
|
| Vue | `.vue` | Full support (script + script-setup extraction, Nuxt page/API/middleware routes) |
|
|
| Liquid | `.liquid` | Full support |
|
|
| Pascal / Delphi | `.pas`, `.dpr`, `.dpk`, `.lpr` | Full support (classes, records, interfaces, enums, DFM/FMX form files) |
|
|
| Lua | `.lua` | Full support (functions, methods with receivers, local variables, `require` imports, call edges) |
|
|
| Luau | `.luau` | Full support (everything in Lua, plus `type`/`export type` aliases, typed signatures, and Roblox instance-path `require`) |
|
|
|
|
## Troubleshooting
|
|
|
|
**"CodeGraph not initialized"** — Run `codegraph init` in your project directory first.
|
|
|
|
**Indexing is slow** — Check that `node_modules` and other large directories are excluded. Use `--quiet` to reduce output overhead.
|
|
|
|
**MCP hits `database is locked`** — current builds shouldn't: CodeGraph bundles its own Node runtime and uses Node's built-in `node:sqlite` in WAL mode, where concurrent reads never block on a writer. If you still see it:
|
|
|
|
- **You're on an old (pre-0.9) install.** Reinstall to get the bundled runtime — `curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh` (macOS/Linux), `irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex` (Windows), or `npm i -g @colbymchenry/codegraph@latest`.
|
|
- **`codegraph status` shows `Journal:` other than `wal`** — WAL couldn't be enabled on this filesystem (common on network shares and WSL2 `/mnt`), so reads can block on writes. Move the project (with its `.codegraph/` folder) onto a local disk.
|
|
|
|
**MCP server not connecting** — Ensure the project is initialized/indexed, verify the path in your MCP config, and check that `codegraph serve --mcp` works from the command line.
|
|
|
|
**Missing symbols** — The MCP server auto-syncs on save (wait a couple seconds). Run `codegraph sync` manually if needed. Check that the file's language is supported and isn't inside a `.gitignore`d or default-excluded directory (e.g. `node_modules`, `dist`).
|
|
|
|
## Star History
|
|
|
|
<a href="https://www.star-history.com/?repos=colbymchenry%2Fcodegraph&type=date&legend=top-left">
|
|
<picture>
|
|
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=colbymchenry/codegraph&type=date&theme=dark&legend=top-left" />
|
|
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=colbymchenry/codegraph&type=date&legend=top-left" />
|
|
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=colbymchenry/codegraph&type=date&legend=top-left" />
|
|
</picture>
|
|
</a>
|
|
|
|
## License
|
|
|
|
MIT
|
|
|
|
---
|
|
|
|
<div align="center">
|
|
|
|
**Made for AI coding agents — Claude Code, Cursor, Codex CLI, opencode, and Hermes Agent**
|
|
|
|
[Report Bug](https://github.com/colbymchenry/codegraph/issues) · [Request Feature](https://github.com/colbymchenry/codegraph/issues)
|
|
|
|
</div>
|