npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aroman22/codegraph-vba

v1.9.0

Published

Local-first code intelligence for AI agents (MCP). Self-contained — bundles its own runtime.

Downloads

2,234

Readme

CodeGraph (VBA & Access Fork)

🎉 1.5 Released — VBA conditional-compilation is now correct + TempVars/RecordSource/RowSource indexed

Already installed? Run codegraph-vba upgrade to update in place.

Follow @getcodegraph on X for updates.

Supercharge Claude Code, Cursor, Codex, OpenCode, Hermes Agent, Gemini, Antigravity, and Kiro with Semantic Code Intelligence

Surgical context · fewer tool calls · faster answers · 100% local


[!NOTE] This repository is a fork of the official CodeGraph. It is renamed to codegraph-vba to avoid name collisions and features custom parser support for VBA (Visual Basic for Applications) and MS Access applications.

Official Documentation & Website →

Windows macOS Linux

Claude Code Cursor Codex opencode Hermes Agent Gemini Antigravity Kiro

The CodeGraph platform is coming — for every PR, know exactly what to test, what could break, which flows are affected, and whether business logic is compromised.

Get early beta access to the hosted product · getcodegraph.com


This is a fork — VBA / Access + Dysflow

This repository is a fork of colbymchenry/codegraph, maintained at ardelperal/codegraph-vba. It is identical to the upstream for every language except VBA / Access — the fork adds nothing new to TypeScript, Python, Go, Rust, Java, etc., and is kept rebased against colbymchenry/codegraph:main so it stays current with upstream fixes and benchmarks.

Why fork? To add VBA / Access language support that does not exist upstream, so agents can navigate Microsoft Access projects managed by Dysflow the same way they navigate TypeScript or Python today. See the VBA / Access + Dysflow integration section below for the feature spec, the pattern table, and the hard invariants.

The fork is published to npm as @aroman22/codegraph-vba. The upstream package @colbymchenry/codegraph does not have VBA / Access support — install @aroman22/codegraph-vba to get it:

# Option A — install from npm (easiest; gets you the codegraph-vba CLI on PATH):
npm i -g @aroman22/codegraph-vba
# or with pnpm:
pnpm add -g codegraph-vba
# or the one-line OS installer (no Node required) — see Get Started below.
# Option B — clone, build, and use the local binary (full control, useful for contributing):
git clone https://github.com/ardelperal/codegraph-vba.git
cd codegraph
pnpm install              # pnpm is the source of truth — see pnpm-lock.yaml
pnpm run build            # produces dist/bin/codegraph.js
# The binary is now at dist/bin/codegraph.js — point your agent's MCP at this path

If you do not need VBA / Access support, install the upstream package instead — it is otherwise identical and gets released more frequently:

npm i -g @colbymchenry/codegraph

Get Started

1. Install the CLI

No Node.js required — one command grabs the right build for your OS:

# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/ardelperal/codegraph-vba/main/install.sh | sh

# Windows (PowerShell)
irm https://raw.githubusercontent.com/ardelperal/codegraph-vba/main/install.ps1 | iex
npm i -g @aroman22/codegraph-vba

CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The installer puts codegraph-vba on your PATH but doesn't change your current shell — open a new terminal before the next step so the command resolves.

Upgrade any time with codegraph-vba upgrade — it detects how you installed (bundle, npm, or npx) and updates in place. Add --check to see if an update is available, or codegraph-vba upgrade <version> to pin one.

2. Wire up your agent(s)

In a new terminal, run the installer to connect CodeGraph to the agents you use:

codegraph-vba install

Detects and auto-configures Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, and Kiro — wiring the CodeGraph MCP server into each. This is the step that connects CodeGraph to your agent; installing the CLI in step 1 does not do it on its own. It only wires up your agent — it does not index any code; building each project's graph is the separate codegraph-vba init in step 3. (Shortcut: npx codegraph-vba downloads and runs this in one go.)

3. Initialize each project

cd your-project
codegraph-vba init

codegraph-vba init creates the local .codegraph-vba/ directory and builds the full graph in the same step — one command, done.

1_C_VYnhpys0UHrOuOgpgoyw

4. No more syncing!

Auto-sync is enabled by default. CodeGraph watches the project and updates the graph on every file change — while your agent edits code, or you add, modify, or delete files. The index is never stale, and there is nothing to re-run.

Uninstall

