Splits the monolithic tree-sitter.ts (3,358 lines) into modular files:
- 14 language config files under src/extraction/languages/
- 3 standalone extractors (Liquid, Svelte, DFM)
- Shared helpers and types modules to avoid circular imports
Also fixes a bug where Java's extractImport hook incorrectly set
handledRefs: true, preventing unresolved reference creation and
degrading codegraph_explore results for Java codebases.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a project directory is gitignored by a parent git repository, `git ls-files` returns no results even though files exist. Added detection for this scenario using `git rev-parse` and `git check-ignore` to fall back to filesystem walking when the project directory is ignored by an ancestor repo.
Changes guidance to recommend spawning Explore agents for exploration questions instead of using codegraph_explore/codegraph_context directly in main session to avoid filling up context with large amounts of source code. Adds completeness signal to codegraph_explore output so agents know not to re-read files that already have source code included.
Introduces a new MCP tool that performs deep code exploration in a single call, returning comprehensive context with full source code sections grouped by file and relationship mapping. Designed to replace multiple codegraph_node + file read operations for thorough understanding of code topics. Updates documentation to position explore as the primary tool for deep exploration questions.
Adds type annotation parsing to create references edges for parameter types, return types, and variable type annotations in TypeScript and other typed languages. Expands symbol extraction from queries to capture lowercase identifiers and filters out more common English words. Removes obsolete search utility tests.
Three issues discovered testing CodeGraph against a Shopify Liquid theme:
1. Callers/callees only traversed 'calls' edges, missing 'references' and
'imports' edges that Liquid extraction creates for {% render %} and
{% section %} tags. Expanded edge filter in getCallers/getCallees.
2. Context builder only ran text search as a fallback when semantic search
returned nothing. For template-heavy codebases, semantic search returns
irrelevant results (e.g., "Toast" for a header navigation query) while
text/path-based matching would find the right files. Now always runs
text search alongside semantic search with multi-term boosting.
3. MCP findAllSymbols only matched nodes by exact name, missing file nodes
whose basename (without extension) matched the symbol. This caused
callers to find zero results even with correct edges, since references
edges point to file nodes (e.g., "product-card.liquid") not component
nodes (e.g., "product-card").
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Java extraction:
- Handle Java method_invocation AST (receiver.method pattern)
- Support Java extends_interfaces and super_interfaces with type_list
- Create unresolved references for Java imports for cross-file resolution
- Extract interface inheritance via extractInheritance
MCP tools:
- Aggregate callers/callees/impact across ALL matching symbols (e.g. multiple
overloads or same-named methods in different classes)
- New findAllSymbols() helper for multi-symbol lookup
Graph traversal:
- Impact analysis now traverses into container children (class → methods)
so that callers of methods appear in the impact radius of their class
Other:
- Add deleteSpecificResolvedReferences() for precise cleanup after resolution
- Add 'instance-method' to resolvedBy union type
- Version bump to 0.6.8
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminate cross-language false positives in name resolution and deprioritize
test files in context building. Benchmarked on a Python+Rust codebase where
37% of edges were false positives from Python built-in methods resolving to
Rust functions (e.g., list.extend → Rust extend).
Resolution fixes (index-time):
- Filter Python built-in type method calls (list.extend, dict.update, etc.)
- Filter bare Python built-in method names (append, extend, pop, keys, etc.)
- Add language boundary checks to matchMethodCall strategies 1, 2, and 3
- Penalize cross-language matches: -80 points in findBestMatch (was 0)
- Reduce confidence for single cross-language exact matches (0.5 vs 0.9)
- Prefer same-language candidates in matchFuzzy
Context relevance fixes (query-time):
- Add isTestFile() utility detecting test files across Python/JS/TS/Go/Rust/Java
- Deprioritize test files in scorePathRelevance (-15 penalty)
- Reduce test file scores to 30% in context builder result merging
- Both skip deprioritization when query mentions "test" or "spec"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Testing showed semantic search produces significantly better results for
natural language queries that Claude writes. FTS alone often ranks
properties above their parent classes and misses conceptual matches.
Embeddings are now always on — the vector manager is created eagerly,
with model download and embedding generation still happening lazily.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminates anonymous error reporting functionality that was collecting stack traces and error context via Sentry. Removes all telemetry-related code, configuration options, and documentation references.
Name matching was creating false `calls` edges between unrelated modules
in monorepos because `findBestMatch()` had no concept of directory
proximity — functions with common names (e.g. `navigate`) in different
apps scored identically and resolved to whichever came first.
Adds path proximity scoring (shared directory segments) so same-module
candidates strongly win over cross-boundary ones, and lowers confidence
for distant matches so import-based resolution takes precedence.
Closes#67
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sentry error reporting can now be disabled by:
1. Declining during the interactive installer (sets CODEGRAPH_TELEMETRY=off
in the MCP server config env)
2. Setting CODEGRAPH_TELEMETRY=off in your shell environment
README updated with a Telemetry section documenting what is collected
and how to opt out.
Closes#68
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The installer previously ran `npm install -g` silently without user
consent. Now it asks for confirmation first, explains why the global
install is needed (hooks & MCP server), and gracefully skips if declined.
README updated to document this step.
Closes#69
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
extractSearchTerms now splits camelCase, PascalCase, snake_case, and
dot.notation into individual tokens (e.g. "getUserName" → ["user", "name"]).
Stop words expanded with code-specific noise words (code, file, function,
method, class, type, etc.) to improve search precision.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AI picking the entry point was unreliable. Now:
- Type a symbol name → dropdown shows matches
- Click a result (or Enter to pick first) → traces its call graph depth 3
- The user picks the starting point, the graph does the rest deterministically
No more AI guesswork. Search + graph traversal = reliable flows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Completely reworked the explore approach:
- Claude (or keyword search) finds ONE entry point, not a list of symbols
- getCallGraph(entry, depth=3) traces the actual call chain deterministically
- No more AI-guessed symbol lists, bridge passes, or relevance filtering
- Search result clicks also trace the full call graph from that point
The graph data was always accurate — the problem was AI trying to guess
the whole flow. Now AI just finds the starting point, graph does the rest.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Stricter prompt rules: only symbols directly in the execution path,
every symbol must call or be called by the next, no tangential features.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update Claude prompt to identify the entry point and return symbols in
execution order. The graph now centers on the entry point and auto-opens
its detail panel, giving users a clear starting point to trace the flow.
- Claude returns {entry, flow} instead of flat array
- Entry point is auto-selected and centered on load
- Detail panel opens immediately for the entry point
- Prompt asks for max 8-10 symbols in execution order
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of expanding all callers/callees of seeds (which pulls in noise
from hub nodes like getSession), now:
1. Find direct edges between Claude's seeds
2. Only add non-seed nodes if they bridge 2+ isolated seeds
3. Cross-connection pass discovers hidden edges between result nodes
4. No more unrelated callers of hub nodes polluting the graph
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds `codegraph visualize` command that launches a localhost web UI for
visually exploring code relationships. Users can ask natural language
questions like "how does authentication work?" and see the relevant code
flow rendered as an interactive graph.
Key components:
- Visualizer HTTP server (src/visualizer/server.ts) with REST API
- Single-page frontend with Cytoscape.js graph + highlight.js code preview
- Claude CLI integration for intelligent query interpretation
- Dark theme, right-click context menus, keyboard shortcuts
- Detail panel with source code, callers, callees, hierarchy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Traverses dependency graph to identify which test files depend on changed source files. Supports stdin input for git integration, custom test file patterns, and configurable traversal depth. Useful for targeted test execution in CI/CD pipelines.
Fixes#47 — "database is locked" after crash and MCP "not initialized"
when project IS initialized.
- FileLock: treat locks older than 10 minutes as stale regardless of PID
status, covering cases where PID was reused or kill signal check fails
- MCP server: log errors from tryInitializeDefault() to stderr instead of
silently swallowing, so transient open failures are diagnosable
- MCP server: retryInitIfNeeded() properly cleans up failed instances
before retrying, preventing resource leaks
- CLI: add 'codegraph unlock' command for manual lock file removal
Fixes#42 — tree-sitter can produce nodes with empty names (e.g. from
complex C/C++ declarators in header files). These nodes were silently
skipped at DB insert time, but their containment edges were still
inserted, causing a FOREIGN KEY constraint violation that crashed
indexing.
Two-layer fix:
- createNode() now returns null for empty names, preventing the node
and its edges from ever being created (Option A)
- storeExtractionResult() filters edges and unresolved refs to only
reference nodes that passed validation, as a safety net (Option B)
Fixes#54 — `codegraph init -i` crashes with "Fatal process out of memory: Zone"
on large codebases because all 16 tree-sitter WASM grammar modules were compiled
upfront by V8, exhausting the WASM Zone allocator.
Changes:
- initGrammars() now only initializes the tree-sitter WASM runtime (Parser.init()),
no longer eagerly loads all grammar files
- New loadGrammarsForLanguages() loads only grammars for languages actually present
in the project (e.g. a Dart project loads ~2-3 grammars instead of 16)
- Orchestrator detects needed languages after file scan, before parsing begins
- Embedding pipeline now uses quantized model (~67MB vs ~270MB) to further reduce
WASM memory pressure when embeddings are enabled
The serve command without --mcp prints a help banner. Writing this to
stdout breaks MCP stdio clients (like Cursor) that expect only JSON-RPC
on stdout. Move all banner output to stderr so stdout stays clean.
Fixes#43
command -v codegraph is unreliable inside npx because npx puts a
temporary binary in PATH. The check always passes, so the global
install is always skipped — which is the root cause of #37 and #38.
Fix: remove the check entirely, always run npm install -g.
- Revert configs (MCP, hooks) to use bare `codegraph` command
- Remove all npx references from configs and messaging
- Add preuninstall script that runs on `npm uninstall -g` to clean up
MCP server, permissions, hooks, and CLAUDE.md section
- Show uninstall instructions in post-install next steps
Global install is still attempted for bare `codegraph` convenience,
but now verifies the command is actually in PATH after install. If it
fails, users get clear actionable messages instead of silent swallowing.
Configs (MCP server, hooks) always use npx regardless — those never
break even if global install fails.
Remove the npm install -g attempt from the installer that silently
fails on many systems (permissions, PATH, node version managers).
All configs (MCP server, hooks, next-steps) now always use
npx @colbymchenry/codegraph. Global install offered as an optional tip.
Fixes#37, #38
- Fix defProc method lookup collisions when multiple classes share
method names (e.g. Create) by indexing qualified forms
- Remove overly broad 'Id' prefix filter that swallowed user-defined
symbols like Identifier or IdleTimer
- Use case-insensitive extension matching for DFM/FMX routing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Integrate main branch changes (WASM grammar architecture, centralized
resolution caches, SQLite adapter) with delphi-support branch. Pascal
grammar is now built as WASM and shipped in src/extraction/wasm/ for
consistency with the WASM-based grammar loading approach.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
web-tree-sitter has a known race condition when loading multiple WASM
grammars concurrently on Node.js 19+ (V8 10.8+). External scanner
symbols from one grammar can overwrite another's GOT entries, causing
"bad export type" errors for TypeScript, TSX, and other languages.
Replace Promise.allSettled(entries.map(...)) with a sequential for...of
loop so each grammar fully initializes before the next one starts.
Ref: https://github.com/tree-sitter/tree-sitter/issues/2338
Replace native tree-sitter with web-tree-sitter + tree-sitter-wasms for
universal cross-platform support. Add node-sqlite3-wasm as a fallback
when better-sqlite3 native bindings aren't available. Move better-sqlite3
and sqlite-vss to optionalDependencies so installs never fail.
Fix installer to use npx fallback when global npm install fails, so MCP
config, hooks, and quick-start instructions all work without the bare
codegraph command in PATH.
Fix tests: update schema version expectation, fix db test paths and
method names, extract MAX_OUTPUT_LENGTH as module constant, normalize
Windows path separators in import resolver.
Two major optimizations for the ref resolution phase:
1. Cache extractImportMappings() results per file path — previously
re-read and re-parsed the source file for every single ref from
that file (e.g. 100 refs from one file = 100 identical file reads)
2. Replace linear scan in matchFuzzy() with a lazily-built
case-insensitive Map index — O(1) lookup instead of iterating
all function/method/class nodes for every unresolved ref.
Also drop low-value prefix matching (confidence 0.3).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These are project-specific directories and should be configured per
project in .codegraph/config.json, not hardcoded globally. Delphi-
specific excludes (__history, __recovery, *.dcu) remain as global
defaults since they are analogous to __pycache__ for Python.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace this.nodes.find() with a lazily-built Map<name, nodeId> for
matching implementation bodies to their declarations. Reduces per-file
complexity from O(methods × nodes) to O(nodes) for index build + O(1)
per lookup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add _libs/**, libs/**, __history/**, __recovery/**, and *.dcu to
default exclude list. Delphi projects store external dependencies
in _libs/ or libs/ (often as Git submodules) and these should not
be indexed — same as node_modules for JS projects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two optimizations that eliminate the O(n²) bottleneck:
1. Add Pascal built-in filtering to isBuiltInOrExternal() — skips
resolution attempts for System.*, Vcl.*, Fmx.* and ~60 common
RTL identifiers (WriteLn, Create, Free, TObject, etc.)
2. Cache getNodesByKind() results during warm cache phase — matchFuzzy()
was calling the database 3 times per unresolved reference instead
of using the in-memory cache that warmCaches() already builds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Some .dpr templates use "program;" without a name, which produces an
empty moduleName in the AST. Fall back to the filename (without extension)
to prevent nodes with empty names that cause downstream FK constraint errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>