Skip to content

Releases: colbymchenry/codegraph

v1.4.1

Choose a tag to compare

@github-actions github-actions released this 10 Jul 22:40

[1.4.1] - 2026-07-10

New Features

  • The MCP server now notices when a newer CodeGraph release exists and tells you — a long-running server used to drift behind releases silently until something broke. On startup it checks the latest release in the background (never blocking, at most once a day, cached across all servers on the machine) and surfaces a one-line "update available — run codegraph upgrade" notice in the server log, in the instructions your agent sees on connect, and in codegraph_status. Nothing updates by itself, and being offline just means no notice. Opt out with CODEGRAPH_NO_UPDATE_CHECK=1; DO_NOT_TRACK=1 disables it too. (#1243)

Fixes

  • codegraph upgrade on a Windows npm install actually runs npm again — modern Node refuses to launch npm.cmd directly, so the upgrade failed with a spawn error before doing anything. npm is now invoked the way a terminal would run it. (#1238)
  • codegraph uninstall now actually uninstalls CodeGraph. It used to remove only the agent configurations and leave every installed binary behind, so codegraph still ran afterward — especially confusing when both an npm global install and a standalone install were present and removing one still left the other answering on PATH. Uninstall now finds every install on the machine (the standalone bundle, the npm global package, the launcher link) and removes them all, after showing you exactly what it found and asking first (--yes skips the prompt). Machine-level settings like your telemetry choice are preserved, a source checkout is never touched, and the new --keep-cli flag restores the old configs-only behavior. (#1071)
  • codegraph_explore no longer lets ordinary English words in a natural-language question hijack the ranking when they happen to match a code symbol's name. A question like "how does the upgrade flow check the latest version" used to treat "check" as a symbol the agent asked for by name, rank that unrelated definition's file first, and crowd the files the question is actually about out of the answer entirely. Precisely written symbol names (camelCase, PascalCase, snake_case, qualified names) still get top billing exactly as before, as do plain-word symbol bags whose words belong together in the same file.
  • PHP method calls made through a class property — $this->dep->method(), the dominant call shape in constructor-injection codebases (Symfony, Laravel) — now resolve to the method on the property's declared type, so callers and impact analysis see production call sites instead of reporting a DI-heavy method as uncalled or test-only. Promoted constructor parameters, typed properties, classic constructor assignment (including multi-line signatures), and typed setter injection all count; interface-typed properties resolve to the interface method, and inherited methods resolve through the type hierarchy. Only property-shaped declarations are consulted — a same-named local variable or parameter elsewhere can never mistype the property — and a property whose type can't be recovered statically stays unlinked rather than guessed. Thanks @w0lan. (#1220)
  • codegraph upgrade now also refreshes what previous versions installed into your agents — the CodeGraph section in CLAUDE.md / AGENTS.md / GEMINI.md and the MCP entry — so upgrading no longer leaves agents following instructions written for tools that have since been renamed or removed. Refresh-only: agents you never configured are not touched, and your permission and hook choices are preserved. Also available manually as codegraph install --refresh, and skippable with CODEGRAPH_NO_INSTALL_REFRESH=1. (#1238)
  • codegraph upgrade on an npm install now upgrades through npm again instead of quietly creating a second copy that never wins the PATH race — previously codegraph --version kept reporting the old version forever, no matter how many times you upgraded. (#1238)
  • After every upgrade, CodeGraph now checks that the codegraph command your terminal resolves actually serves the freshly installed version — confirming you don't need a new terminal, or telling you exactly which stale install is shadowing the new one. (#1071)
  • The safety watchdog no longer kills a healthy index on severely degraded storage. It used to judge liveness purely by the event loop, so one long database write on a struggling disk looked identical to a hung process and could get a valid, in-progress index terminated. During codegraph index/codegraph init the watchdog now also checks whether the index files on disk are advancing before it acts: slow-but-progressing work is left alone (bounded by a hard cap), while a genuinely hung process is still killed exactly as fast as before. (#1231)
  • Incremental sync now picks up cross-file relationships that only become resolvable after an edit — for example, when a file gains an export that another, unchanged file was already importing or calling. Previously the reference in the unchanged file was never revisited, so callers, impact, and flow results silently omitted the new edge (while status reported a clean index) until a full re-index. References that can't be resolved yet are now remembered and automatically retried whenever a change introduces a symbol that could satisfy them — this also covers a class gaining a new method that other files already call. Thanks @loadcosmos for the report with a minimal reproduction. (#1240)
  • The reverse case is fixed too: when an edit removes or moves a symbol (or deletes its file), callers in unchanged files now re-resolve during the same sync — rebinding to the symbol's new home when it moved, or waiting to reconnect automatically when it comes back — instead of silently losing their relationship until a full re-index. (#1240)

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 10 Jul 08:44

[1.4.0] - 2026-07-10

New Features

  • Indexing is dramatically faster on slow storage — mechanical HDDs, network folders, and virtualized disks. The database no longer folds its write journal back into the main file thousands of times during a bulk index (that folding was ~95% of all disk activity); it now streams writes sequentially and folds them back in a few large, coalesced passes that run off the main thread. In a disk-throttled benchmark matching the reported hardware, a mid-size Java project went from over 25 minutes to under a minute, and there is no change on fast disks. Opt out with CODEGRAPH_NO_WAL_DEFER=1; tune the fold-back threshold with CODEGRAPH_WAL_VALVE_MB. (#1231)
  • New CODEGRAPH_PARSE_TIMEOUT_MS environment variable to raise the per-file parse budget on unusually slow storage, the same way CODEGRAPH_PARSE_WORKERS already tunes the worker count. (#1231)

Fixes

  • Indexing on slow storage (mechanical HDDs, network folders) no longer collapses into false "parse timeout" failures. When disk writes stalled the coordinating thread, parses that had already finished — including empty files — were being misjudged as hung, their workers killed, and the files silently dropped from the index. A parse result is now judged by the worker's own clock, so a stalled coordinator accepts the finished result instead of killing the worker; only a genuinely hung parse is terminated (after a wider grace window). Files that do hit the timeout are retried at the end of indexing instead of being silently lost. Thanks @KnifeOfLife for the exceptional report. (#1231)
  • Parse workers now receive their grammar files from memory instead of each re-reading them from disk on spawn, eliminating a feedback loop on slow disks where every worker restart added more disk contention — and making worker restarts cheaper everywhere. (#1231)

v1.3.1

Choose a tag to compare

@github-actions github-actions released this 09 Jul 04:20

[1.3.1] - 2026-07-09

Fixes

  • Indexing very large codebases no longer dies at the end of the "Resolving refs" step. Two failure modes are fixed: on multi-million-symbol projects (e.g. the Linux kernel, ~95,000 files) the final analysis phase ran out of memory and crashed the process outright, and on large projects on slower machines (reported on a 24,000-file Java project on Windows) the same phase could stall long enough that the safety watchdog killed a healthy, still-progressing index at ~98% (#1212). The whole phase now streams its work instead of holding whole-graph snapshots in memory, keeps the process responsive throughout, and skips analysis passes for languages a project doesn't contain — which also makes the tail of indexing noticeably faster on single-language repos. The resulting graph is identical, and a genuinely wedged process is still detected and killed.
  • Indexing and codegraph sync stay responsive through their heaviest internal steps on huge projects: the post-index database maintenance (which on a multi-gigabyte index could stall the process for minutes and get a fully successful index killed by the safety watchdog at the finish line) now runs on a background thread, storing a giant generated file no longer freezes the process mid-extraction, and the reference-resolution bookkeeping between progress updates is broken into small responsive steps. The resulting graph is byte-for-byte identical.
  • Fixed a race that could leave a freshly-attached MCP session permanently silent: when a client's first messages arrived glued together during the daemon's connection handshake (roughly one attach in five on a busy machine), the daemon could drop them and stop reading that connection entirely — every tool call from that session then hung with no reply. The handshake now hands the connection over losslessly, and the fix is validated by hammering the previously-flaky attach test 25× under load.
  • The first tool call after the shared daemon starts no longer waits behind the query workers' cold start (which can take many seconds on a busy machine) — it's served directly until the first worker is warm, so a fresh session answers immediately.

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