Changed your mind? One command removes CodeGraph from every agent it configured:

codegraph-vba uninstall

Reverses the installer — strips CodeGraph's MCP server config, instructions, and permissions from each configured agent. Your project indexes (.codegraph-vba/) are left untouched; remove those per-project with codegraph-vba uninit. Use --target to remove from specific agents, or --yes to run non-interactively.


Why CodeGraph?

When an AI agent needs to understand code — to answer a question or make a change — it discovers structure the slow way: grep, glob, and Read, one file at a time, rebuilding call paths and dependencies by hand. That's a pile of tool calls and round-trips before it even starts the real work.

CodeGraph hands the agent the exact code it needs in one call. It's a pre-built knowledge graph of every symbol, call edge, and dependency in your codebase — so instead of crawling files, the agent asks one question and gets back the relevant source, the call paths between those symbols (including dynamic-dispatch hops grep can't follow), and the blast radius of a change. Surgical context, not a file-by-file search — which means fewer tool calls and faster answers on every codebase, large or small.

A note on cost: CodeGraph's win on every codebase is precision and speed — fewer tool calls, faster answers. It cuts token and dollar cost too, but those savings are scale-dependent: small and noisy on a modest codebase, and material only once a repo is large and tangled — at the scale of a Google or Microsoft monorepo, multiplied by a whole team's daily agent usage — for them to compound into a real line item. On a 500-file project, adopt CodeGraph for the speed; the cost savings show up when the codebase (and the team) gets big.

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, 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).

The universal win — every repo, every size: 58% fewer tool calls · 22% faster · file reads cut to ~zero.

The reliable, universal payoff is surgical context and speed: CodeGraph collapses the agent's grep/find/Read crawl into a few direct queries — returning the exact methods you asked about even when they're buried in a multi-thousand-line file — so it answers with near-zero file reads while the no-CodeGraph agent spends its budget on discovery. The Tokens and Cost columns are real too, but — as noted above — they're scale-dependent: small and noisy per query, compounding into real money only at large-codebase, high-volume scale.

| Codebase | Language | Tool calls | Time | File reads | Tokens | Cost | |----------|----------|------------|------|------------|--------|------| | VS Code | TypeScript · ~10k files | 81% fewer | 11% faster | 0 vs 9 | 64% fewer | 18% cheaper | | Excalidraw | TypeScript · ~640 | 40% fewer | 27% faster | 0 vs 7 | 25% fewer | even | | Django | Python · ~3k | 77% fewer | 13% faster | 0 vs 9 | 60% fewer | 8% cheaper | | Tokio | Rust · ~790 | 57% fewer | 18% faster | 0 vs 8 | 38% fewer | even | | OkHttp | Java · ~645 | 50% fewer | 31% faster | 0 vs 4 | 54% fewer | 25% cheaper | | Gin | Go · ~110 | 44% fewer | 24% faster | 1 vs 6 | 23% fewer | 19% cheaper | | Alamofire | Swift · ~110 | 58% fewer | 33% faster | 0 vs 9 | 64% fewer | 40% cheaper |

File reads = median files the agent opened with vs without CodeGraph — the surgical-context win in one column. Tokens and Cost are the same with-vs-without deltas; they're directional (they move run-to-run) and, per query, small in absolute terms — which is why they only become a line item at scale. codegraph_explore also collapses redundant interchangeable implementations to signatures, so a response is sized to the answer rather than the file count.

VS Code · ~10k files | Metric | WITH cg | WITHOUT cg | Δ | |---|---|---|---| | Time | 1m 59s | 2m 13s | 11% faster | | File Reads | 0 | 9 | −9 | | Grep/Bash | 0 | 11 | −11 | | Tool calls | 4 | 21 | 81% fewer | | Total tokens | 640k | 1.79M | 64% fewer | | Cost | $0.68 | $0.83 | 18% cheaper |

Excalidraw · ~640 files | Metric | WITH cg | WITHOUT cg | Δ | |---|---|---|---| | Time | 1m 32s | 2m 6s | 27% faster | | File Reads | 0 | 7 | −7 | | Grep/Bash | 1 | 8 | −7 | | Tool calls | 9 | 15 | 40% fewer | | Total tokens | 1.27M | 1.69M | 25% fewer | | Cost | $0.78 | $0.78 | even |

