Skip to content

Releases: colbymchenry/codegraph

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 07 Jul 19:27

[1.3.0] - 2026-07-07

New Features

  • CodeGraph now indexes Nix (.nix) — flakes, NixOS and home-manager modules, overlays, and package sets join the graph: let and attrset bindings, functions (simple, destructured { pkgs, ... }, and curried), and inherit bindings all become searchable symbols, with call edges between bindings. File-level wiring follows the ways Nix actually connects files: import ./relative/path.nix (with import ./dir reaching the directory's default.nix), NixOS module imports = [ ./hardware.nix ../common ] lists, flake-style modules = [ ./configuration.nix ] lists, and the nixpkgs callPackage ./pkgs/foo { } idiom — so "what does this configuration actually pull in" and "what uses this module" are answerable on real setups. Dynamic references (import <nixpkgs>, variable paths, flake-input module references) are deliberately left unlinked rather than guessed. Thanks @TyceHerrman. (#324, #332, #648)
  • The NixOS module system's option wiring is bridged, so flow questions cross the module boundary instead of going dark at it: a config write like launchd.user.agents.myapp = { ... } or home.file.".gitconfig" = { ... } links to the module that declares that option (options.launchd.user.agents = mkOption { ... } — flat and nested declaration spellings both count, quoted keys like system.defaults.NSGlobalDomain."com.apple.dock" match their exact declaration), which makes "how does enabling this service produce the launchd daemon / generated config file" traceable end-to-end and "what sets this option" answerable across modules, tests included. Precision is deliberately conservative: interpolated ${...} paths, options declared in more than one module, and submodule-internal option namespaces stay unlinked rather than guessed, and every bridged hop is labeled as heuristic module-system wiring rather than shown as a plain reference.
  • CodeGraph now indexes ArkTS (.ets) — the language of HarmonyOS / OpenHarmony apps. Everything TypeScript gets extracted (classes, interfaces, enums, type aliases, imports/exports, call edges), plus ArkTS's own constructs: @Component / @ComponentV2 structs with their decorators (@Entry, @State, @Prop, @Link, @Local, @Param, …) captured and searchable, build() view trees linked parent→child so "which pages render this component" is answerable, chained attributes connected to the @Extend/@Styles functions they invoke, @Builder methods and functions wired into the call graph, and .onClick(this.handler)-style event bindings linked to their handler methods. Modular HarmonyOS projects resolve across module boundaries too: a bare import { CartRepository } from "data" follows the oh-package.json5 file: dependency to the right module — honoring each module's declared main entry, from .ets and .ts consumers alike — while ambiguous names in multi-app monorepos deliberately stay unlinked rather than guessed, and mixed .ets/.ts codebases cross-link freely. Validated on real HarmonyOS apps including the official OpenHarmony samples monorepo. (#396, #512, #648, #890)
  • ArkUI's dynamic hops are bridged so flow questions cross them instead of going dark, each labeled as dynamic dispatch rather than shown as a plain call: methods that assign a reactive property (@State, @Local, …) link to the component's build() (the re-render hop — assignment-gated, so a method that merely reads state gets no edge); emitter.emit(eventId) links to the matching emitter.on/once subscriber when both sides share a statically-recoverable event key (numeric ids pair within one file only, named constants within one module, so unrelated samples in a monorepo never cross-link); and router.pushUrl({ url: 'pages/Detail' }) links to the target page's @Entry struct, with ambiguous urls left unlinked rather than guessed.
  • Interrupted or incomplete indexing is now visible instead of silent: a run killed mid-index (crash, out-of-memory, watchdog) leaves a marker that codegraph status reports as a truncated index, a completed run that dropped files reports itself as partial — both in the human output and in status --json — and codegraph index prints a warning with the exact counts when its result doesn't add up to what the scan discovered.
  • CodeGraph now indexes Terraform and OpenTofu (.tf, .tfvars, .tofu) — resources, data sources, modules, variables, outputs, providers, and every locals attribute become symbols (e.g. aws_s3_bucket.my_bucket, var.region, module.vpc, local.prefix), and uses like var.region, module.vpc.id, data.aws_caller_identity.current, or aws_s3_bucket.my.arn are wired up cross-file, so search, callers, and impact queries return real results on infrastructure repos instead of nothing. Module calls are bridged across the module boundary: a module block's inputs link to the child module's variables, module.vpc.vpc_id reaches the child's output "vpc_id" definition, and the block's local source path links to the module's files — so "what breaks if I change this module's variable" reaches every caller instead of dead-ending at the declaration (registry and git sources are deliberately left as visible boundaries rather than guessed). Cross-component wiring through the cloudposse/atmos remote-state module connects too: module.vpc.outputs.vpc_cidr in one component reaches the vpc component's own output when the component name is statically declared (a literal, or a variable with a literal default) and exactly one directory matches — anything dynamic or ambiguous stays unlinked. Aliased providers are first-class: provider "aws" { alias = "east" } gets its own symbol, and provider = aws.east on a resource (or a module's providers map) links to that configuration, found up the module tree the way Terraform actually inherits it. moved/import/removed state-migration blocks and check assertions reference the resources they name, so a refactor's paper trail is part of the graph. .tfvars assignments link to the variables they set, including var-files kept in a subdirectory. Resolution follows Terraform's real per-directory scoping, so same-named variables across modules never cross-link and "what depends on var.project_id" in a multi-module repo never mixes in unrelated modules. Thanks @Javviviii2. (#83, #310, #648)
  • CodeGraph now indexes CUDA (.cu, .cuh) — kernels, device/host functions, structs, and classes become symbols, and the host→kernel call edge survives the <<<grid, block>>> launch syntax, so questions like "how does this call reach the GPU kernel?" trace across the CPU/GPU boundary instead of going dark at the launch site. Real-world launch styles all connect: templated launches (my_kernel<Traits, 256><<<grid, block>>>(args)), launches through a local function pointer (auto kernel = &my_kernel<...>; ... kernel<<<grid, block>>>(args) — each branch-assigned target linked), brace-initialized launch configs (<<<dim3{1,1,1}, dim3{256,1,1}>>>), and kernels defined through a name-in-first-argument macro (flash-attention's DEFINE_FLASH_FORWARD_KERNEL(kernel_name, ...) { ... } style), which now index under their real kernel names. CUDA that lives in plain .h/.hpp headers — where much real-world device code sits, launch-template headers included — is recognized by content and indexed the same way. Validated on llm.c, flash-attention, and NVIDIA CUTLASS. (#387, #648)
  • C++ symbols defined inside namespace blocks now carry the namespace in their qualified name (flash::compute_attn, C++17 namespace a::b { included), and namespace-qualified calls (ns::fn(...)) resolve to their definitions — previously such calls never linked at all, which hid much of the call graph in namespace-heavy C++ codebases from callers and impact analysis.
  • C++ calls that spell out template arguments (fn<T, 256>(args)) now link to the function they instantiate, the same normalization templated base classes already had.
  • CodeGraph now indexes Solidity (.sol) — contracts, libraries, interfaces, structs, enums, modifiers, events, errors, and state variables become first-class symbols, with call edges that follow emit, revert, modifier guards (onlyOwner-style, including base-constructor chains like constructor() ERC20(...)), and library/method calls (including using directives). import directives resolve to the imported file, so cross-contract questions like "trace transferFrom through allowance and balance updates" or "how does onlyRole reach the role storage?" work out of the box on real Solidity codebases (validated on solmate, solady, and OpenZeppelin Contracts). Thanks @naiba. (#374, #648)
  • Erlang behaviour dispatch is now followed through the graph: a framework call through a variable module — cowboy's Handler:init/Middleware:execute folds, a plugin manager's Mod:callback(...) — links to the repo's implementations of the behaviour that declares that callback, so flow traces and impact cross the OTP callback boundary instead of stopping at it. The links are precision-gated: the callback arity must match, exactly one behaviour may own that callback shape (a collision stays unlinked rather than guessed), the implementer must actually export the callback, and the fan-out is bounded — a behaviour with hundreds of implementers stays a visibly dynamic boundary. Every bridged hop is labeled as dynamic dispatch with its wiring site, never shown as a plain static call.
  • CodeGraph now indexes Erlang (.erl, .hrl) — functions, with clauses and arities of the same name grouped as one symbol spanning all of them, plus records with their fields, -type/-opaque aliases, -define macros, and -spec signatures attached to every function. Cross-module mod:fn(...) calls resolve to the target module's function, fun name/arity values are captured as references (so callback registrations like `lists:foreach(fun submit/...
Read more

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 02 Jul 03:18

[1.2.0] - 2026-07-02

New Features

  • Method calls made through a local variable now resolve to the method in many more languages. When code does const logger = new Logger(); logger.log(); (or the equivalent), CodeGraph infers the local variable's type from its declaration or initializer and links the call to the right method — so these calls now show up in callers, impact/blast-radius, and codegraph_explore flow traces instead of being dropped. Previously only C++ handled this; it now also covers TypeScript, JavaScript, Python, Java, C#, Kotlin, Swift, Go, Rust, Dart, Scala, and PHP. (#1108)
  • Ruby method calls made on a receiver (logger.log) now record an edge to the method. Previously the Ruby indexer kept only the receiver and discarded the method name, so a method called through a variable or object had no recorded callers and was missing from impact/blast-radius and flow traces; combined with the local-variable type inference above, logger = Logger.new; logger.log now links to Logger#log. Calls to a class method (Foo.bar) and object construction (Foo.new) are still recorded too. (#1110)
  • The same local-variable method-call resolution now extends to Lua, Luau, R, and Pascal/Delphi. A method invoked through a local — Lua/Luau local lg = Logger.new(); lg:log(), R lg <- Logger$new(); lg$log(), or Pascal var lg: TLogger; ... lg.Log — now links to the right method instead of being dropped. (#1112)

Fixes

  • Indexing a large project no longer gets killed partway through with a "Main thread unresponsive — killing the wedged process" message. The safety watchdog that stops a genuinely stuck index was mistaking slow-but-normal work for a hang: on a big repo, linking up references and cross-file relationships can legitimately run for a while, and that work now regularly yields so the watchdog can tell real progress from a true stall. Projects that previously failed to finish codegraph init / codegraph index (and had to fall back to CODEGRAPH_NO_WATCHDOG=1) now complete normally, while a genuinely hung process is still caught. Thanks @zmcrazy, @YoungLiao, and @GeeLab-Mob for the reports. (#1091)
  • On Windows, a console window no longer briefly flashes when CodeGraph runs as a background MCP server. When the npm launcher started the bundled runtime — which happens every time an editor starts the server or reconnects after the daemon idles out — and during its self-heal step that extracts a missing platform bundle, Windows would pop up a black console (conhost) window for a moment. Both now launch hidden, matching how the daemon already behaved; the browser-open step of codegraph login was hardened the same way. Thanks @luoyerr for the report and root-cause analysis. (#1092)
  • C++ forward declarations no longer crowd out the real class definition. A class Foo; forward declaration — common in large C++ and Unreal Engine codebases, where a heavily used class is forward-declared across dozens of headers — was indexed as its own class node every time it appeared. So exploring that class returned mostly forward-declaration sites, and could even pick one of them as the representative for blast-radius, burying the actual definition and its members and callers. Bodiless forward declarations are now skipped for C and C++, exactly as forward-declared structs and enums already were, so only the real definition is indexed. Languages where a class with no body is a complete definition — such as Kotlin's class Empty and Scala — are unaffected. Thanks @luoyxy for the report and root-cause analysis. (#1093)
  • C++ methods that return a reference, and user-defined conversion operators, are now indexed under their correct names. An inline getter like const FGameplayTagContainer& GetActiveTags() const — everywhere in Unreal Engine headers — was indexed as & GetActiveTags() const instead of GetActiveTags, and a conversion operator like operator EALSMovementState() const kept its trailing () const instead of reading operator EALSMovementState. In both cases the garbled name meant you couldn't find the symbol by name and its callers weren't linked. Both now read cleanly, matching how pointer-returning and value-returning methods already worked. (#1096)
  • C++ functions written with an inline-specifier macro before the return type are now indexed correctly. In Unreal Engine, inline helpers are commonly written FORCEINLINE FString GetEnumerationToString(...); the FORCEINLINE macro made the parser read the return type as part of the function's name (FString GetEnumerationToString instead of GetEnumerationToString) and lose the real return type, so the function couldn't be found by name and its callers weren't linked. CodeGraph now recognizes the standard Unreal inline macros (FORCEINLINE, FORCENOINLINE, FORCEINLINE_DEBUGGABLE), so both the name and the return type are captured. (#1100)
  • The same function-name recovery now covers inline macros from common third-party C++ libraries, not just Unreal Engine — including pugixml (PUGI__FN, PUGIXML_FUNCTION), Godot (_FORCE_INLINE_), Boost (BOOST_FORCEINLINE), and generic ALWAYS_INLINE / FORCE_INLINE. Functions decorated with these are now indexed under their real names. On a large Unreal project vendoring these libraries this cleaned up the large majority of remaining function-name garbling. (#1101)
  • C++ function names are now recovered even when decorated with a macro CodeGraph doesn't specifically know about. A function written SOME_LIBRARY_MACRO ReturnType doWork(...) previously had the macro or return type absorbed into its name whenever the macro wasn't one CodeGraph recognized; now the real name (doWork) is recovered regardless of the macro, so it's findable and its callers link — no per-library configuration needed. The recognized-macro list was also broadened (Qt, Folly, Abseil, LLVM, V8, Eigen, rapidjson) so those additionally capture the return type. This only ever cleans up an already-garbled name and is limited to C and C++, so ordinary names — and languages like Kotlin and Scala where identifiers can legitimately contain spaces — are unaffected. (#1102)
  • The set of C++ libraries whose macros are recognized for full return-type recovery was expanded well beyond Unreal Engine — now spanning Mozilla, Protobuf, {fmt}, nlohmann/json, GLM, Bullet, Skia, OpenCV, EASTL, Cocos2d-x, GLib, SQLite, and the common Windows calling conventions (so HRESULT WINAPI CreateThing(...) indexes as CreateThing returning HRESULT). Functions from libraries not on the list still get their name recovered automatically; being listed additionally recovers the return type. (#1103)
  • Graph traversal and blast-radius results no longer drop or miscount relationships in a handful of edge cases. When a symbol could be reached by more than one path, an impact/blast-radius query could leave out a direct dependency between two symbols that were already linked another way; separately, the lower-level graph traversal used by the library API could keep only one of several relationships between the same pair of symbols (for example a symbol that both calls and references another), count a caller reached through two different call sites twice, or return slightly more results than the requested size limit on a very highly-connected symbol. These were long-standing and mostly masked by later de-duplication, so day-to-day query results were largely unaffected, but the traversal now returns the complete, correctly-bounded set. Thanks @inth3shadows for the precise, individually-traced reports. (#1086, #1087, #1088, #1089, #1090)
  • Method calls to same-named classes in different files now resolve to the right definition. If two files each declared, say, a Logger class with its own log() method, a call could be linked to whichever definition happened to be indexed first — so a call in one file wrongly pointed at the class in another, mixing up that method's callers and blast radius. This affected calls written as obj.log(), Logger.log(), and Logger::log() across many languages, including C++, Python, TypeScript, Java, C#, and Rust. When a method name is ambiguous, CodeGraph now prefers the definition in the calling file itself — the correct target in the common case — while Java/Kotlin calls that an import already pins to another file are unaffected. Thanks @inth3shadows for the minimal repro and root-cause analysis. (#1079)

v1.1.6

Choose a tag to compare

@github-actions github-actions released this 30 Jun 04:44

[1.1.6] - 2026-06-30

Fixes

  • The standalone installer (install.sh) no longer leaves old versions piling up on disk. Each upgrade installed the new release into its own directory and re-pointed the launcher at it, but never removed the previous ones — so on macOS and Linux a full vendored Node runtime (tens of MB per version) accumulated with every update. The installer now keeps only the version it just installed and removes the older ones automatically (the npm installer's download-fallback cache prunes the same way). Windows installs already replaced a single directory in place, so they were never affected. Anything still left behind under ~/.codegraph/versions from earlier upgrades is safe to delete. Thanks @lalanbv for the report. (#1074)
  • codegraph index can now rebuild an existing oversized index from an older version, instead of hanging until the watchdog kills it. The previous fix (#1065) stopped new indexes from sweeping in a gitignored corpus of nested repos, but a project that had already built the multi-gigabyte graph before upgrading couldn't recover: codegraph index is meant to rebuild from scratch, yet it cleared the old graph by deleting every row one at a time, and on a graph of well over a million symbols that took longer than the 60-second responsiveness watchdog allows — so the command was killed before indexing even started, leaving the bad index in place. A full re-index now discards the old database outright and starts fresh, which is near-instant regardless of the old size and also frees the disk the bloated database was holding. Thanks @AriaShishegaran for the detailed follow-up report. (#1067)

v1.1.5

Choose a tag to compare

@github-actions github-actions released this 30 Jun 02:08

[1.1.5] - 2026-06-30

Fixes

  • C++ classes annotated with an export or visibility macro are now indexed as real classes. This is the class MYMODULE_API UMyComponent : public UActorComponent style used throughout Unreal Engine — where an XXX_API macro sits between class/struct and the type name — as well as the equivalent *_EXPORT / *_ABI macros common in Qt, Boost, LLVM, and many other libraries. Previously that macro made the parser misread the whole declaration as a function, so the class was dropped entirely: it never appeared in the graph and its base class went unrecorded, which made "find subclasses", type-hierarchy, and impact-through-inheritance queries come back empty for effectively every gameplay class in an Unreal Engine project. The class, its members, and its inheritance link are now all captured. Thanks @luoyxy for the detailed report and proposed fix. (#1061)
  • codegraph_explore now surfaces the options/config type behind a function when you ask, in plain language, what to change to add a parameter to it. A question like "what do I need to change to add a new parameter to X" shares no words with the file that actually defines X's options — for example a functional-options struct and its With… builders living in a separate options.go, reachable only through X's signature — so that file scored near-zero on every text and connectivity signal and got dropped: explore returned X itself but not the file you'd edit, and the agent fell back to grep. Explore now follows a named function's parameter and return types and pulls in the file that defines them when ranking would otherwise bury it, so the options/config file shows up with its fields. Well-connected types that already rank are left untouched, so ordinary "how does X work" flow questions are unchanged. (The separate tools codegraph_search/codegraph_impact/codegraph_node remain available via CODEGRAPH_MCP_TOOLS for anyone who prefers driving each step explicitly.) Thanks @wauxhall for the detailed investigation. (#1064)

v1.1.4

Choose a tag to compare

@github-actions github-actions released this 29 Jun 21:58

[1.1.4] - 2026-06-29

Fixes

  • CodeGraph again respects .gitignore for nested repositories that git tracks as gitlinks. The recent change that taught CodeGraph to descend into nested repos recorded as 160000 "commit" pointers (#1031, #1033) did so even when your .gitignore excludes the directory those repos live in — so a gitignored reference or benchmark corpus full of cloned repositories got pulled into the index anyway. One project with a gitignored benchmark/repos/ of 19 cloned repos saw over 138,000 files swept in and a 4.8 GiB graph, and a full index then stalled in the "Resolving refs" phase until the watchdog killed it. CodeGraph now treats a gitignored gitlink the same as any other gitignored embedded repo: excluded by default, and re-included only when you opt the directory in with codegraph.json includeIgnored. Nested repos in non-ignored locations — the case #1031/#1033 fixed — are unchanged. Thanks @AriaShishegaran for the detailed report. (#1065)

v1.1.3

Choose a tag to compare

@github-actions github-actions released this 29 Jun 04:04

[1.1.3] - 2026-06-29

Fixes

  • CodeGraph now indexes nested repositories that git records as gitlinks, so a workspace built by stacking several repos inside one another indexes completely from a single codegraph init at the top. When a repo contains another git repo that was git added into it — so git tracks it as a 160000 "commit" pointer rather than a folder of files — or a submodule that isn't an active, initialized submodule in your checkout, that nested repo's source used to be skipped entirely: indexing the top level stopped at the nested repo's boundary and pulled in only the outer repo's own files, so a stacked-repo project came up nearly empty (one report saw ~10 files indexed at the root). CodeGraph now descends into each such nested repo that has a real working tree on disk and indexes it as its own embedded repository, recursively, so every layer of a stacked workspace is covered. Active submodules (already handled) and plain untracked nested clones are unchanged; a nested repo under a dependency directory such as vendor/ or node_modules/ stays excluded; and a submodule with nothing checked out on disk is correctly left alone rather than reported as empty. Thanks @ofergr and @kun-yx for the reports. (#1031, #1033)
  • CodeGraph no longer shows a misleading "different git working tree" warning when you work inside a submodule (or other nested repo) of a workspace you indexed at its root. Because indexing a workspace now pulls in its submodules and embedded clones, a query run from inside one correctly resolves up to the workspace's single index — but it was still warning that the results came from "a different working tree" and suggesting you run codegraph init -i, which would have split the submodule back out into its own separate index and undone the unified view. CodeGraph now recognizes that the nested repo's code is already part of the workspace index and stays quiet. The warning still appears for a genuine git worktree — a second checkout of the same repository on another branch, which really does have its own uncommitted symbols — since that's the case it exists for. (#1031, #1033)
  • On Windows, CodeGraph's background server now shuts down cleanly instead of occasionally aborting with a crash error. When the indexed project contained a nested repository (a submodule or embedded clone), stopping the server could race the file watcher's teardown and exit with a Windows crash code rather than a clean exit. Shutdown now lets that teardown finish first, so the server stops cleanly and promptly. (Windows only; other platforms were unaffected.) (#1033)
  • C++ classes that inherit from a templated base — class Widget : public Base<int>, a CRTP base like class App : public CRTPBase<App>, or a struct inheriting a template — are now linked to that base class in the graph. Previously the template arguments (<int>) made the inheritance go unrecognized, so these classes looked like they inherited from nothing and impact/callers analysis stopped at the boundary; the connection is now followed like any other base class. Thanks @ryancu7 for the report. (#1043)
  • C++ objects constructed on the stack — Calculator calc(0) or Widget w{1, 2} — now record that the enclosing function instantiates that class, the same as heap construction (new Calculator(0)) already did. Previously only the new form was tracked, so a function that built objects with the ordinary stack syntax looked like it didn't construct them and the dependency was missing from impact/callers. Thanks @Dshuishui for the report. (#1035)
  • The graph no longer stores duplicate copies of the same relationship. The same dependency between the same two symbols at the same spot could be recorded more than once, which inflated edge counts and let callers/impact results list a relationship twice. Each relationship is now stored exactly once, and existing projects are de-duplicated automatically the next time CodeGraph opens them. Thanks @inth3shadows for the detailed report. (#1034)
  • codegraph node can now read a file from the command line. File-read mode — pass -f/--file to get a file's source with line numbers plus the files that depend on it, the same output as the codegraph_node MCP tool — was rejected with "missing required argument 'name'", because the command always demanded a symbol name even though file mode has none, leaving the feature unreachable from the CLI. The symbol name is now optional: codegraph node -f src/auth.ts (or codegraph node src/auth.ts) reads the file, codegraph node parseToken looks up a symbol, and running it with neither prints a short usage hint instead of a cryptic error. Thanks @jcrabapple for the report. (#1044)
  • codegraph query no longer prints meaningless relevance percentages like "12042%" next to each result. The number was a raw full-text search score — useful only for ordering the results, not as a real 0–100% figure — so multiplying it by 100 produced wild values that made the output look broken. Results are already listed best-match first, so the CLI now just shows them in that order with no score, matching what the search tool reports to AI agents. If you script against codegraph query --json, the raw score is still included for sorting or thresholding. Thanks @jcrabapple for the report. (#1045)
  • codegraph explore no longer reports an alarming, inflated result count on broad natural-language queries. The "Found N symbols across M files" summary used to count every symbol the search swept in while ranking, so a broad query (for example "publish status to the API") on a large project could announce hundreds of symbols across a big fraction of the codebase — reading as if you had to wade through all of them — even though only the most relevant handful are actually shown with their source. The summary now counts just the files explore returns source for, so the number matches what you see. Ranking and results are unchanged: the right symbols still come first, and any further relevant files are still listed by name under "Not shown above" so nothing is hidden. Thanks @jcrabapple for the report. (#1046)
  • Android resource files no longer bloat the index. A res/ tree — layouts, drawables, value bags (strings, colors, styles), menus, navigation graphs — contains no code symbols, but on an Android app it can be the overwhelming majority of files (one project: 26,000+ XML files, ~97% of everything, contributing zero symbols), which inflated the database, slowed indexing, and padded file counts and codegraph explore/search results with entries that have nothing to find. CodeGraph now skips Android resource directories by default — res/layout/, res/values/, res/drawable/, res/menu/, and the rest, including their locale/density/version variants like res/values-es/ or res/drawable-hdpi/. Your actual code is untouched, and so is the one kind of XML that does carry symbols — MyBatis mapper files, which live under src/main/resources/, not res/. res/raw/ is deliberately kept (it can hold real assets), and you can re-include any excluded directory with a .gitignore negation such as !res/values/. Thanks @jcrabapple for the report. (#1047)

v1.1.2

Choose a tag to compare

@github-actions github-actions released this 28 Jun 06:34

[1.1.2] - 2026-06-28

New Features

  • You can now exclude committed directories from the index with an exclude list in codegraph.json — even when they're git-tracked. .gitignore can't drop a directory git already tracks, so a vendored theme or SDK that's checked into your repo (a committed Metronic theme under static/, a bundled vendor library) had no supported way to be kept out — it just bloated the graph and slowed indexing. Add a root codegraph.json with, e.g., { "exclude": ["static/", "**/vendor/**"] } and those paths are skipped on indexing, sync, and file-watching, on both git and non-git projects. Patterns are gitignore-style and matched against repo-root-relative paths. This complements the existing includeIgnored (its opposite — opt in to gitignored embedded repos). (#999)
  • CodeGraph now follows C/C++ commands that are dispatched through macro-built function-pointer tables, so the handler functions they reach are no longer dead-ends in the graph. Many C projects register a handler into a struct's function-pointer field through a macro and a generated table — redis is the classic case: every command (getCommand, decrbyCommand, …) is wired into the command struct's proc field by a MAKE_CMD(…) table that lives in a generated, #include-d file, then invoked as c->cmd->proc(c). CodeGraph now reads those macro-built tables — including ones whose struct type is itself a macro alias, whose table sits in an #include-d file that is never indexed on its own, or that are wrapped in conditional compilation (#ifdef) and defined inline with the struct. It recognizes function-pointer fields declared through a function typedef, and follows the receiver — a chained access (c->cmd->proc) or an array subscript through a file-scope table ((cmdnames[i].cmd_func)(…)) — across field types. It also follows dispatch through a bare array of function pointers with no struct wrapper at all — the opcode/handler-table pattern common in interpreters and emulators, where a table like opcodes[op](…) invokes one of many registered handler functions by index — linking the dispatcher to every handler in the array. The upshot: asking for the callers or blast radius of a command handler now finds the dispatcher that reaches it. For redis, call shows up as a caller of every command; for SQLite, the builtin SQL functions registered through FUNCTION(...) link to where they're invoked; for Vim, every :ex and normal-mode command links from the dispatcher. (#991, extending #932)
  • CodeGraph no longer times out when many agents query it at once. The shared background server that serves all your editor and agent sessions used to run every query on a single thread, so a burst of concurrent requests — for example a swarm of subagents exploring a large monorepo together — queued up behind one another and, while the heavy ones ran, froze the connection so finished answers couldn't even be sent back until the whole batch drained. Past a handful of simultaneous callers that routinely surfaced as MCP request timeouts. The shared server now answers queries across a pool of worker threads, so concurrent requests run in parallel and the connection stays responsive the whole time; when it's genuinely saturated a call returns a brief "busy, retry shortly" note (not an error) instead of hanging past your client's timeout. The pool sizes itself to your machine — roughly one worker per core, leaving one for coordination — and a single editor session is unaffected (no pool, no overhead). Set CODEGRAPH_QUERY_POOL_SIZE to choose a specific number of workers, or 0 to revert to single-threaded in-process queries.
  • Indexing now parses files across multiple CPU cores instead of one, so building a project's graph — codegraph index, the first index of a project, and the background re-index after changes — is faster on multi-core machines, most noticeably on large or parse-heavy codebases. The graph it produces is identical to before and re-indexing stays deterministic: parsing runs in parallel, but results are still committed in a fixed order, so the same project always yields the same graph. CodeGraph sizes the pool to your machine automatically (leaving a core free for everything else); set CODEGRAPH_PARSE_WORKERS to choose a specific number of parse workers, or CODEGRAPH_PARSE_WORKERS=1 to restore the previous single-core behavior. Peak memory is unchanged — workers reclaim parser memory independently, so it doesn't grow with the number of cores. (#1015, #320)
  • When CodeGraph's MCP server runs with no default project of its own — started outside any repository (for example behind an MCP gateway), or at a monorepo root whose indexes live in sub-projects — it now marks projectPath as a required argument on every tool call. Before, projectPath was always optional, so an agent talking to such a server would often omit it, get back guidance to pass it, and not reliably retry — you had to nudge it by hand every time. Now the requirement is part of the tool definition the agent sees, so it supplies the path to the project it's working on the first time. When the server does have a default project — the normal case, launched inside your repo — projectPath stays optional and a call without it falls back to that project exactly as before. Thanks @wauxhall for the report. (#993)
  • CodeGraph's MCP tools now work in Cursor's Ask mode (and any other client that only permits read-only tools). Every CodeGraph tool just reads your indexed code — it never changes your workspace — but it didn't advertise that, so Cursor's Ask mode blocked every call with "you are in ask mode and cannot run non read-only tools," and you had to switch to Agent mode to use CodeGraph at all. CodeGraph now declares all its tools read-only using the standard MCP tool annotations, so Cursor (and similar clients) allow them in read-only contexts. Nothing about how the tools behave changes. Thanks @CDsouza315 for the report. (#1018)

Fixes

  • A codegraph index or codegraph init that gets orphaned or wedged now stops itself instead of pinning a CPU core forever. If you killed the command (or the terminal/agent that launched it), the underlying indexer process used to keep running in the background — the parent couldn't pass the signal along — and a genuinely stuck index had nothing watching it either, since the self-recovery watchdogs were wired only into the background MCP server. Both gaps are closed: indexing now self-terminates when its parent goes away, and a main thread that stops making progress is killed so it can't hang indefinitely. Opt out with CODEGRAPH_NO_WATCHDOG=1 (liveness) or CODEGRAPH_PPID_POLL_MS=0 (orphan detection), matching the server. (#999)
  • Indexing no longer hangs at "Resolving refs" on a repo that commits a large JavaScript/TypeScript theme or SDK. A vendored admin theme (Metronic is the classic case — ~1,300 committed .js files) re-declares the same method names (init, update, render, destroy, …) on hundreds of widgets, and resolution used to score every same-named definition against every call — work that grows with the square of how many times a name repeats. On such a repo it pinned a CPU core for 15–30 minutes and effectively never finished. Resolution now declines to guess when a name is defined more times than any real codebase ever repeats one (the cutoff is generous — normal projects top out far below it and are completely unaffected), since no proximity heuristic can pick the one true target among thousands anyway. Indexing that previously wedged now completes in seconds, and precise resolution (imports, qualified names, class-name matches) is unchanged. This is the same class of slowdown as the 1.1.0 import-name fix, now closed for repeated method/symbol names. Tune the cutoff with CODEGRAPH_AMBIGUOUS_NAME_CEILING if you ever need to. Thanks @DANOX2 for the detailed report and repro. (#999)
  • Claude Code's front-load prompt hook now fires for non-English prompts. The optional hook that injects CodeGraph context for structural questions only recognized English keywords, so a structural question written in Chinese — or any non-Latin-script language — silently injected nothing: the hook looked like it wasn't wired up despite a correct setup, with no error to explain why. The gate is now language-aware. It recognizes Chinese structural keywords (如何/流程/调用/依赖/实现/架构…), and — in any language — a prompt that names a real code symbol from your project, such as getUserId, article_publish, user.login, or parseToken() (the name is checked against the index, so an ordinary word that merely looks like code doesn't trigger it). Non-structural prompts ("fix this typo", in any language) stay a no-op as before, so nothing fires where there's no structural answer to give. Thanks @whinc for the detailed report and repro. (#994)
  • The background auto-sync server now starts for projects kept on an ExFAT or FAT external drive (and some network mounts). Those filesystems don't support the operations the server relies on to coordinate and to listen locally, so it failed immediately and re-logged the same error on every retry — background indexing was broken, so you had to run codegraph sync by hand after changes. (The MCP tools, the prompt hook, and manual codegraph index/sync were unaffected, since none of them need the server.) The server now works around those limitations automatically — falling back to a different coordination method and relocating its local socket to your system temp directory — so background indexing works there exactly like anywhere else, with no configuration needed. Verified end-to-end on real removable-drive filesystems on macOS, Linux, and Windows. Thanks @zengwenliang416 for the detailed report. (#997)
  • If you use CodeGraph as a library, the QueryBuilder.deleteResolvedReferences() helper no longer throws "too many SQL variables" when handed a very lar...
Read more

v1.1.1

Choose a tag to compare

@github-actions github-actions released this 24 Jun 22:20

[1.1.1] - 2026-06-24

Fixes

  • CodeGraph respects your .gitignore again when looking for nested git repositories. A directory you've gitignored — a resource/ or .repos/ folder of cloned reference projects, a large vendored data dir — is no longer walked into and indexed: version 1.0.0 started searching inside every gitignored directory for embedded git repos and pulling them all in, which could multiply a graph many times over and slow indexing to a crawl on a multi-gigabyte folder of clones, even though you'd explicitly excluded it. Indexing the repos inside a gitignored directory is now opt-in — add an includeIgnored list to a codegraph.json at your repo root, e.g. { "includeIgnored": ["packages/", "services/"] }, to index the embedded repos under the directories you name. The "super-repo of independent clones" layout from 1.0.0 still works, just declared explicitly. Nested repos you haven't gitignored (untracked clones) are indexed as before, and a project without this layout is unaffected. (#970, #976, #622)
  • The MCP server no longer drops out with Transport closed when its connection to the shared background server hits a transient socket error. To serve all your editor/agent sessions from a single index, CodeGraph runs one shared background server they reach over a local socket; a stray error on that socket while a session was connecting used to take the whole server process down, so your agent saw a bare Transport closed even though codegraph status and codegraph sync were perfectly healthy. Now such an error is handled gracefully — the session falls back to serving itself in-process instead of crashing. This is most common on WSL2 when your project lives on a Windows drive (a /mnt/c or /mnt/d path), where that socket is flaky; if you still hit problems there, set CODEGRAPH_NO_DAEMON=1 to skip the shared server entirely and run each session in its own process. Affects Codex and any other MCP client. (#974)
  • A shared background server that can't bind its socket now cleans up its own lock file before exiting, instead of leaving a stale lock that the next launch trips over — which previously could let duplicate serve --mcp processes pile up for the same project. (#974)

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 23 Jun 21:46

[1.1.0] - 2026-06-23

New Features

  • Claude Code: an optional front-load hook makes your agent reach for CodeGraph automatically. When you ask a structural question — "how does X work", "what calls Y", "trace the flow from A to B" — CodeGraph injects the relevant source and call paths into the prompt up front, so the agent answers from the graph instead of grepping around to rebuild it. You're asked during codegraph install (default yes; Claude Code only, since it's the agent with prompt hooks), it's removed by codegraph uninstall, and codegraph upgrade turns it on for existing Claude setups. It's strictly additive and degradable — non-structural prompts and un-indexed projects are left alone — and you can switch it off any time without uninstalling by setting CODEGRAPH_NO_PROMPT_HOOK=1.
  • Vue store actions, mutations, and getters are now indexed as symbols you can find and read. Whether your store is Vuex (mutations / actions objects in a module) or Pinia — both the options form (defineStore({ actions: { … } })) and the setup form (defineStore('id', () => { … }), where actions are local functions) — each action, mutation, and getter is now a real node. So codegraph search finds login or getSessionList, and codegraph_explore / codegraph_node show its body and what it calls, instead of "not found" because the function only existed as an object-literal property.
  • codegraph_explore now connects a Vue component to the Pinia store action it calls. When code does const store = useUserStore() and then store.fetchUser(), that call now links through to the fetchUser action in the store module — so "what happens when this view loads its data?" traces from the component into the action's body instead of stopping at the store.fetchUser() line. Works for both Pinia store styles (options and setup), and stays precise (a built-in like store.$patch() or an unrelated same-named method isn't mislinked).
  • codegraph_explore now follows Vuex string dispatch. A dispatch('user/login') or commit('SET_TOKEN') call — namespaced 'module/action' keys included — now links to the action or mutation it names, resolved to the correct store module even when several modules share an action name (and without being fooled by a same-named api/ helper). So "what runs when this dispatches?" traces from the call into the store handler and on to the mutations it commits. Vuex's canonical export default { namespaced, actions, mutations } module shape is now indexed too, so those handlers are findable symbols.
  • codegraph_explore now connects React data-fetching flows built on RTK Query (Redux Toolkit's createApi). An endpoint defined inside createApi({ endpoints }) and the useGetXQuery / useUpdateYMutation hook it generates were both invisible to analysis — so "what does this component fetch?" or "where does useGetThingQuery get its data?" dead-ended, because the hook, the endpoint, and the component had nothing linking them. CodeGraph now indexes each endpoint and each generated hook as real symbols and wires the path component → useGetXQuery → getX → queryFn, so the flow resolves in one explore call instead of reading the API slice by hand. Both the arrow (endpoints: build => ({ … })) and method (endpoints(builder) { return { … } }) styles are recognized, along with the useLazyGetXQuery variant; hand-written hooks of a similar name are left untouched.
  • codegraph_explore now follows Celery task dispatch in Python. A send_email.delay(...) or send_email.apply_async(...) call now links to the @shared_task / @app.task function it runs — typically defined in a different module (tasks.py) from where it's triggered (a view or service) — so "what actually happens when this is dispatched?" traces from the call site straight into the task body instead of stopping at the .delay() line. Both decorator dialects are recognized (bare @shared_task and the arg'd @app.task(bind=True, …) form), including the module-qualified tasks.invalidate_cache.apply_async() call style. It stays precise: a .delay() on something that isn't a Celery task is never mislinked, so a project that doesn't use Celery is unaffected.
  • codegraph_explore now follows Spring application events in Java. A publishEvent(new OrderShippedEvent(...)) call now links to every @EventListener that handles that event — usually in a different class — so "what reacts when this is published?" traces from the publisher straight into each listener method instead of dead-ending at publishEvent(...). The link is by event type, and all the common listener styles are recognized: a @EventListener typed on its parameter, the @EventListener(SomeEvent.class) form, @TransactionalEventListener, and the older implements ApplicationListener<SomeEvent>. One event fans out to all its listeners, and a plain Spring app with no event bus is unaffected.
  • codegraph_explore now follows MediatR request and notification dispatch in C#/.NET. A _mediator.Send(command) or _mediator.Publish(notification) call now links to the Handle method of the matching IRequestHandler<> / INotificationHandler<> — usually in a different file in a Clean Architecture layout — so "what handles this command?" traces from the controller straight into the handler instead of stopping at the mediator call. The sent type is recognized whether it's constructed inline (Send(new GetFooQuery())), built into a local first (var cmd = new …; Send(cmd)), or passed in as a parameter, and it's matched by type — so a MessagingCenter.Send(...) or a same-named DTO that isn't a request is never mislinked, and a project without MediatR is unaffected.
  • codegraph_explore now follows Sidekiq background-job dispatch in Ruby. A DestroyUserWorker.perform_async(id) (or .perform_in / .perform_at) call now links to that worker's perform method — usually in app/workers/ away from the controller or model that enqueues it — so "what runs in the background here?" traces from the enqueue straight into the job body. Both the modern include Sidekiq::Job and the older Sidekiq::Worker are recognized, namespaced workers resolve to the right class even when several share a name (e.g. Comments::NotifyWorker vs Articles::NotifyWorker), and Rails ActiveJob's perform_later — a different mechanism — is intentionally left alone.
  • codegraph_explore now follows Laravel events in PHP. An event(new OrderShipped($order)) call now links to every listener that handles it — each listener's handle() method, usually a separate app/Listeners/ class — so "what reacts to this event?" traces from the dispatch straight into the listener bodies. Listeners are found both ways Laravel registers them: by a typed handle(OrderShipped $event) (auto-discovery, including a handle(A|B $event) union that listens for two events) and by the protected $listen map in your EventServiceProvider (which also catches a listener whose handle() has no type-hint). One event fans out to all its listeners, and queued jobs — dispatched via ::dispatch() rather than event() — are correctly left out.
  • CodeGraph now understands Lombok-generated methods in Java. @Getter, @Setter, @Data, @Value, and @Builder generate getters, setters, builder(), equals/hashCode/toString, and the @Slf4j log field at compile time, so those methods never appear in the source — and a user.getName(), User.builder(), or log.info(...) call used to resolve to nothing, silently breaking call-chain analysis (the agent would conclude the method didn't exist and reconstruct it by hand). Those members are now indexed from the annotations and fields, so they appear in codegraph search and codegraph_explore/codegraph_node, and callers trace through them like any hand-written method. They're marked as Lombok-generated so they read as generated, not hand-written; a method you write yourself is never overridden, static fields get no accessor, and a class without Lombok is unaffected. Thanks @git87663849. (#912)
  • codegraph_explore now follows C and C++ function-pointer dispatch. C does polymorphism with function pointers: a struct carries a function-pointer field, concrete functions are registered into it through a table (static struct cmd commands[] = {{"add", cmd_add}, …}), a designated initializer (.handler = on_open), or an assignment, and the code dispatches indirectly (p->fn(argv)). None of that was visible to analysis — the indirect call resolved to nothing, so git's command runner looked like it called nothing and a vtable's implementations had no callers. CodeGraph now links the dispatch site to the registered handlers, keyed by the struct field, so "what runs when this dispatches?" traces from p->fn(...) into every function registered for that field. This covers the command-table idiom (git, redis) and the ops-struct/vtable idiom (curl's content-encoders, protocol handlers), including the case where a generic hook slot is reassigned from a registry (h->func = found->fn). It stays precise — distinct function-pointer fields don't cross-link, a plain data field is never treated as a dispatch, and a project without function-pointer dispatch is unaffected. (#932)
  • codegraph_explore now follows GoFrame route bindings in Go. GoFrame's standard router wires routes reflectively: the path and method live in a g.Meta struct tag on a request type (g.Meta `path:"/user/sign-in" method:"post"`), the controller method that serves it is matched by that request type, and the two are joined at runtime by group.Bind(...) — so there was no path string and no edge from a route to its handler, and "where is /user/sign-in handled?" or "where are the routes bound to controllers?" could only be answered by reading. CodeGraph now indexes each g.Meta route as a real route node and links it to th...
Read more

v1.0.1

Choose a tag to compare

@github-actions github-actions released this 13 Jun 21:10

[1.0.1] - 2026-06-13

New Features

  • New codegraph daemon command (alias daemons) — an interactive manager for the background daemons. It shows what's running (your current project's daemon first, pre-selected), and you arrow-key to one and press enter to stop it, or pick "Stop all". Previously the only way to shut a daemon down was to hunt for its pid and kill it by hand. (#845)
  • Checking your installed version is now easy to reach however you guess at it: codegraph version, codegraph -v, and codegraph -version all print it, alongside the existing codegraph --version. (#864)
  • The CodeGraph MCP server now self-heals if its main thread ever locks up. A lightweight watchdog notices when the process has stopped responding and stops it so a fresh one starts on your next request — it can no longer sit pinned at 100% CPU with no way to recover. Tune the detection window with CODEGRAPH_WATCHDOG_TIMEOUT_MS, or turn it off entirely with CODEGRAPH_NO_WATCHDOG=1. (#850)

Fixes

  • Git worktrees nested inside your project — like the .claude/worktrees/ that Claude Code creates — are no longer indexed as duplicate copies of your whole codebase. CodeGraph deliberately indexes genuine embedded repos (a real second project checked out inside yours), but a worktree is just another working view of a repo it already indexed, so each one was multiplying every symbol — one report went from ~1,850 files to over 24,000, with search and explore flooded by stale duplicates. CodeGraph now recognizes worktrees and skips them, while still indexing real embedded repos and submodules. Thanks @tphakala. (#848)
  • Running codegraph serve --mcp by hand no longer just hangs in silence. That command is the MCP server your AI agent starts for itself — not a step you run directly — and in a terminal it used to sit there waiting for input that never comes, looking broken. It now recognizes when a person runs it and explains what to do instead (codegraph status, codegraph daemon), and it's been dropped from the command listing so it stops looking like something you need to launch.
  • Cross-file static method calls like ClassName.staticMethod() now resolve correctly. CodeGraph was linking the call to the class instead of the method (and recording it as a construction), so callers and impact for a static method came back empty — a real blind spot in TypeScript and JavaScript codebases that lean on static utility classes (Python and other languages with the same call shape benefit too). The call now links to the method itself. Thanks @contextFlow-lab. (#825)
  • codegraph affected now accepts ./-prefixed and absolute file paths, not just bare project-relative ones. Passing ./src/x.ts or an absolute path — common when the file list comes from another tool — used to silently match nothing and report no affected tests. Thanks @contextFlow-lab. (#825)
  • The CodeGraph MCP server no longer risks getting stuck at 100% CPU after an unexpected internal error. Previously such an error was logged but the process was left running in a broken state, where it could spin a CPU core indefinitely and had to be killed by hand. The server now logs the error and exits cleanly, so a fresh one starts on the next request. Thanks @songhlc. (#850)
  • CodeGraph no longer indexes your entire home directory by accident. Running the installer — or codegraph init / codegraph index — from your home folder or a filesystem root would index everything underneath it (caches, Library, every other project), producing a multi-gigabyte index and constant file-watching churn. CodeGraph now refuses these roots and points you at a specific project instead; pass --force if you genuinely mean to. (Combined with the macOS file-descriptor fix already in 1.0.0, this closes the report of a runaway watcher exhausting the system file limit.) Thanks @ligson. (#845)