[1.0.0] - 2026-06-12
Security
- Closed a path-traversal hole where a symbolic link inside an indexed project that pointed outside the project root could make CodeGraph serve that out-of-root file's contents (for example a file under your home directory) to the AI agent. CodeGraph now resolves symlinks when validating file access and refuses to read anything whose real location is outside the project, while still allowing symlinks that stay within it. Thanks @sulthonzh. (#527)
- CodeGraph now indexes Spring configuration files (
application.properties/application.yml) by key only, and never includes their values incodegraph_exploreorcodegraph_nodeoutput. Previously a secret committed to one of these files — a database password, API key, or connection string with embedded credentials — could be surfaced to an AI agent that asked about nearby code, even though the agent never opened the file. The configuration keys are still indexed, so reference and impact analysis are unaffected; an agent that genuinely needs a value reads the file itself. Shopify Liquid{% schema %}blocks are likewise indexed by name only. (#383)
New Features
-
CodeGraph now indexes R (
.R/.r) — functions in every assignment form (name <- function(...),name = function(...), nested definitions), S4 / Reference / R6 classes with their methods,setGeneric/setMethodgenerics, top-level variables and constants,library()/require()imports,source()file references, and call edges — including calls inside tidyverse pipe chains. Statistical and research codebases get the full explore / impact / callers surface. (#828) (R) -
Workspaces holding multiple git repositories now index as a whole. Running
codegraph initat the root of a directory that contains several independent git repos — including the common "super-repo" layout where the parent repo's.gitignorehides the child repos to keepgit statusquiet — now indexes every nested project into one graph, with each child repo's own.gitignorerespected.codegraph syncand live file watching pick up changes inside the nested repos too (previously change detection only consulted the parent repo, so edits in child repos were invisible until a full re-index). Git repositories insidenode_modules(npm git-dependencies) remain excluded. (#514) -
codegraph_explorenow explains where a flow ends instead of going silent. When the symbols you ask about don't connect statically — because the code dispatches through a runtime mechanism like a computed call (handlers[action.type](...)), Python'sgetattr, a command/mediator bus (sender.Send(new DeleteCommand(...))), reflection, ornew Proxy— explore now announces the exact dispatch site (file and line) where the static path stops, and when the dispatch key is visible in the source it shortlists the likely runtime targets (for example pointing a MediatR command straight at itsHandler.Handlemethod). Detection is deterministic and runs only when a flow fails to connect; fully connected flows are unchanged, and nothing about indexing or the graph itself changes. Relatedly, a custom event bus whose emit and handler connect through a single synthesized hop now shows that hop explicitly (with the registration site) — it previously rendered nothing because the connection was "too short" for the flow section. (#687) -
Anonymous usage telemetry, documented field-by-field and easy to turn off. CodeGraph now collects a small set of anonymous usage statistics — which commands and MCP tools get used, which languages get indexed, which agents connect — so language and agent support work goes where real usage is. Never any code, file paths, file or symbol names, search queries, or IP addresses; usage aggregates locally into daily totals before anything is sent, and the ingest endpoint is public, auditable code in the repository that enforces the documented field list. The installer asks up front with a visible default-on toggle (and never re-asks); everywhere else a one-line notice prints before the first send. Disable any time with
codegraph telemetry off,CODEGRAPH_TELEMETRY=0, or the cross-toolDO_NOT_TRACK=1standard — off means off: nothing is recorded, nothing is sent, and buffered data is deleted.TELEMETRY.mddocuments every field. -
Subagents and non-MCP agents can now reach CodeGraph. Two new CLI commands —
codegraph explore "<symbols or question>"andcodegraph node <symbol-or-file>— print exactly what the matching MCP tools return (relevant symbols' source + call paths; one symbol's source + callers; file reads with line numbers), so any agent with a shell can use the graph. Andcodegraph installnow writes a small marker-fenced CodeGraph section into each agent's instructions file (CLAUDE.md/AGENTS.md/GEMINI.md) pointing at both surfaces — that file is what Task-tool subagents actually see, where the MCP server's own guidance only reaches the main agent. Measured on a delegated code-exploration task: subagents went from almost never using CodeGraph (~1 in 9 runs) to using it in every run, including runs with zero grep/file-reading fallback. The section is small, survives your own content, upgrades cleanly from the old long block, andcodegraph uninstallremoves it. Thanks @liuyao37511. (#704) -
The MCP tool list is now a focused default of four —
codegraph_explore,codegraph_node,codegraph_search, andcodegraph_callers. The other four (codegraph_callees,codegraph_impact,codegraph_files,codegraph_status) remain fully functional — the CLI and library API are unchanged, andCODEGRAPH_MCP_TOOLSre-enables any of them — but they're no longer listed to agents by default: measured agent behavior shows they're never or rarely picked, and the information they carry already arrives inline on the tools agents do use (explore's blast-radius section, node's dependents note, a symbol's own body as its callee list). A leaner list saves context tokens every session and steers agents to the right tool by presence alone. -
CodeGraph now goes quiet instead of failing loudly in unindexed projects. When an AI agent's session starts in a workspace that has no CodeGraph index, the MCP server now announces itself as inactive with a short note and lists no tools at all — instead of presenting the full toolset and erroring on every call, which taught agents to distrust CodeGraph even where it works. Querying another project that isn't indexed likewise returns clear guidance (use your regular tools for that codebase; the user can run
codegraph initthere to enable CodeGraph) instead of an error, and genuine internal errors now tell the agent to retry once rather than give up on CodeGraph entirely. Indexing stays your decision — agents are told not to run it themselves. (#769) -
Astro projects are now indexed.
.astrofiles previously weren't parsed at all — on a typical Astro site that left most of the codebase invisible to search, impact, andcodegraph_explore. CodeGraph now extracts the TypeScript frontmatter (functions, imports,getStaticPaths, …) and client-side<script>blocks, captures function calls and<Component>usages in template markup so cross-component dependencies trace end-to-end, resolves theAstroglobal andastro:*module imports as framework-provided, and mapssrc/pages/file-based routing to route nodes (.astropages and.tsendpoints, including[param]and[...rest]dynamic segments, with underscore-prefixed files correctly excluded). Validated on two real-world Astro sites with 93% measured cross-file coverage and every page mapping to its route. Thanks @xingwangzhe. (#768) (Astro) -
Same-named symbols across a monorepo's apps are no longer conflated. In a NestJS-style workspace with one
UserServiceper app,codegraph_callers,codegraph_callees, andcodegraph_impactnow report one section per distinct definition — each app's callers and blast radius under its own file-labeled heading — instead of a single merged list, and accept afileargument to focus exactly the definition you mean (likecodegraph_nodealready did). Impact in particular no longer overstates a change's blast radius by merging unrelated same-named classes. Thanks @Igorgro. (#764) -
Fixed a related source of cross-package wrong edges: PascalCase type references from plain
.tsfiles were being resolved as React components, which could link a file's own type alias to an arbitrary same-named class in another package (on one large monorepo this produced over a thousand wrong cross-package reference edges; 96% are now gone, and the remainder are genuine shared-model imports). Component resolution now applies only to references from JSX-capable files and never guesses between multiple candidates without a positional signal. The Svelte and Vue component resolvers had the same arbitrary-pick flaw (Vue resolved the first same-named.vuefile found anywhere in the tree) and now follow the same rule: same-directory first, otherwise only an unambiguous name resolves. Re-index a project to benefit. (#764) (TypeScript, React, Svelte, Vue) -
TypeScript and JavaScript class fields are now reported as properties instead of methods. A plain field like
public fonts: Fonts;previously extracted as a method, misrepresenting class shape and letting calls to same-named functions resolve to data fields (a boolean field namedisArraywas soaking upArray.isArray(...)call edges). Fields holding arrow functions or function expressions (onClick = () => {…}, including wrapped ones likeonScroll = throttle(() => {…})) correctly remain methods and their bodies are still analyzed. Field initializers are analyzed too, sohistory = createHistory()records its call — and JavaScript class fields, which previously produced no symbol at all, now appear in the graph. Re-index a project to benefit. (#808) (TypeScript, JavaScript) -
Callback registration through
thisnow resolves precisely in TypeScript and JavaScript:window.addEventListener("online", this.onOfflineStatusToggle)or an API object like{ mutateElement: this.mutateElement }produces a reference edge to the enclosing class's own method — never a same-named method on an unrelated class, and never a data field. Builds on the callback-registration support below. (#808) (TypeScript, JavaScript) -
Callback-registration coverage deepened across four more shapes: a
this.<member>registration whose method lives on a base class now resolves through the inheritance chain (bus.on("submit", this.handleSubmit)in a subclass links to the parent'shandleSubmit); Java and Kotlin method references to other classes (Handlers::onMessage,OtherClass::handle) resolve across files, withthis::andsuper::scoped to the defining class and references through a variable deliberately left out; and Swift bare callback names now match only the enclosing type's methods (implicitself), eliminating a class of wrong edges where a parameter likerequestlinked to a same-named method on an unrelated type. (Java, Kotlin, Swift, TypeScript, JavaScript) -
PHP string and array callables now register: a string passed to a callable-taking core function (
usort($items, 'cmp_items'),array_map('absint', …),call_user_func,spl_autoload_register, …) links to that function — including across files — and the array forms[$this, 'method']and[Foo::class, 'method']link to the named method (the$thisform resolves through the class and its parents). Strings passed to arbitrary functions are deliberately ignored: only known callable positions are trusted. Validated on WordPress core (+556 edges, every sampled edge a genuine registration). (PHP) -
Ruby lifecycle-hook symbols now register:
before_action :authenticate,after_save :reindex,around_create,validate :check,rescue_from(…, with: :handler)and friends link the symbol to the method it names — on the class itself or inherited from a parent (before_action :authenticatein a controller resolves toApplicationController's method).validates(plural) is excluded since its symbols name attributes, not methods. Validated on rails/rails (+385 edges, every sampled edge genuine). (Ruby) -
Method references to a type that needed no import now resolve: Java/Kotlin same-package references (
.concatMapMaybe(Maybe::just, …)), Kotlin companion-object members (KtHandlers::handle), and cross-file C++ member pointers (&TestSuite::RunSetUpTestSuite). Resolution stays anchored to the named type, so a same-named member on a different class never matches. (Java, Kotlin, C++) -
CodeGraph now sees where a function is registered as a callback, not just where it's called. A function name passed as an argument (
signal(SIGINT, handler),qsort(…, compare),addEventListener(…, onBlur)), assigned to a function pointer or field (ops->recv_cb = my_cb,OnClick := Handler), or placed in a struct initializer or handler table ({ .recv_cb = my_cb },{ "get", getCommand }) now produces a reference edge from the registration site to the function — socodegraph_callersandcodegraph_impactsurface callback wiring that previously looked like dead code. Works across all supported languages, including the language-specific forms: C/C++&fn, JavaClass::method, Kotlin::fn, Swift#selector, Objective-C@selector, Rubymethod(:fn), Scala eta-expansion, and Delphi/Pascal@HandlerandOnClick := Handlerevent wiring. Callers output labels these "via callback registration". Resolution is deliberately conservative: an ambiguous name produces no edge rather than a wrong one. Re-index a project to benefit. Thanks @zmcrazy. (#756) -
The
codegraph_nodeMCP tool can now read a whole source file like the built-in Read tool — only faster, served from the index. Pass a file path with no symbol and it returns that file's current source with line numbers (the same<n>⇥<line>shape Read produces, so an assistant can edit straight from it), narrowable withoffset/limitexactly like Read, plus a one-line note of which files depend on it (the file's blast radius). Use it anywhere you'd reach for Read on an indexed source file. PasssymbolsOnly: truefor just the file's structure. Configuration/data files (.yml/.properties) are summarized by key only, never dumped, so secrets in them are never surfaced. The agent-facing guidance was also retuned so assistants reach for codegraph while implementing a change (not only when answering questions), since one codegraph call returns the same bytes plus the blast radius, faster than re-reading the file. -
New
codegraph upgradecommand updates CodeGraph to the latest release in place — it detects how you installed (the standaloneinstall.sh/install.ps1bundle, npm, or npx) and does the right thing for each, on macOS, Linux, and Windows. Usecodegraph upgrade --checkto see whether an update is available without installing, orcodegraph upgrade <version>to move to a specific version. After upgrading it reminds you to re-index your projects so they pick up the newer engine's improvements. (#679) -
codegraph statusnow flags when a project's index was built by an older engine than the one you're running and recommends re-indexing (also surfaced incodegraph status --json), so you know when acodegraph index -forcodegraph syncwill add coverage a newer release introduced. -
Cross-file impact and blast-radius coverage now spans all 22 supported languages and 14 web frameworks, each validated on a real-world repo — see the new coverage table in the README. This release ships the cross-file resolution behind it, including Lua and Luau
require, Shopify OS 2.0 Liquid section templates, Delphi form code-behind, Rust cross-module calls and Rocket route macros, Swift Fluent relationships, and the SvelteKit / Nuxt / Vapor / Axum route conventions. The residual everywhere is genuine static-analysis frontiers (runtime dispatch, reflection / DI, framework-convention entry points), never hidden. -
C#
record structandreadonly record structdeclarations now index with the correctstructkind, and positional one-liner records (public record struct Money(decimal Amount);) index reliably in every form — previously a bodiless value-type record could be skipped entirely and could halt extraction of the declarations following it in the same file. (#831) (C#) -
C# types are now tracked by their namespace-qualified name. Same-named types in different namespaces — a domain entity and a DTO both called
CatalogBrand, say — are told apart instead of collapsing into one arbitrary match, so a reference resolves to the right one and impact no longer conflates them. (C#) -
ASP.NET Razor (
.cshtml) and Blazor (.razor) markup are now parsed for code relationships. A@model/@inherits/@injectdirective links the view to the C# view-model, base type, or service it names; a Blazor<MyComponent/>tag (plus@typeof(...)and genericTItem="..."arguments) links to the component class; and the C# inside@code { }/@functions { }/@{ }blocks is analyzed too, so services and types used in component logic are linked. A view-model, component, or service referenced only from markup is no longer reported as having no dependents, and editing it surfaces the views that use it. (ASP.NET, Blazor) -
A Razor/Blazor type reference now resolves through the component's
@usingnamespaces — including the folder's cascading_Imports.razor— so a simple name that exists in several namespaces lands on the right one. A@model/<MyComponent>/@codereference toCatalogBrandresolves to the@using'd DTO (BlazorShared.Models.CatalogBrand) rather than a same-named domain entity. (ASP.NET, Blazor) -
codegraph status --jsonnow also reports the running CLIversion, the index directory (indexPath), and alastIndexedtimestamp (ISO-8601, or null when nothing's indexed yet), so CI and scripts can pin the CLI version and check index freshness from a single command. A matchingCodeGraph.getLastIndexedAt()library method exposes the same freshness check without shelling out. Thanks @12122J and @eddieran. (#329) -
TypeScript service/RPC contracts defined as a tuple of generic types —
type MyServiceList = [Service<'query_apply_record', …>, Service<'apply_confirm', …>]— now index each entry's string-literal name as a searchable symbol. Previously these names existed only as type arguments, socodegraph query query_apply_recordfound nothing even though the names are the app's primary API surface. The pattern is common in typed RPC / BFF clients and mock servers where the types are the source of truth for a runtime proxy object. Utility types (Pick,Omit,Record) and route paths are deliberately left out to avoid noise. Thanks @jiezhiyong. (#634) (TypeScript) -
New
CODEGRAPH_DIRenvironment variable sets the per-project index directory name (default.codegraph). This lets one working tree hold two independent indexes — most usefully when you open the same checkout from both Windows and WSL, which can't safely share a single.codegraph/: the background-server lock and the SQLite database are tied to the OS that wrote them, and SQLite locking across the WSL2/Windows filesystem boundary is unreliable. SetCODEGRAPH_DIR=.codegraph-winon the Windows side, leave WSL on the default, and each keeps its own index in the same folder without clobbering the other. CodeGraph also skips any sibling.codegraph-*directory when indexing and watching, so neither environment trips over the other's data. Thanks @rrtt2323. (#636)
Fixes
- opencode on Windows now finds CodeGraph. The installer wrote opencode's global MCP entry to
%APPDATA%\opencode\, but opencode reads its config from~/.config/opencode/on every platform (honoringXDG_CONFIG_HOME), so the entry was invisible to it. Installs now write where opencode actually looks, andcodegraph install/codegraph uninstallboth clean a stale CodeGraph entry out of the old%APPDATA%location — other servers and comments in that file are left untouched. Thanks @fucknoobhanzo for the report and @WodenJay for the first patch. (#535) - The
codegraph_searchtool'skind: "type"filter — a value its own schema advertises — silently matched nothing; it now correctly finds type aliases. Thecodegraph_exploretool's parameter guidance also no longer suggests runningcodegraph_searchfirst, which contradicted explore's call-it-first design and cost agents an extra round-trip. - Symbols defined in Svelte and Vue
<script>blocks were reported one line below where they actually are — a function on line 3 was reported at line 4 — which offset every script-block symbol's location in search,codegraph_node, and explore output. Line numbers now match the file exactly. Re-index a project to benefit. (Svelte, Vue) - Doc comments are now captured for exported,
const-assigned, and decorated declarations, and the documentation a symbol carries is now clean across every supported language. Previously a comment aboveexport class X,export const fn = () => …, a plainconst fn = () => …, or a decorated Pythondef/class(@app.route(...),@dataclass) was dropped entirely — only comments directly above a plain declaration were kept. CodeGraph now finds the comment through theexport/const/ decorator wrapper. Comment-marker cleanup was also rounded out for every language CodeGraph supports: Rust/Swift/Kotlin doc lines (///,//!), Python/Ruby/shell#, Lua/Luau (--and--[[ ]]), and Pascal ({ }and(* *)) no longer leave stray markers in the stored text — validated end-to-end across all 19 code languages plus Svelte/Vue<script>blocks. (#780). Thanks @caleb-kaiser. - Go method calls made through a chained factory function now resolve to the correct type. A call like
New().Method()used to drop the receiver, so the chained method attached to a same-named method on an unrelated type — or didn't resolve. CodeGraph now captures Go return types (a pointer*Fooresolves toFoo, and a multi-return(*Foo, error)to its first result), infers the chained receiver's type from what the factory function returns, and resolves the method on it — including methods promoted from an embedded struct — creating the edge only when the type or an embedded type genuinely has the method. Existing Go indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Go) - Scala method calls made through a companion-object factory, a fluent chain, or a case-class
applynow resolve to the correct type. A call likeFoo.create().bar()orBuilder(cfg).bar()used to drop the receiver, so the chained method silently attached to a same-named method on an unrelated type — most often mis-attributing a standard-libraryOption/Iterator.map/.flatMap/.foreachonto your own same-named class. CodeGraph now captures Scala return types (a genericList[Foo]resolves to its containerList, a qualifiedpkg.FootoFoo), infers the chained receiver's type from what the inner call returns or constructs, and resolves the method on it — including methods inherited from a trait the type extends — creating the edge only when that type or one of its traits genuinely has the method (so a wrong inference produces no edge instead of a misleading one). Existing Scala indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Scala) - Rust method calls made through a chained associated function now resolve to the correct type. A call like
Foo::new().bar()orFoo::with(cfg).build()used to drop the receiver, so the chained method silently attached to a same-named method on an unrelated type — or didn't resolve. CodeGraph now captures Rust return types (-> Selfresolves to the implementing type), infers the chained receiver's type from what the associated function returns, and resolves the method on it — including methods provided by a trait the type implements (via the newimpl Trait for Typerelationships) — creating the edge only when the type or one of its traits genuinely has the method. Existing Rust indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Rust) - Dart method calls made through a static factory, a factory or named constructor, or a fluent chain now resolve to the correct type. A call like
Foo.create().bar()used to drop the receiver, so the chained method silently attached to a same-named method on an unrelated type — most often mis-attributing a standard-libraryOption/Iterator.map/.whereonto your own same-named class. CodeGraph now indexes Dart factory and named constructors (factory Foo.create(),Foo.named()) as first-class members so calls to them resolve, captures Dart return types (a genericList<Foo>resolves to its containerList), infers the chained receiver's type from what the inner call returns or constructs, and resolves the method on it — including methods inherited from a superclass or mixin — creating the edge only when that type genuinely has the method. Plain construction (Foo(...)) is still recorded as instantiation. Existing Dart indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Dart) - Objective-C methods called through a chained message send now resolve to the correct class. A call like
[[Foo create] doIt]used to drop the receiver, sodoItsilently attached to a same-named method on an unrelated class — most often a test helper or stdlib class. CodeGraph now captures Objective-C method return types and infers the chained receiver's type from what the inner message returns. For the ubiquitous[[X alloc] init]and singleton ([[X sharedInstance] …]) patterns — where the factory returnsinstancetype— the receiver is the classXitself, so the chained method resolves onX(including methods inherited from a superclass), creating the edge only when the class genuinely has the method. Existing Objective-C indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Objective-C) - Pascal/Delphi methods called through a chained factory call now resolve to the correct class. A call like
TFoo.GetInstance().DoIt()used to drop the receiver, soDoItsilently attached to a same-named method on an unrelated class. CodeGraph now captures Pascal return types and infers the chained receiver's type from what the factory function returns — resolving to the declared type (including an interface return likeIFoo), and for a constructor (TFoo.Create().…) or a typecast (TFoo(x).…) to the classTFooitself, since both yield aTFoo. The edge is created only when that type genuinely has the method (so a wrong inference produces no edge). Existing Pascal/Delphi indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Pascal/Delphi) - Pascal/Delphi paren-less method calls are now tracked. Pascal lets a no-argument method or procedure drop its parentheses (
Obj.Free;,List.Clear;,TFoo.GetInstance.DoIt;), which previously weren't recorded as calls at all — so callers, impact, and trace missed them. CodeGraph now extracts these, scoped to statement position so a field or property access (which looks identical) is never mistaken for a call. On a real Delphi codebase this added ~1,100 previously-missing call edges with no false positives. Existing Pascal/Delphi indexes should be re-indexed (codegraph index -f) to benefit. (Pascal/Delphi) - Pascal/Delphi calls inside a standalone procedure or function (one with no
interfacedeclaration, defined only in theimplementationsection) are now attributed to that routine instead of the whole file. Previously such a routine had no symbol of its own, so everything it called was lumped under the unit —codegraph_callersreturned the file, and impact couldn't tell which routine was responsible. These routines are now indexed and their calls attributed correctly. Existing Pascal/Delphi indexes should be re-indexed (codegraph index -f) to benefit. (Pascal/Delphi) - Chained method calls now resolve when the chained method is inherited from a superclass or declared on an interface/protocol the receiver's type conforms to — for example a call on a sealed-subclass instance (
Either.Right(x).combine(...)) that invokes a method defined on its parent type. Previously these chains found no caller edge even though the factory's type was known, so the call was invisible to callers, impact, and trace. CodeGraph now walks the type's supertypes (itsextends/implementsrelationships) to find the method, creating the edge only when a supertype genuinely declares it (so a wrong inference still produces no edge). This makes Java, Kotlin, and C# factory and fluent chains more complete. Existing indexes should be re-indexed (codegraph index -f) to benefit. (#750) - Swift method calls made through a static factory, fluent chain, or constructor now resolve to the correct class. A call like
Foo.make().draw()orFoo().draw()used to drop the receiver, so the chained method silently attached to a same-named method on an unrelated class — or didn't resolve at all. CodeGraph now captures Swift return types and infers the chained receiver's type from what the inner call returns (or the constructed type), creating the edge only when that class genuinely has the method (so a wrong inference produces no edge instead of a misleading one). Existing Swift indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Swift) - C# method calls made through a static factory or fluent chain now resolve to the correct class. A call like
Foo.Create().Bar()orJObject.Parse(s).Property(...)used to lose the receiver's type, so the chained method didn't resolve and the call was invisible to callers/impact/trace. CodeGraph now captures C# return types and infers the chained receiver's type from what the inner call returns, creating the edge only when that class genuinely has the method (so a wrong inference produces no edge). Existing C# indexes should be re-indexed (codegraph index -f) to benefit. (#750) (C#) - Kotlin method calls made through a companion-object factory or fluent chain now resolve to the correct class. A call like
Foo.getInstance().bar()orConfig.create(opts).build()used to drop the receiver entirely, so the chained method silently attached to a same-named method on an unrelated class — or didn't resolve at all — corrupting callers, impact, and trace. CodeGraph now captures Kotlin return types and infers the chained receiver's type from what the inner call returns, creating the edge only when that class genuinely has the method (so a wrong inference produces no edge instead of a misleading one). Existing Kotlin indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Kotlin) - Java method calls made through a static factory or fluent chain now resolve to the correct class. A call like
Foo.getInstance().bar()orConfig.create(opts).build()used to lose the receiver's type, so when two classes had a same-named method the call silently attached to whichever was indexed first — or didn't resolve at all — corrupting callers, impact, and trace. CodeGraph now captures Java return types and infers the chained receiver's type from what the inner call returns, creating the edge only when that class genuinely has the method (so a wrong inference produces no edge instead of a misleading one). Covers factories and fluent builders that take arguments (hashKeys().arrayListValues()), including builders that return a nested type. Existing Java indexes should be re-indexed (codegraph index -f) to benefit. (#750) (Java) - PHP: a method called through a chained static factory —
Cls::for($x)->method(...), the canonical Laravel per-credential / per-tenant client idiom — now records a caller edge. Previously the receiver type (whatfor()returns) was never recovered, socodegraph_callersreturned nothing for the method and the call was invisible tocodegraph_impact. CodeGraph now captures PHP return types —: self/: staticresolve to the declaring class,: SomeClassto that class — and resolves the chained method on the factory's result, creating the edge only when that class actually has the method (so a wrong inference produces no edge). Existing PHP indexes should be re-indexed (codegraph index -f) to benefit. Thanks @cvanderlinden. (#608) (PHP) - Search relevance: including the project name in a query (a user naturally writes
MyApp backend routes) no longer buries the part of the codebase the query is actually about. The project name lexically matches whatever stack embeds it — aMyAppFrontend/directory, aMyAppAppclass — and it was over-weighted two ways: a single PascalCase word was scored once per sub-token (my/app/myapp), so one concept boosted that path several times over; and the name carried full path / disambiguation weight even though it names the whole repo, not any symbol. Now path relevance counts each query word once, and a word matching the project name (derived fromgo.mod,package.json, or the repo directory) is dropped from path scoring and fromcodegraph_explore's type-disambiguation bias — unless it's the only term, so a bare project-name search still works. In a mixed-stack repo, a backend question now surfaces the backend even with the project name in the query. Thanks @MiNuo1. (#720) - Go: a function called only from inside an anonymous closure — a cobra
RunE: func(…) {…}handler, a goroutine literal, or a callback closure stored in a package-levelvar— now shows its real caller. Previously the call leaked to the file node, socodegraph_callersandcodegraph_impactreported such a function as having no meaningful caller; the call is now attributed to the enclosing declaration, so editing the function surfaces the closures that use it. Existing Go indexes should be re-indexed (codegraph index -f) to benefit. Thanks @Cyclone1070. (#693) (Go) - Indexing no longer aborts when a
.gitignorecontains non-UTF-8 bytes or an unparseable pattern. A.gitignoretransparently encrypted in place by corporate DLP / endpoint-security software (a common enterprise scenario) — or one with a stray pattern the matcher can't compile (\[, producing "Unterminated character class") — used to crash the entiresync/indexwith a screen of garbled bytes and never name the offending file, leavingFiles: 0 / Nodes: 0. CodeGraph now skips a.gitignorethat isn't valid UTF-8 text whole, drops only the individual unparseable patterns from a text one, and logs a warning naming the file — indexing continues either way. Thanks @zhanghang-9527. (#682) - C++ method calls made through a singleton, factory, or chained getter now resolve to the correct class. A call like
Foo::instance().bar(),WidgetFactory::create().draw(),openSession()->run(), or the same stored in anautolocal first, used to lose the receiver's type — so when two classes had a same-named method the call silently attached to whichever was indexed first (or didn't resolve at all), corrupting callers, impact, and trace. CodeGraph now infers the receiver's type from what the inner call returns (capturing C++ return types for the first time) and creates the edge only when that class genuinely has the method, so a wrong guess produces no edge instead of a misleading one. Covers singletons and self-returning accessors, factories that return a different type, free-function factories,make_unique/make_shared/new/ direct construction, and single-level member chains. Existing C/C++ indexes should be re-indexed (codegraph index -f) to benefit. Thanks @stabey. (#645) (C/C++) - The shared background server no longer logs a scary-looking
[error] … undefinedline on every session start. Attaching to the shared daemon is normal, healthy behavior, but the informational message was being surfaced by MCP hosts (Claude Code and others) as an error; it's now silent by default — setCODEGRAPH_MCP_LOG_ATTACH=1to surface it when debugging daemon attach. Thanks @mturac. (#618) - On Windows, CodeGraph's background processes no longer pile up without bound and saturate CPU over a long session. When the editor or agent that launched CodeGraph exited, its helper process couldn't tell its parent had gone — Windows reports process lineage differently than macOS and Linux — so the helper kept running, the shared background server never saw the client disconnect, and its idle timer never fired to shut it down. CodeGraph now detects parent-process exit directly on Windows, so helpers and the idle background server wind down promptly, the same as they already did on macOS and Linux. (#692, #576, #680)
- The MCP server now shuts down cleanly when its editor/agent connection drops abruptly, instead of risking an orphaned process that pins a CPU core. Editors talk to a stdio MCP server over a socket; if that socket failed with an error rather than closing cleanly — which can happen when the editor window is reloaded or the launching process is killed — the server didn't treat it as a disconnect and could be left running. CodeGraph now treats any failure of its input stream as a shutdown signal and tears the stream down, so an orphaned server exits promptly. (#799)
- The shared background server has two further safeguards against ever lingering: it now drops a client the moment it detects that client's process is gone (even if the disconnect arrived uncleanly — a force-quit or a dropped connection that never closed the socket), and it won't stay running indefinitely with clients attached but no activity. Together these guarantee it always winds down, on every platform. (#692)
- A session no longer loses CodeGraph when the shared background server is restarted out from under it — for example when your MCP host (opencode and others) stops and restarts the server as you open another session. Previously the affected session's connection died silently and any request in flight at that moment hung; now CodeGraph keeps that session working by serving it locally, so the tools stay available without restarting the session. (#662)
- React Native native→JS events now connect through the common
sendEvent(context, "X", body)wrapper. Many libraries (react-native-device-info and others) wrap the event emitter behind a helper whose.emit(eventName, …)takes a variable, so the matcher — which looked for.emit("literal", …)— missed it; the literal event name actually lives in the wrapper call. Now a native method that firessendEvent(…, "batteryLevelChanged", …)links to the JSaddListener('batteryLevelChanged', …)handler, so editing the native emitter surfaces the JS subscriber. (React Native) - React Native / Expo cross-language bridges are more complete and more precise. An Expo Module method declared with a generic type — Android's
AsyncFunction<Float>("getBatteryLevelAsync")— is now indexed (the<Float>used to defeat the matcher, so every Android Expo method was dropped and a JS call resolved only to the iOS Swift impl). The iOS and Android implementations of the same JS-visible method — both Expo Modules and classic NativeModules (@ReactMethodon Android, the matching method on iOS) — are now linked to each other, so a JS call that resolves to one platform still reaches the other and editing either platform's native code surfaces the JS caller. And aType.memberstatic read in native code (e.g. Android'sBatteryManager.EXTRA_LEVEL) no longer falsely links to a coincidentally same-named class in another language (a webBatteryManager) — type references stay within a language family, while genuine cross-language bridges (config→code, JS↔native calls) are unaffected. (React Native, Expo) - A TypeScript/JavaScript reference or import no longer gets mis-linked to a same-named class in a native language. In a React Native / Expo repo that has both a TypeScript
TestRunnertype and a KotlinTestRunnerclass, a TS reference toTestRunner— or animport Reactsitting next to a SwiftReact— used to resolve onto the native symbol (the component resolver matched any same-named class regardless of language, and import statements weren't language-checked at all). References and imports now stay within their language family, so they land on the right symbol while genuine cross-language bridges (JS↔native calls, config→code) are untouched. A C/C++#include "Foo.h"likewise no longer resolves to a same-named header from another platform (an iOS Objective-CFoo.h). (React Native, Expo, TypeScript, C/C++) - Native includes and Kotlin Multiplatform imports now resolve to the correct file in multi-platform projects. A C/C++
#include "Foo.h"now resolves to the header in the including file's own directory first (the C quoted-include rule), so when a module ships a same-named header per platform (a Windows, an Apple, and an AndroidFoo.hside by side) the local one correctly shows its dependents instead of an arbitrary other-platform header looking like the dependency. And a Kotlin Multiplatformexpectdeclaration is no longer reported as having no dependents: acommonMainimport now resolves to thecommonMainexpect(matched within the importing source set) rather than being absorbed by one platform'sactual. (C/C++, Kotlin) codegraph affectednow reports the tests and files that actually depend on your changes. It used to follow onlyimportstatements — but those never cross file boundaries in CodeGraph's graph — so it returned no affected tests for any change, in every language. It now traces the real cross-file usage graph (calls, references, instantiations, and classextends/implements), sogit diff --name-only | codegraph affectedsurfaces the test files that exercise the changed code. Circular-dependency detection, which had the same blind spot, now works too.- Blast radius, callers, and
codegraph affectednow recognize far more of the dependencies that were already in your code. A symbol now counts as a dependency whether it's called, used only in a type annotation inside a function body (const items: Foo[] = []), imported and placed in a registry array or passed as an argument, used as a JSX component, simply re-exported from a barrel (export { X } from './x'), or pulled in as a namespace (import * as ns from '@/x') — including through tsconfig path aliases like@/. Previously only called, instantiated, or signature-typed symbols created a cross-file link, so a file that used a dependency in any other way could look like it depended on nothing — and the file that defined a widely-used symbol could look like nothing depended on it. The graph still indexes exactly the same symbols; it just connects the ones that were already there. (TypeScript/JavaScript) - The same completeness fix now applies to Python: a name brought in with
from module import Xis recorded as a dependency on that module even whenXis only stored in a list/dict, passed as an argument, used as a decorator, or re-exported through an__init__.py. Previously Python linked only imports that were called or instantiated, so a module consumed purely by value — or only re-exported — looked like nothing depended on it. codegraph_callers(and thecallerscommand) now lists the places a class is instantiated, not just where it's imported. Constructing a class —Foo(...)in Python,new Foo()elsewhere — is calling its constructor, so asking who calls a class now returns the construction sites, andcodegraph_callees/ trace cross the instantiation the same way. Previously a class's instantiation sites were invisible tocallers, so "what breaks if I change this class?" could come back empty even when the constructor was called from many places. Works on your existing index — no re-index needed. (#774)- Rust impact and
codegraph affectednow connect far more of the module graph. Struct literals (Widget { n: 1 }) are recorded as instantiations; ause/pub usebrings its item into the dependency graph — so apub usere-export hub (amod.rsre-exporting its submodules) depends on the modules it re-exports — resolved by Rust module path (crate::/self::/super::), so a re-export of a common name likereadlinks to the right module instead of a same-named symbol elsewhere; and trait dispatch reaches implementations — a struct whose methods cover a trait's is treated as implementing it, and a call through&dyn Traitresolves to the concrete method. Previously a Rust type linked only when called or used in a type position, so structs built by literal, modules surfaced only throughpub use, and trait-only implementations looked like they had no dependents. (#584 for Rust traits) - Rust cross-module function calls now resolve to the right file. A call to a sibling submodule's function —
users::router(), the common router-assembly / handler-registration pattern wheremod users;makesusersa child of the current module — is now resolved relative to the current module, not only the crate root. Deeper module-path calls (database::profiles::find()— thedb.run(|c| …)data-access shape) now resolve too; these were being discarded before resolution even ran, because the path's leaf function name was never checked. Previously such a call linked to nothing, so a module reached only asmodule::path::function()looked like it had no dependents; a web app wired this way (Axum, Rocket, and similar) now surfaces its handler and data-access modules' real callers. (Rust) - Rocket route handlers now connect to where they're mounted. A handler registered in a
routes![a::b::handler, …]orcatchers![…]macro used to be invisible — the macro body is a raw token tree, so the handler looked like it had no caller (Rocket mounts it at runtime) and its file showed no dependents. The handler paths are now read out of the macro and linked to themount/registercall, so editing a Rocket handler surfaces its route registration and a routes module is no longer reported as unused. (Rust, Rocket) - SvelteKit pages now connect to their server
loadfunctions. SvelteKit wires a+page.server.js/+page.jsload(and formactions) to the sibling+page.svelte'sdataby file path, with no import between them — so editing aloadpreviously showed no impact on the page it feeds. Each page is now linked to theload/actionsin its own route directory (and likewise for+layout), so editing a loader surfaces the page that renders its data, and tracing a page reaches its server-side data source. (Svelte, SvelteKit) - Nuxt nested components are now connected to where they're used. Nuxt auto-imports a component in a subdirectory by a directory-prefixed name —
components/media/Card.vueis used in templates as<MediaCard/>— but it was tracked by its file name (Card), so the usage didn't resolve and the component looked unused. PascalCase component tags (<MediaCard>,<NavBar>) in a.vuetemplate are now matched, falling back to the Nuxt directory-prefixed name, so editing a nested component surfaces every page and component that renders it. (Vue, Nuxt) - Lua and Luau
requirecalls now connect to their module files. A dotted module path (require("telescope.config")→telescope/config.luaor.../config/init.lua) and a Roblox/Luau instance-path require (require(script.Parent.Signal)→ theSignalmodule) now link to the file they load, so editing a module surfaces every file that requires it. Previously requires resolved to nothing, so a Lua/Luau module looked like it had no dependents. (Lua, Luau) - Shopify OS 2.0 sections now connect to the JSON templates that use them. Modern Shopify themes define templates as JSON (
templates/*.json, plus section groupssections/*.json) that list sections bytyperather than with a{% section %}Liquid tag, so a section used only from a JSON template was reported as having no dependents. Those JSON files are now read and each sectiontypeis linked to itssections/<type>.liquid, so editing a section surfaces the templates that render it. (Liquid, Shopify) - Delphi form definitions now connect to their code-behind units. A
.dfm(VCL) or.fmx(FireMonkey) form is owned by its same-named.pasunit through the{$R *.dfm}directive rather than ausesclause, so a form file used only as a definition was reported as having no dependents. The unit is now linked to its form, so editing a form surfaces the unit that owns it. (Pascal/Delphi) - Swift property wrappers and attributes are now connected. A
@Argument/@Published/@State/ custom@propertyWrapperon a property — and attributes on types, methods, and functions (@objc,@MainActor, …) — now record a dependency on the wrapper/attribute type. Previously these were dropped entirely (Swift attributes parse differently from other languages, and stored properties weren't being inspected), so the wrapper type looked unused and the file using it depended on nothing — a big gap for SwiftUI and argument-parser-style code. - Swift Fluent relationship models are no longer orphaned. A type referenced only through a property-wrapper argument —
@Siblings(through: AcronymCategoryPivot.self, …), the many-to-many pivot/join model — now records a dependency on that type. Previously only the wrapper itself (Siblings) and the property's declared type were captured, so a pivot model reached solely through the relationship looked like nothing depended on it and editing it surfaced no impact. (Swift, Vapor/Fluent) - Java annotations are now connected. Annotation definitions (
@interface Foo) are indexed as types, and every@Foousage on a class, method, or field is recorded as a dependency on it. Previously neither side was captured — annotation usages were dropped (they live inside the declaration's modifiers) and@interfacetypes weren't indexed at all — so annotation-driven code (Spring@GetMapping, JPA@Entity, Gson@SerializedName, …) showed the annotation as having no users and the annotated class as not depending on it. - Kotlin Multiplatform
expect/actualdeclarations are now connected. A platform implementation —actual fun,actual class, or anactual typealiasin ajvm/native/js/wasmsource set — is linked to the commonexpectdeclaration it fulfills (including the common case of anexpect classfulfilled by anactual typealias). Previously a caller in common code resolved to theexpectdeclaration, so every platformactuallooked like it had no dependents and editing one showed an empty blast radius; now changing a platform implementation surfaces the common API and everything that uses it. (Kotlin) - Scala impact and
codegraph affectednow connect the type graph that typeclass-style code is built on. A parameterized supertype (trait Monoid[A] extends Semigroup[A] with Serializable) now links to each parent; a type used in aval/defsignature, as a type argument, or as a context bound (def f[A: Monoid]) — including the trailing implicit parameter list ((implicit M: Monoid[A])) where typeclass instances are passed — now records a dependency; andnew T[...] { … }counts as an instantiation. Previously Scala linked only plain calls and bare, non-generic supertypes, so a trait extended with type parameters, used as a type, or required as an implicit looked like nothing depended on it — which on a typeclass-heavy codebase (cats, algebra) was most of the graph. (Scala) - PHP impact and
codegraph affectednow understand namespaces anduseimports. Classes are tracked by their namespaced name, so the many same-named classes a framework defines (Laravel has 7+Factoryinterfaces, severalDispatchers, across namespaces) are told apart instead of collapsing into one arbitrary match. Ause App\Contracts\Cache\Factory;now records a dependency on exactly that class — so a contract or interface that's imported and constructor-injected (the dependency-injection pattern) is no longer reported as having no dependents — and parameter, property, and return type-hints are recorded too. Previously PHP ignored namespaces entirely and linked only calls,new, and inheritance. (PHP) - Objective-C impact and
codegraph affectedare dramatically more complete. Four gaps are fixed: a single-argument message ([cache storeImage:key]— the most common call form) now matches itsstoreImage:method instead of dropping the colon; a class-message receiver ([SDImageCache sharedCache],[[Foo alloc] init]) now records a dependency on the class, whose@interfacelives in the header;#import "Foo.h"now resolves to the header file, so a header is no longer reported as having no dependents; and class-method message calls now resolve through the receiver type. Together these took typical libraries from a third-to-half of their files showing real dependents to ~90%. (Objective-C) - A type referenced only through a static member or enum value now records a dependency. Reading an enum value (
MediaKind.video), a static constant (Colors.red,JsonScope.EMPTY_DOCUMENT), or a class constant (Foo::BAR) now links to the type — previously only method calls andnewdid, so a type or enum used purely by value (enum-heavy APIs, constants classes — a very common pattern) looked like nothing depended on it. Applies to Java, C#, Kotlin, Swift, Scala, Dart, PHP, and C++. - Dart impact and
codegraph affectednow follow mixins and method type annotations. Awithmixin — Dart's core composition mechanism, which Flutter is built on — now records a dependency, so editing a mixin surfaces every class that mixes it in (the wholewithclause used to be dropped, and a class declaredwith Malone even lost its real superclass link). And types used in a method's parameters or return value now link to their definition, so a class or enum referenced only as a type — not constructed or called — is no longer reported as having no dependents. (Dart) - C++ free functions are now indexed under their real name. A function written with a qualified-type parameter (
std::string TableFileName(const std::string& dbname)) or anauto … -> std::stringtrailing return type was mistakenly named after that type (string), so calls to it never resolved,codegraph_nodecouldn't find it by name, and the file defining it looked like nothing depended on it. The function now keeps its real name, so cross-file calls, callers, and blast radius work — a meaningful gain for any namespaced C++ codebase (this is how most free functions in a library look). (C++) - Ruby impact and
codegraph affectednow follow mixins andrequires.include,extend, andprependof a module — Ruby's primary composition mechanism (ActiveSupport concerns,Comparable,Enumerable) — now record a dependency on that module, so editing a concern surfaces every class that mixes it in; previously these were read as a call to a method namedinclude, so a module whose methods are exercised only by application code looked like nothing depended on it. Andrequire "lib/foo"/require_relative "../foo"now link to the required file, so a file pulled in only by arequire(config-loaded components, gems that don't autoload) is no longer reported as having no dependents. Together these took a typical gem from ~71% of its files showing real dependents to ~100%. (Ruby) - C#
recordtypes are now indexed.record,record class, andrecord structdeclarations (everywhere in modern C# — DTOs, value objects, CQRS messages, MediatR notifications) were previously skipped entirely, so every reference, generic type argument (IEnumerable<MyRecord>), andnew MyRecord(...)pointed at nothing and the file defining a record looked like it had no callers or dependents. (#237) - C# is now parsed with an up-to-date grammar that understands C# 12 primary constructors. A class or struct written as
class OrderService(IRepo repo, [FromKeyedServices("primary")] ICache cache) { … }is now indexed reliably — previously the constructor parameter list confused the parser and could drop the whole class (and all of its methods) from the index, most often exactly when a parameter carried an attribute, as in the ASP.NET keyed-dependency-injection pattern. The primary-constructor parameters are also recorded as dependencies, so the services a type is constructed with show up in its blast radius and "who depends on this contract" answers. Method return types, base types, and members all continue to resolve, and#if-guarded members in multi-targeting code keep parsing correctly. (#237) - Go interfaces now connect to their implementations. Go has no
implementskeyword — a type satisfies an interface just by having the right methods — so CodeGraph now infers that link: a struct whose methods cover an interface's method set is treated as implementing it, and a call through the interface (API.Marshal(...)) reaches every concrete implementation. This means a type used only via an interface (the common plugin/strategy pattern — e.g. JSON-codec or renderer implementations selected at runtime) is no longer reported as having no callers or no dependents, and impact now flows from an interface method to the implementations behind it. (#584) - Go now records cross-package struct creation. A composite literal like
render.XML{...}orpkga.Widget{...}— including ones registered in a package-levelvar registry = map[string]R{...}— now links to the package that defines the type. Cross-package function calls and type references already resolved; this closes struct instantiation, so a package whose types are only constructed elsewhere (a common pattern for interface implementations) is no longer reported as having no dependents. Go type conversions such as(*Wrapped)(x)now link to the converted-to type as well. - Python now follows whole-module imports —
from . import certsthencerts.where(), orfrom pkg import subthensub.run(). Calls and attribute access through an imported submodule now resolve to that submodule, and importing a module is recorded as a dependency on it even when the member you use is itself re-exported from a third-party package. This also fixed Python relative-import path resolution generally (from .sub.mod import x), socodegraph affectedand impact see the real module graph of a package. - Python now also links a whole-module absolute import (
import conduit.apps.signals) to that module's file, not justfrom x import y. A module imported by its dotted path — common in package setup and side-effect imports — is no longer reported as having no dependents. Standard-library imports (import os) correctly create no edge. (Python) - Python
from package import submodulenow links to that submodule's file, resolved through the import's package so it lands on the right one when same-named modules exist in sibling packages (the FastAPI / Django router-aggregator pattern:from app.api.routes import authenticationwith an unrelatedauthentication.pyelsewhere). So a route/handler module pulled in only by an aggregator is no longer reported as having no dependents. (Python) - Python now records the actual call edge for a function invoked through an imported module —
from pkg import module(orimport pkg.module) followed bymodule.func(), a common testing and namespacing pattern. Previously only the module-level dependency was tracked, socodegraph_callers,codegraph_callees, and impact on the target function came back empty even though the import itself resolved. (#578) (Python) - Django
include('app.urls')now records a dependency from the project URLconf onto the included app'surls.py, so an app's routes module is no longer reported as having no dependents and editing it surfaces the project that mounts it. (Django) - A chained method call (
builder.Services.AddCoreServices(...)) now resolves to its definition. Previously only a single-segment receiver (obj.method()) resolved, so a call through a property/member chain — very common for C# extension methods like ASP.NET dependency-injection registration (AddCoreServices/AddWebServices) and Guard clauses — found no definition. (C#, and any language with chained calls) - A renamed default import (
import articlesController from './article.controller'where the module doesexport default router) now records a dependency on the imported module. Previously only named imports linked, so a module consumed only through a default import — the standard Express/NestJS route-controller pattern — looked like nothing depended on it. External packages (import React from 'react') still create no edge. (TypeScript/JavaScript) - The background file watcher no longer exhausts your machine's file-descriptor budget. On macOS it previously kept one open file handle per watched file, so on a large project the running MCP server could pile up tens of thousands of handles and blow past the system-wide limit — at which point unrelated apps (your shell, editor, Docker, browser) started failing with "too many open files" until the codegraph process was killed. The watcher now uses a single recursive watch on macOS and Windows, and bounded per-directory watches on Linux, so its cost stays flat no matter how large the project is. (#644, #496, #555, #628, #579)
- Indexing a project with very symbol-dense files (tens of thousands of functions or methods in a single file) no longer runs out of memory. The step that links dynamic call relationships used to load every function and method into memory at once, which could exhaust the heap and abort indexing with "JavaScript heap out of memory" on large or generated codebases; it now streams them, so memory stays flat no matter how many symbols the project has. (#610)
- Indexing a very large repository no longer aborts during its first sync with a "too many SQL variables" error. (#540)
- Files under directories with non-ASCII names (for example CJK characters) are no longer silently skipped during indexing. (#541)
- The
.codegraph/index folder no longer cluttersgit status: its generated ignore file now excludes everything in the folder except itself, so the database,daemon.pid, sockets, and logs stop showing up as untracked changes. (#492, #484) - Projects initialized by an older version now get that fix automatically: a
.codegraph/.gitignorewritten before this change — which listed only the database, cache, and logs and so let the daemon'sdaemon.pidget committed — is upgraded in place the next time you run any CodeGraph command. A.gitignoreyou've customized yourself is left untouched. (#788) - SAP HANA
.xsjs/.xsjslibfiles are now indexed as JavaScript. (#556) - TypeScript
.mtsand.ctsmodule files are now indexed instead of being skipped. (#366) - JavaScript modules that wrap their code in an anonymous function — AMD/RequireJS, NetSuite SuiteScript, IIFE bundles — now have their inner functions and calls indexed, instead of the file coming up nearly empty. (#528)
- Go methods declared on generic types (e.g.
func (s *Stack[T]) Push(...)) are now correctly attached to their type, so callers, callees, and impact include them. (#583) - Go methods now attach to their receiver type even when declared in a different file from the
typeitself — the idiomatic split wheretype User struct{…}lives in one file andfunc (u *User) Save()in another. Previously a cross-file method was orphaned from its struct, so the type's member list, callers/callees, and impact missed it; as a knock-on, a struct whose interface-satisfying methods are spread across files now also links to the interfaces it implements. (#583) - Asking what a symbol impacts no longer drags in every unrelated sibling method of its class — impact now follows real dependencies instead of the structural "contains" relationship, keeping the result focused on what actually depends on the symbol. (#536)
- CodeGraph's MCP server now answers an agent's
resources/listandprompts/listprobes with an empty list instead of an error, clearing the-32601messages some clients (opencode, Codex) logged on connect. (#621) - Svelte and Vue components used through a barrel file —
export { default as Button } from './Button.svelte're-exported from anindex.tsand imported elsewhere — are no longer falsely reported as having 0 callers. CodeGraph now follows the default re-export all the way to the component and resolves the imports that.svelte/.vuefiles themselves use, socodegraph_callersandcodegraph_impactsee every place a component is used. This also covers components imported from another package in a workspace/monorepo (@scope/ui/widgets) and bare directory imports (import { x } from './'). Previously a live component consumed only through a barrel looked like dead code. Thanks @nakisen. (#629) - Components used in a Vue Single-File Component's
<template>—<MyButton />, or the kebab-case<my-button />— are now indexed as usages, socodegraph_callersandcodegraph_impactinclude components that appear only in another component's markup (including through a barrel re-export). Previously only a Vue component's<script>block was analyzed, so template-only usages were invisible. (#629) - PHP:
include/require/include_once/require_onceof a static path now create a file→file dependency edge, socodegraph_callersandcodegraph_impactfollow includes in procedural / script-style PHP codebases — previously only namespaceusestatements became dependency edges. Dynamic includes (include $var,require __DIR__ . '/x') are skipped. Thanks @atahan150 (#660).