Django · ~3k files | Metric | WITH cg | WITHOUT cg | Δ | |---|---|---|---| | Time | 1m 43s | 1m 58s | 13% faster | | File Reads | 0 | 9 | −9 | | Grep/Bash | 0 | 5 | −5 | | Tool calls | 3 | 13 | 77% fewer | | Total tokens | 559k | 1.41M | 60% fewer | | Cost | $0.57 | $0.62 | 8% cheaper |

Tokio · ~790 files | Metric | WITH cg | WITHOUT cg | Δ | |---|---|---|---| | Time | 1m 55s | 2m 20s | 18% faster | | File Reads | 0 | 8 | −8 | | Grep/Bash | 0 | 6 | −6 | | Tool calls | 6 | 14 | 57% fewer | | Total tokens | 1.08M | 1.73M | 38% fewer | | Cost | $0.82 | $0.82 | even |

OkHttp · ~645 files | Metric | WITH cg | WITHOUT cg | Δ | |---|---|---|---| | Time | 1m 1s | 1m 29s | 31% faster | | File Reads | 0 | 4 | −4 | | Grep/Bash | 2 | 6 | −4 | | Tool calls | 5 | 10 | 50% fewer | | Total tokens | 502k | 1.10M | 54% fewer | | Cost | $0.41 | $0.55 | 25% cheaper |

Gin · ~110 files | Metric | WITH cg | WITHOUT cg | Δ | |---|---|---|---| | Time | 1m 14s | 1m 37s | 24% faster | | File Reads | 1 | 6 | −5 | | Grep/Bash | 1 | 2 | −1 | | Tool calls | 5 | 9 | 44% fewer | | Total tokens | 651k | 847k | 23% fewer | | Cost | $0.46 | $0.57 | 19% cheaper |

Alamofire · ~110 files | Metric | WITH cg | WITHOUT cg | Δ | |---|---|---|---| | Time | 1m 35s | 2m 21s | 33% faster | | File Reads | 0 | 9 | −9 | | Grep/Bash | 0 | 4 | −4 | | Tool calls | 5 | 12 | 58% fewer | | Total tokens | 766k | 2.10M | 64% fewer | | Cost | $0.57 | $0.95 | 40% cheaper |

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).

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?" |

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.


Key Features

| | | |---|---| | Surgical Context | One tool call returns entry points, related symbols, and code snippets — no slow file-by-file exploration | | 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 | | 30+ Languages | TypeScript, JavaScript, ArkTS, Python, Go, Rust, Java, C#, VB.NET, PHP, Ruby, C, C++, CUDA, Objective-C, Metal, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Nix, Erlang, CFML, COBOL, Solidity, Terraform/OpenTofu, Svelte, Vue, Astro, Liquid, Pascal/Delphi, VBA / Access | | Framework-aware Routes | Recognizes web-framework routing files and links URL patterns to their handlers across 17 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 | | VBA / Access + Dysflow | Indexes the Dysflow-exported source tree (.bas/.cls + .form.txt/.report.txt) of Microsoft Access projects so agents can navigate VBA code the same way they navigate TypeScript or Python | | 100% Local | No data leaves your machine. No API keys. No external services. SQLite database only |

When your agent (Claude Code, Cursor, Codex, opencode) launches codegraph-vba serve --mcp, three layers keep the index in step with your code — and make sure the agent never gets a silent wrong answer in the brief window between an edit and the next sync:

  1. File watcher with debounced auto-sync. A native FSEvents / inotify / ReadDirectoryChangesW watcher captures every source-file create / modify / delete and triggers a re-index after a debounce window (default 2000ms, tunable via CODEGRAPH_WATCH_DEBOUNCE_MS, clamped to [100ms, 60s]). Bursts of edits collapse into a single sync.

  2. Per-file staleness banner. During the brief debounce window, MCP tool responses that would reference a still-pending file prepend a ⚠️ banner naming it and telling the agent to Read it directly. Pending files NOT referenced by the response surface as a small footer instead. Either way, the agent gets an explicit signal — validated with Claude Code, where the agent literally says "Reading the file directly for the live content" before opening it.

  3. Connect-time catch-up. When the MCP server (re)connects, codegraph runs a fast (size, mtime) + content-hash reconciliation against the working tree before answering the first query — so edits made while no MCP server was running (a git pull from the terminal, edits from another editor, a previous agent session that exited) get absorbed on the next session's first tool call.

agent writes src/Widget.ts
  → watcher fires (<100ms)
  → debounce (default 2s)
  → sync; Widget.ts is in the index
  → next agent query sees it

Verify any time with codegraph-vba status (CLI). If anything is pending, you'll see a ### Pending sync: section naming the files and their edit age.

The handful of cases where manual codegraph-vba sync makes sense: the watcher is disabled (sandboxed environments, or CODEGRAPH_NO_DAEMON=1), or you're scripting against the index outside an agent session and want a pre-flight sync at the start of your script.

→ Full deep-dive in the upstream Guides → Indexing a Project.


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. For VBA / Access projects the same idea applies to Access's data/event wiring rather than URL routes — see the bottom row of the table.

| 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 | | Play | GET/POST/… verb routes in conf/routesController.method actions (Scala + Java) | | 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 | | Vue Router / Nuxt | pages/ file-based routes, server/api/ endpoints, route middleware | | Astro | src/pages/ file-based routes (.astro pages + .ts endpoints, [param]/[...rest] syntax) | | VBA / Access (Dysflow) | SQL embedded in DoCmd.RunSQL / CurrentDb.OpenRecordset / Executereferences edges to the FROM/INTO/UPDATE table; WithEvents form-event listeners → handler; form module ↔ .cls code-behind binding (see VBA / Access + Dysflow integration for the full pattern table) |

VBA / Access has no URL router, so instead of route nodes its "routing" is the data and event wiring that connects Access UI to behavior — SQL-string table references, WithEvents form handlers, and form-to-code-behind bindings. Each is a synthesized references edge tagged with metadata.synthesizedBy (vba-sql-table, vba-withevents, vba-form-binding).


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 codegraph_explore connects the flow end-to-end across the gap — call paths and blast radius cross the boundary instead of stopping at it.

| 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 | realm-swift | Wikipedia-iOS | | RN legacy bridge | AsyncStorage | react-native-svg | react-native-firebase | | RN native → JS events | RNGeolocation | — | react-native-firebase | | Expo Modules | expo-haptics | expo-camera | expo SDK sweep (7 packages) | | Fabric / Paper views | react-native-segmented-control | react-native-screens | 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.


VBA / Access + Dysflow integration

Microsoft Access projects managed via Dysflow live as .accdb binaries on one side and a Dysflow-exported source tree on the other — .bas (standard modules), .cls (class modules + form code-behind), .form.txt and .report.txt (Dysflow's canonical SaveAsText format for form/report UI). CodeGraph indexes that source tree so agents can navigate Access code the same way they navigate TypeScript or Python projects — and so the existing TypeScript/Java/Python code surrounding an Access codebase (when applicable) stays queryable in the same graph.

The two are sibling tools: Dysflow owns the Access binary round-trip (sync, compile, schema-first TDD, fixtures, sandbox), CodeGraph owns the knowledge graph. They meet at the source tree.

| Pattern | .bas / .cls side | .form.txt / .report.txt side | How | |---|---|---|---| | Form code ↔ UI binding | .cls class node (canonical form code) | .form.txt module node + property nodes per control | UnresolvedReference with synthesizedBy: 'vba-form-binding'; resolver wires form module → sibling .cls class at index time | | Implements IFoo | .cls declares Implements IFoo | — | Emits an implements edge from the class to IFoo | | Dim x As Foo.Bar | .bas/.cls qualified type reference | — | references edge to Foo with synthesizedBy: 'vba-name-resolution'; silent when unresolvable | | WithEvents m_X As Form_Foo | .cls listener declaration | — | references edge to Form_Foo with synthesizedBy: 'vba-withevents' — closes the event-driven form flow | | Event Foo(...) / RaiseEvent Foo(...) | .cls custom event declaration + raise site | — | event node plus raises-event edges from the raising procedure; WithEvents also emits subscribes-event edges with the listener variable name | | Type T ... End Type | .bas/.cls user-defined type declaration | — | type node plus type_member child nodes linked by type-member edges and member type metadata | | Declare PtrSafe Function X Lib "dll" | .bas/.cls Win32/API declaration | — | declare node with DLL, alias, kind, and PtrSafe metadata; VBA call sites still emit calls edges to it | | Enum / Const domain dictionaries | .bas/.cls enum blocks and module constants | — | enum, enum_member, and constant nodes linked to their module/class; constant string values are preserved in metadata for local resolution | | Saved Access QueryDefs | queries/<Name>.sql | — | query node per Dysflow-exported .sql file with references edges to tables named by FROM / JOIN / INTO / UPDATE | | New Clase(...) | .bas/.cls instantiation | — | references edge with synthesizedBy: 'vba-new-binding' | | SQL in VBA strings | .bas/.cls SQL inside DoCmd.RunSQL / CurrentDb.OpenRecordset / CurrentDb.Execute / db.Execute | — | Table names extracted from FROM/INTO/UPDATE <table>references edges with synthesizedBy: 'vba-sql-table' |

Hard invariants enforced by the extractor and verified by tests:

  • .cls is the canonical source for form code. .form.txt emits zero function / sub / class nodes — only the form-level module node and property nodes per control. Dysflow overwrites .form.txt's embedded code on the next import, so emitting code from there would be both wrong and ephemeral.
  • Option-only files stay silent. A .bas containing only Option ... directives emits zero symbol nodes; a .bas with only Enum, Const, Event, Type, or Declare declarations DOES emit its module node because those declarations are real graph symbols.

VBA / Access node kinds added by the fork:

| Node kind | Meaning | |---|---| | enum / enum_member | VBA Enum block and its members | | constant | VBA Const declaration; string values are kept in metadata when available | | query | Dysflow-exported saved Access query (queries/<Name>.sql) | | event | VBA custom Event declaration | | type / type_member | VBA user-defined Type ... End Type and each declared member | | declare | Win32/API Declare / Declare PtrSafe statement | | form-layout | .form.txt / .report.txt form/report container | | form-instance-control | Access control instance from form/report UI text |

Scope: Dysflow-managed projects only (Dysflow's .form.txt / .report.txt SaveAsText format). Legacy .frm / .dsr Access binary formats are not in scope.


Quick Start

1. Run the Installer

npx codegraph-vba

The installer will:

  • Ask which agent(s) to configure — auto-detects installed ones from: Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, Kiro
  • Prompt to install codegraph-vba 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, plus a small marker-fenced CodeGraph section in the agent's instructions file (CLAUDE.md / AGENTS.md / GEMINI.md) — that's how subagents and non-MCP agents learn the codegraph-vba explore command, since the MCP server's own guidance only reaches the main agent. Removed cleanly by codegraph-vba uninstall.
  • Set up auto-allow permissions when Claude Code is one of the targets

The installer wires up your agents only — it does not index your code. After it finishes, build each project's graph yourself with codegraph-vba init (step 3). One global codegraph-vba install covers every project; you run codegraph-vba init once per project.

Non-interactive (scripting / CI):

codegraph-vba install --yes                              # auto-detect agents, install global
codegraph-vba install --target=cursor,claude --yes       # explicit target list
codegraph-vba install --target=auto --location=local     # detected agents, project-local
codegraph-vba 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 / Gemini CLI / Antigravity IDE / Kiro) for the MCP server to load.

3. Initialize Projects

cd your-project
codegraph-vba init

Builds the per-project knowledge graph index, which then auto-syncs on every file change. A single global codegraph-vba 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-vba/ directory exists.

Install globally:

npm i -g @aroman22/codegraph-vba

Add to ~/.claude.json:

{
  "mcpServers": {
    "codegraph": {
      "type": "stdio",
      "command": "codegraph-vba",
      "args": ["serve", "--mcp"]
    }
  }
}

Add to ~/.claude/settings.json (optional, for auto-allow):

{
  "permissions": {
    "allow": [
      "mcp__codegraph__*"
    ]
  }
}

One wildcard auto-approves every CodeGraph tool — codegraph_explore is the only one listed by default, but if you re-enable others via CODEGRAPH_MCP_TOOLS they're already permitted, no prompt.

CodeGraph's MCP server delivers its usage guidance to your agent automatically, in the MCP initialize response. In short, it tells the agent to:

  • 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.
  • Reach for 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' verbatim source grouped by file, the call paths between them (dynamic-dispatch hops included), and a blast-radius summary. Name a file or symbol in the query to read its current line-numbered source.
  • Trust the results — don't re-verify with grep, and check the staleness banner after edits.
  • Works per project: query any project that has a .codegraph-vba/ index by passing projectPath — so a monorepo where only some services are indexed, or a second repo, works in one session. A path with no index returns clean guidance to use built-in tools; indexing stays your decision.

The exact text is src/mcp/server-instructions.ts — the single source of truth for the main agent. Because subagents and non-MCP harnesses never see the MCP guidance, the installer also writes a short marker-fenced section into the agent's instructions file pointing at the codegraph-vba explore CLI equivalent.


How It Works

┌───────────────────────────────────────────────────────────────────┐
│                            Claude Code                            │
│                                                                   │
│   "How does a request reach the database?"                        │
│       calls CodeGraph tools directly — no Explore sub-agent       │
│                                 │                                 │
└─────────────────────────────────┬─────────────────────────────────┘
                                  │
                                  ▼
┌───────────────────────────────────────────────────────────────────┐
│                        CodeGraph MCP Server                       │
│                                                                   │
│ explore  ·  one call → verbatim source + call flow + blast radius │
│                                 │                                 │
│                                 ▼                                 │
│                       SQLite knowledge graph                      │
│          symbols · edges · files · FTS5 full-text search          │
└───────────────────────────────────────────────────────────────────┘
  1. Extractiontree-sitter 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-vba/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

codegraph-vba                         # Run interactive installer
codegraph-vba install                 # Run installer (explicit)
codegraph-vba uninstall               # Remove CodeGraph from your agents (inverse of install)
codegraph-vba init [path]             # Initialize a project + build its graph (one step)
codegraph-vba uninit [path]           # Remove CodeGraph from a project (--force to skip prompt)
codegraph-vba index [path]            # Full index (--force to re-index, --quiet for less output)
codegraph-vba sync [path]             # Incremental update
codegraph-vba status [path]           # Show statistics
codegraph-vba unlock [path]           # Remove a stale lock file that's blocking indexing
codegraph-vba query <search>          # Search symbols (--kind, --limit, --json)
codegraph-vba explore <query>         # Relevant symbols' source + call paths in one shot (same output as the codegraph_explore MCP tool)
codegraph-vba node <symbol|file>      # One symbol's source + callers, or read a file with line numbers (same output as codegraph_node)
codegraph-vba files [path]            # Show file structure (--format, --filter, --max-depth, --json)
codegraph-vba callers <symbol>        # Find what calls a function/method (--limit, --json)
codegraph-vba callees <symbol>        # Find what a function/method calls (--limit, --json)
codegraph-vba impact <symbol>         # Analyze what code is affected by changing a symbol (--depth, --json)
codegraph-vba affected [files...]     # Find test files affected by changes (see below)
codegraph-vba daemon                  # Manage background daemons — pick one to stop (alias: daemons)
codegraph-vba telemetry [on|off]      # Show or change anonymous usage telemetry
codegraph-vba upgrade [version]       # Update to the latest release (--check, --force)
codegraph-vba version                 # Print the installed version (also -v, --version)
codegraph-vba help [command]          # Show help, optionally for one command

codegraph-vba affected

Traces import dependencies transitively to find which test files are affected by changed source files.

codegraph-vba affected src/utils.ts src/api.ts         # Pass files as arguments
git diff --name-only | codegraph-vba affected --stdin   # Pipe from git diff
codegraph-vba 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:

#!/usr/bin/env bash
AFFECTED=$(git diff --name-only HEAD | codegraph-vba affected --stdin --quiet)
if [ -n "$AFFECTED" ]; then
  npx vitest run $AFFECTED
fi

MCP Tools

When running as an MCP server, CodeGraph exposes a single toolcodegraph_explore. Measured agent behavior showed that one strong tool steers agents better than a menu of narrower ones — fewer mis-picks, and it saves context every session:

| Tool | Purpose | |------|---------| | codegraph_explore | 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 the call paths between them and a blast-radius summary. Surfaces dynamic-dispatch hops (callbacks, React re-render, interface→impl) grep can't follow. Name a file or symbol in the query to read its current line-numbered source, the same shape the Read tool gives you. |

The other tools (codegraph_node, codegraph_search, codegraph_callers, codegraph_callees, codegraph_impact, codegraph_files, codegraph_status) stay fully functional but unlisted by default — everything they return already arrives inline on codegraph_explore (its blast-radius section, the relationship map, a symbol's body as its callee list). Re-enable any of them for the MCP surface with the CODEGRAPH_MCP_TOOLS environment variable (e.g. CODEGRAPH_MCP_TOOLS=explore,node,search,callers), or use their CLI equivalents (codegraph-vba node / query / callers / callees / impact / files / status).

Even when the server's own root has no .codegraph-vba/ index, the tools stay available: pass projectPath to query any indexed project — a sub-service in a monorepo, or a second repo — in the same session. A path that has no index returns clean guidance to use built-in tools instead, so nothing fails loudly, and indexing stays your decision.


Library Usage

CodeGraph can be embedded directly. The npm package re-exports its programmatic API, so both import and require resolve the CodeGraph class in your own process — handy for embedding it in an app (e.g. an Electron main process).

import CodeGraph from 'codegraph-vba';
// CommonJS works too:
//   const { CodeGraph } = require('codegraph-vba');

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();

Lower-level building blocks are exported from the same entry point for callers that drive the graph directly: DatabaseConnection, QueryBuilder, getDatabasePath, initGrammars / loadGrammarsForLanguages, and FileLock.

Embedding requirements

  • Install from npm (npm i codegraph-vba) so the matching per-platform package — which carries the compiled library and its dependencies — is fetched alongside the shim.
  • The API runs on your runtime, so it needs Node 22.5+ for the built-in node:sqlite (Electron qualifies when its bundled Node is 22.5+). The CLI and MCP server are unaffected — they run on the self-contained bundled runtime.
  • TypeScript types ship with the package. As with any Node-targeting library, keep @types/node available and skipLibCheck: true (the common default).

Configuration

Next to none — CodeGraph is zero-config by default, with nothing to write or keep in sync to get started. Language support is automatic from the file extension; there's nothing to wire up per language. The one optional file is for mapping custom file extensions.

What it skips out of the box:

  • Dependency, build, and cache directoriesnode_modules, vendor, dist, build, target, .venv, Pods, .next, and the like across every supported stack — 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.

.gitignore can't drop a directory you've committed, though. For a vendored theme or SDK that's checked into the repo (e.g. a Metronic theme under static/), list it under exclude in codegraph.json — gitignore-style patterns, matched against repo-root-relative paths, honored on index, sync, and watch:

{
  "exclude": ["static/", "**/vendor/**"]
}

Custom file extensions

If your project uses a non-standard extension for a supported language — say .dota_lua for Lua, or .tpl for PHP — those files are skipped by default, because the extension isn't one CodeGraph recognizes. Map them with an optional codegraph.json at your project root:

{
  "extensions": {
    ".dota_lua": "lua",
    ".tpl": "php"
  }
}

Each value is a supported language id. The mappings merge on top of the built-in defaults and win on conflict, so you can also re-point a built-in (e.g. ".h": "cpp"). Commit the file to share the mapping with your team. A typo'd language or a malformed file is warned about and skipped — it never breaks indexing — and a project with no codegraph.json behaves exactly as before. Re-index (codegraph-vba index) after adding or changing mappings.

Telemetry

CodeGraph collects anonymous usage statistics — which tools and commands get used, which languages get indexed — to guide where language and agent support work goes. Never any code, paths, file or symbol names, queries, or IP addresses; usage is aggregated locally into daily totals before anything is sent, and the ingest endpoint is public code in this repo that enforces the documented field list. The installer asks up front; turn it off any time:

codegraph-vba telemetry off    # or: CODEGRAPH_TELEMETRY=0, or DO_NOT_TRACK=1

TELEMETRY.md lists every field, with the off-switches and the full data-handling story.

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 for the one-line install commands.

Supported Agents

The interactive installer auto-detects and configures each of these — wiring up the MCP server (which delivers its own usage guidance, so no instructions file is written):

  • Claude Code
  • Cursor
  • Codex CLI
  • opencode
  • Hermes Agent
  • Gemini CLI
  • Antigravity IDE
  • Kiro

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) | | Astro | .astro | Full support (frontmatter + script extraction, template component/call references, src/pages/ 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) | | R | .R .r | Full support (functions in every assignment form, S4/R5/R6 classes with methods, library/require imports, source() file references, call edges) | | Luau | .luau | Full support (everything in Lua, plus type/export type aliases, typed signatures, and Roblox instance-path require) |

Measured cross-file coverage

Impact and blast-radius queries are only as good as the dependency graph behind them, so coverage is measured rather than asserted. Fair coverage = the share of symbol-bearing source files that have at least one resolved cross-file dependent — something that imports, calls, references, or (through a framework convention) routes to them — on a real-world benchmark repo per language. The residual is always a genuine static-analysis frontier (runtime dynamic dispatch, reflection / DI containers, framework-convention entry points, vendored third-party code), never hidden by gaming the denominator.

| Language | Benchmark repo | Coverage | |---|---|---| | TypeScript / JavaScript | this repo | 95.8% | | Python | psf/requests | 100% | | Go | gin-gonic/gin | 96.6% | | Rust | BurntSushi/ripgrep | 86.7% | | Java | google/gson | 93.3% | | C# | jbogard/MediatR | 85.2% | | PHP | guzzle/guzzle | 100% | | Ruby | sidekiq/sidekiq | 100% | | C | redis/redis | 92.2% | | C++ | google/leveldb | 94.8% | | Objective-C | SDWebImage | 91.6% | | Swift | Alamofire | 95.3% | | Kotlin | square/okhttp | 96.2% | | Scala | gatling/gatling | 91.2% | | Dart | flutter/packages | 92.4% | | Svelte / SvelteKit | sveltejs/realworld | 100% | | Vue / Nuxt | nuxt/movies | 93.5% | | Astro | xingwangzhe/stalux | 93.0% | | Lua | nvim-telescope/telescope.nvim | 84.2% | | Luau | dphfox/Fusion | 92.2% | | Liquid | Shopify/dawn | 73.8% | | Pascal / Delphi | PascalCoin | 77.4% |

Framework routing is validated the same way, on a canonical app per framework: Express 100%, FastAPI 98%, Flask 100%, NestJS 96.8%, Gin 96.5%, Axum 100%, Rocket 93.8%, Vapor 100%, Laravel 92%, Rails 89.6%, React Router 100% — and the convention/reflection-heavy ones at their honest static-analysis ceiling: ASP.NET 83.9%, Spring 83.3%, Drupal 78.9%, Play 76.3%, Django 74.1%. SvelteKit, Vue/Nuxt, and Astro use file-based routing, so their page/endpoint coverage is the Svelte/SvelteKit (100%), Vue/Nuxt (93.5%), and Astro (93.0% — every src/pages/ file maps to a route node on the two validation repos) figures in the table above.

Troubleshooting

"CodeGraph not initialized" — Run codegraph-vba 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/ardelperal/codegraph-vba/main/install.sh | sh (macOS/Linux), irm https://raw.githubusercontent.com/ardelperal/codegraph-vba/main/install.ps1 | iex (Windows), or npm i -g @aroman22/codegraph-vba@latest.
  • codegraph-vba 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-vba/ folder) onto a local disk.

MCP server not connecting — Your agent starts the server itself, so you don't launch it by hand. Make sure the project is initialized and indexed (codegraph-vba status) and that the path in your MCP config is correct. If it still won't connect, re-run codegraph-vba install to rewrite the config.

MCP tool calls fail with Transport closed while codegraph-vba status/sync are healthy — almost always WSL2 with the project on a Windows drive (a /mnt/c or /mnt/d path), where the local socket CodeGraph uses to share one background server across sessions is unreliable. CodeGraph now falls back to serving the session in-process instead of dropping the connection, but if you still hit it, set CODEGRAPH_NO_DAEMON=1 in your MCP server's environment to skip the shared server entirely (each session runs in its own process). Moving the project onto the Linux-native filesystem (e.g. under ~/ instead of /mnt/) restores the shared server.

Missing symbols — The MCP server auto-syncs on save (wait a couple seconds). Run codegraph-vba sync manually if needed. Check that the file's language is supported and isn't inside a .gitignored or default-excluded directory (e.g. node_modules, dist).

Sharing one checkout between Windows and WSL — Don't point both at the same .codegraph-vba/: the background-server lock and the SQLite index are tied to the OS that wrote them, and SQLite locking across the WSL2/Windows filesystem boundary is unreliable. Give each side its own index in the same tree by setting CODEGRAPH_DIR to a distinct name on one of them — e.g. CODEGRAPH_DIR=.codegraph-win on Windows, leaving WSL on the default .codegraph-vba. CodeGraph skips any sibling .codegraph-* directory when indexing and watching, so the two never trip over each other.

Star History

License

MIT


Made for AI coding agents — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, and Kiro

Report Bug · Request Feature