为codegraph打分
给出您宝贵的评分:
手机端可长按上方图片保存到相册,或点击「下载/分享」分享到微信
使用 codegraph,你可以:
专为 Claude Code、Cursor 等智能体打造预索引代码知识图谱,减少调用与 token 消耗,本地运行保障数据安全,提升代码理解效率。
用户评论 (0)
2026年05月28日
2026年03月24日
2026年05月25日
2026年06月13日
v1.6.0
2026年08月27日
[1.6.0] - 2026-08-26
Highlights
- GitHub Copilot is now supported —
codegraph installsets it up in VS Code, the Copilot CLI, and JetBrains IDEs, next to the agents it already knew. - Set up in one command —
codegraph install --yes --initwires up your agents and indexes your project with no prompts, ideal for a fresh container or CI. - Better answers for your agent —
codegraph_exploreno longer repeats code it already showed you, always brings back the files and symbols you asked for by name, and spends its space on the code that actually answers the question rather than look-alikes, generated files, and type shims. - Your graph stays right as you keep coding — a long-running index no longer drifts from a fresh one, and edits to
codegraph.json(such asexclude) apply immediately without a restart. - No more silent crashes or hangs — deeply nested C/C++ files, Swift Vapor projects, and large sync batches that used to kill or stall indexing now finish cleanly.
- A disk-space leak is fixed — a force-killed session could leave the database's write-ahead log behind to grow without bound (tens of gigabytes was reported); the leftover log is now folded back into the index and trimmed automatically the next time the project opens. The index itself has no size limit.
- Works from a workspace or monorepo root — the MCP server finds your indexed project when launched from a folder above it, and says so clearly when it can't find one.
- More accurate code graphs for TypeScript, Rust, Erlang, C/C++, and Python projects — see the full list below.
- Also new: per-project Codex setup (
codegraph install --location=local), adeprioritizesetting to keep helper folders from outranking your real code, thecodegraph contextcommand, and usage stats that now stay entirely on CodeGraph's own servers.
After upgrading, run codegraph index once in each project so your existing graph picks up these fixes — codegraph status reminds you when it's needed.
New Features
-
GitHub Copilot is now a supported agent:
codegraph installcan configure Copilot Chat in VS Code (copilot-vscode), the GitHub Copilot CLI (copilot-cli), and the Copilot plugin in JetBrains IDEs (copilot-jetbrains). Installed Copilot surfaces are auto-detected like every other agent, existing MCP server entries in their config files are preserved, andcodegraph uninstallreverses the setup cleanly. Restart VS Code or your JetBrains IDE after installing so Copilot picks up the server. -
codegraph install --initwires up your agents and builds the current project's index in one command, andcodegraph init --yesruns without any prompts — so a fresh container or CI job can bootstrap CodeGraph with a single non-interactive line (codegraph install --yes --init). The installer still never indexes anything unless you ask for it with the flag, and the usual safety refusal for a home directory or filesystem root applies. (#1578) -
Codex CLI can now be set up per project instead of only user-wide:
codegraph install --location=localwrites./.codex/config.tomland the CodeGraph block in your project'sAGENTS.md, so CodeGraph is wired into that repo only rather than every Codex session on the machine.codegraph uninstall --location=localreverses it, and the global install is untouched either way. Codex only applies a project's config once you've marked the project trusted, so the installer says so after a local install. Thanks @maxmilian. (#1531) -
A new
deprioritizesetting incodegraph.jsonkeeps the paths you name from outranking your product code in search andcodegraph_exploreanswers, without removing anything from the index. It takes gitignore-style patterns just likeexclude, but is ranking-only: helper-script trees, generated output, or optional add-on directories whose generic symbol names (usage,run,status) would otherwise crowd out the code that actually answers a query stay fully indexed and findable — and a query that genuinely targets such a tree still returns it. Thanks @maxmilian. (#982) -
codegraph_exploreno longer re-sends source it already returned earlier in the same conversation. A file it has already shown you comes back as a short pointer — the path, the symbols and the exact line range, with confirmation that the file hasn't changed since — and the space that frees is spent on code you haven't seen yet, so a follow-up call covers new ground instead of repeating the last one. If a file was edited in between, its source is always shown again in full. SetCODEGRAPH_EXPLORE_DEDUP=0to turn this off. -
When an agent connects over MCP, CodeGraph now states up front that it indexes 30+ languages — TypeScript/JavaScript, Python, Go, Rust, Java, C#, C/C++, PHP, Ruby, Swift, Kotlin, and more — so agents no longer assume a language isn't supported and skip the graph. (#671)
-
Anonymous usage telemetry is now stored entirely on CodeGraph's own first-party infrastructure — no third-party analytics vendor receives any of it, and the endpoint that receives it makes no outbound requests at all. Individual events are deleted after 90 days, leaving only anonymous daily totals. Nothing about what is collected changed, your IP address is still never read or stored, and every off-switch works exactly as before (
codegraph telemetry off,CODEGRAPH_TELEMETRY=0,DO_NOT_TRACK=1).TELEMETRY.mdremains the complete field-by-field list.
Fixes
Better answers from codegraph_explore
-
Naming a file by its path in a
codegraph_explorequery now works reliably: the path is resolved against the index and that file is guaranteed a place at the top of the answer. Previously the path was broken into fragments — bracketed route segments like SvelteKit's[id]made this worst — and pieces likepageorrunsmatched every sibling file, so the file you actually named could be crowded out of the answer entirely. A path that doesn't match any indexed file is now called out instead of silently ignored. -
Naming a kebab-case file without its extension in a
codegraph_explorequery —background-image-tablerather thanbackground-image-table.tsx, the way import paths and prose spell it — now returns that exact file too. Previously the name was split at the hyphens, and in a kebab-cased frontend those pieces (background,image,table) are among the most common words in the codebase, so look-alike sibling files filled the answer while the named file never appeared. Hyphenated words that don't name an indexed file, like "cross-call" or "non-blocking", are left alone. -
Plainly-worded
codegraph_explorequestions now find camelCase code: a query like "auto-scroll to bottom" can reach a function namedscrollFeedToBottom, because query words are matched against the words inside identifiers, not just whole names. -
Variables and constants now count when
codegraph_explorepicks its starting symbols, so state held in plain variables —$state-style variables in Svelte, for example — no longer gets overlooked. -
codegraph_explorenow concentrates its answer on the code that actually answers your question instead of spreading it across files that merely share a word with it, so more of the answer arrives in a single call. Thanks @LeDuyViet for the detailed measurements and reproduction. (#1500) -
Files only weakly related to your question now come back as a name, symbol and line number instead of spending the answer on their source — name one of them in a follow-up
codegraph_exploreto get it back in full. (#1500) -
A generated CRUD or protobuf layer no longer crowds out the hand-written code sitting beside it: generated files are now recognized by the
// Code generated by … DO NOT EDIT.style banner written at the top of the file, not just by a filename that looks generated. Re-index after upgrading to pick up the new detection. (#1500) -
Test and spec files in a repository's top-level
test/orspec/directory are now recognized as such, so they no longer take room from the code you asked about. (#1500) -
Generated type-declaration files that announce themselves with a "Generated by … by running …" banner — Cloudflare Wrangler's
worker-configuration.d.tsis the common one — are now recognized as generated. Previously a file like that could take most of acodegraph_exploreanswer on nothing more than a few common words, pushing the hand-written code you asked about out of the response entirely. Re-index after upgrading to pick up the new detection. -
A hand-written type-declaration file — an ambient
.d.tsof global shims, vendored typings, module augmentation — no longer takes over acodegraph_exploreanswer about how something works. Files like these declare common names (Body,Message,ImageMetadata) and nothing else, so a plainly-worded question could match one strongly enough that it ranked first and crowded the actual handler out of the answer. They are now ranked lower for questions about behaviour, and are still listed by name so one follow-up call fetches them. Asking about a type by name still returns its declaration first, and a shared types module the rest of your code imports is unaffected. -
When you name a symbol in a
codegraph_explorequery, its definition now actually comes back. Two cases previously lost it. If the symbols you named don't call one another — sibling functions inside the same factory or module are the everyday example — CodeGraph stopped treating them as symbols you had asked for, and answered with whatever sat at the top of their file instead; on one 1,400-line file that meant a same-stemQueuedMessageinterface on line 70 came back while thequeueMessagefunction on line 1087 did not. And when an answer had to be trimmed to fit, it was trimmed from the bottom of the file down, so a symbol near the end of a long file was always the first thing cut. Trimming now protects the definitions you named wherever they sit in the file. -
A file built around one very long function no longer takes the whole
codegraph_exploreanswer for itself — or disappears from it. Previously such a file was shown in full however big it was, which used up the room every file after it needed, and when the function was larger than the entire response the file was dropped without a word. These files now come back as a bounded window on whole lines — the signature and the top of the body, plus the call site when the call path runs through it — with the rest one follow-upcodegraph_exploreaway. -
codegraph_exploreno longer lets the first file in an answer spend the room set aside for the files below it, so the rest of the answer still arrives. Previously a large file near the top could quietly use up everything left, and the files ranked under it — each already judged relevant enough to include — were dropped with no source at all; on one question only one of six made it into the answer. Every file now keeps what it was given, and a question that really is about one file still concentrates on that file. -
When a
codegraph_exploreanswer runs right up against its size limit, it now drops the trailing notes rather than a whole file's source. Previously the last file was cut even though trimming the notes alone would have fit, so a file that had already been read, ranked and rendered was thrown away at the last moment. Across a range of real projects this returns one more file and up to 20% more source per call. -
Every file
codegraph_exploredecides to include now actually arrives. A file shown in full could still spend room set aside for files below it — the fix above covered files shown as excerpts but not files shown whole — and the answer's own size bookkeeping under-counted each file's heading, so the answer ran past its limit and a fully prepared file was discarded at the end. A file that no longer fits whole is now shown as excerpts instead of vanishing, and one that overshoots by a little is trimmed to fit rather than dropped. -
The list of files an answer could not cover — the "explore these names for their source" pointers — is no longer thrown away when the answer is full. It is now budgeted for and trimmed to fit, so a full answer still tells you what it left out and which names to ask for next, instead of ending with no pointers at all.
-
When a
codegraph_exploreanswer shows a file as excerpts, a large excerpt that no longer fit was dropped entirely instead of being shortened. If the file's first excerpt happened to be a trivial one — an import block, a one-line helper next to the code you asked about — the excerpt carrying the actual answer was the one thrown away, and the file came back with a quarter of the room it had been given. On real projects that meant the top-ranked file delivered a fraction of its share while a far less relevant file took the rest. Excerpts are now shortened to fit, whole method by whole method, and only dropped when what is left is too small to hold anything readable. -
The blast-radius section of
codegraph_exploreflagged "no covering tests found" whenever no test called a symbol directly — falsely branding helpers that tests exercise through their callers as untested (about 40% of flagged symbols in a measured sample). The check now follows caller chains up to 3 hops and reports indirect coverage as "tested via callers"; when nothing is found it states exactly what was checked instead of an unconditional warning. Thanks @inth3shadows for measuring the false-positive rate. (#1475) -
When a file changed on disk after its last index sync,
codegraph_nodeandcodegraph_explorecould return a different symbol's code under the requested name — current file bytes cut at outdated line positions — while presenting it as verbatim, trustworthy source. This hit hardest on projects queried throughprojectPath(for example, sub-projects of a monorepo), which have no live file watcher to flag pending edits. Both tools now verify each file against the index before showing sliced code: an out-of-date file is either shown whole with its full current source, or its code is withheld with a clear "changed on disk" notice — never served as a wrong slice. A fresh re-index restores normal output automatically. Thanks @inth3shadows for the thorough report and verification passes. (#1474)
Finding your project, live updates, and the CLI
-
The MCP server now finds your project when it's launched from a workspace folder above it: if the launch directory has no index of its own but exactly one indexed project sits below it (a repo container, an agent workspace, a monorepo root), that project becomes the session's default — live file watching and the shared daemon included — instead of every tool call failing until a
projectPathor--pathis supplied. Thanks @nakisen. (#1606) -
When no project can be resolved at all, the MCP server now says so instead of starting silently: a startup log line names the directory it searched, and tool calls list the indexed sub-projects it can see nearby so you can pass one as
projectPath. Previously the server looked healthy from the outside while every tool quietly had no project to answer from. Thanks @nakisen. (#1607) -
Editing
codegraph.json'sexcludeorinclude(or a.gitignore) while the MCP server is running now takes effect immediately. Previously the running file watcher kept the scope it had when it started, so a newly excluded file was removed bycodegraph syncand then quietly re-added by the watcher seconds later — which looked likeexcludenot working at all — until the server was restarted. A scope change now refreshes the watcher and triggers a full reconcile, and a changed file the watcher hands to sync is re-checked against the current scope first, so the CLI and the live server can no longer disagree about what belongs in the index. Thanks @K1nG11. (#1590) -
codegraph statusnow sees new files inside brand-new directories. Git reports an entirely-untracked directory as a single collapsed entry, so source files created there — a freshly scaffoldedfrontend/, for example — were missing from the pending-changes report, which could claim everything was up to date while those files had not yet been indexed. Thanks @maxmilian. (#1213) -
The
codegraph context <task>command documented in the CLI help now actually exists — it builds a ready-to-inject context pack for a task (relevant symbols, their relationships, and code) in markdown or JSON, restoring the contract external integrations like Memorix rely on (--path,--format json,--max-nodes,--no-code). (#1611) -
On Windows, the Claude Code prompt hook written by
codegraph installfailed with "command not found" when hooks run through Git Bash, which needs the.cmdextension to find the launcher. The installer now writes the platform-correct command, and re-runningcodegraph install(orcodegraph upgrade) repairs an existing install in place. (#1466) -
Looking a symbol up by name no longer reads the whole graph. Every search made one full pass over all indexed symbols for each word you typed, and a question that named several symbols made two more passes per name — including for a word that matches nothing, which is the common case. The cost therefore grew with the size of the project, and it was paid again on every message when the prompt hook is enabled. These lookups now go through the name index instead. Results are identical; only the time to get them changes, and it no longer grows with the project. Thanks @maxmilian.
Indexing reliability and disk usage
-
Indexing no longer crashes the whole process — a segmentation fault with no message and no partial index — on a C/C++ (or any other) file with extremely deep nesting, such as the parser stress-test fixtures in the clang and gcc test suites or a fuzzer corpus. Such a file is now handed to the fallback parser and recorded with a parse warning while the rest of the repository indexes normally. Thanks @apollo600 for the exact diagnosis. (#1581)
-
Indexing no longer hangs on a Swift Vapor project containing a call with a long argument list. A single
.get(...)-style call with many labeled arguments and nouse:handler — the shape generated request builders produce — could stallcodegraph index,codegraph sync, and the MCP server indefinitely. Route detection now handles such files in milliseconds, and every previously-recognized route shape still parses exactly as before. Thanks @maxmilian. (#1544) (Swift) -
Syncing a large batch of changed files no longer crashes with "Maximum call stack size exceeded" partway through. The crash aborted reference resolution after the files' symbols were already stored, leaving the graph with far fewer connections than a fresh index would have — and it hit exactly the scenarios that re-parse many files at once, including the automatic repair above. Thanks @netbrah for pinpointing the failure. (#1558)
-
A long-lived index no longer drifts away from what a fresh
codegraph indexwould produce. When a file gained or lost a symbol, references to that name in files the sync never touched kept pointing at the definition that was correct before the change, and — because nothing distinguished two same-named definitions — the winner could come down to the order files happened to be written, which differs between a full index and a sync. On this project's own repository, replaying 80 commits throughsyncleft 5.7% of connections wrong; it is now 1.3%, and the wrong-answers-still-being-asserted half drops by 99.7%. Since call edges are what flow questions follow and whatcodegraph_exploreranks files by, this quietly degraded answers as an index aged, with nothing to indicate it. Syncing is unchanged in speed, and an edit that only changes a function's body does no extra work at all. SetCODEGRAPH_NO_REBIND=1to opt out. -
Fixed a v1.5.0 regression where a perfectly valid file could be permanently recorded as having 0 symbols, with no error reported. When a file's first parse attempt was interrupted — a parsing worker crash or timeout, most likely on slow or heavily loaded machines — the automatic retry stored an empty result for any language on the native extraction path, so the file's functions and classes silently vanished from search, callers, and impact until the file was next edited. Retries now store the file's real symbols, and a file already recorded as symbol-free is detected and repaired automatically by the next sync or re-index after upgrading. Thanks @Baiae for the report. (#1541)
-
A CodeGraph process that gets force-killed — by the stuck-process watchdog, a crash, or the OS — no longer leaves the database's write-ahead log behind to grow without bound. Previously each killed session stacked more data onto the same log file and nothing ever shrank it, which on machines where sessions were killed regularly could quietly eat tens of gigabytes of disk. The log's resting size is now bounded (64 MB by default;
CODEGRAPH_WAL_HEAL_MBchanges it), and any oversized leftover is folded back into the index and trimmed automatically the next time the project is opened. This bounds only the log — the index itself has no size limit, and a large repository's log is still allowed to grow in proportion to its index while it is being built. Thanks @tiendungdev for the exceptional Windows report that pinned this down. (#1431) -
The background server's watchdog no longer kills a healthy server that is just waiting on a slow disk: like indexing already does, it now checks whether the database files are still making progress before concluding the process is stuck. Fewer spurious kills also means fewer leftover write-ahead logs. (#1431)
-
codegraph statusnow shows the write-ahead log's size next to the database size and warns when killed sessions have left it oversized, and every line in the background server's log now carries a timestamp so kills and restarts can be placed in time. (#1431) -
A background daemon left behind by an out-of-memory kill or force-kill can no longer block every future session when the operating system reuses its process ID: daemon management now verifies a recorded process is really a CodeGraph daemon before trusting or signaling it, and
codegraph unlockclears stale daemon artifacts as well as the indexing lock. Thanks @hcg1023 for the report and @danusha2345 for the fix. (#1553) -
When indexing has to fall back to parsing a file with its comment lines stripped — a last-resort recovery after repeated parser crashes — the file is now flagged with a visible warning instead of being reported as cleanly indexed. The recovered result can be incomplete, and reporting success made a fresh index quietly disagree with a later re-parse of the same unchanged file. Thanks @jeremypetz for the precise init-versus-sync symbol accounting that exposed this. (#1565)
-
Data-only C/C++ headers near the file-size limit no longer hold a parser worker for several minutes before timing out; the default large-file parse budget is now bounded, while an explicitly configured larger timeout is still honored. (#1555)
-
Reopening an index after a crash during bulk loading now restores every dropped database index, and a successful recovery sync marks the index complete instead of leaving it permanently flagged as interrupted. (#1556)
-
Files skipped because they are too large or repeatedly fail to parse are now recorded with the reason, so unchanged rejected files are no longer rediscovered and retried on every status check and sync — and a later successful parse of such a file replaces the record with its real symbols. Thanks @netbrah for the exceptional failure analysis behind this batch, and @danusha2345 for the fixes. (#1557)
-
C/C++ function-pointer analysis now bounds its compiled-pattern caches, so very large repositories can no longer exhaust the JavaScript engine's regular-expression code space during indexing. (#1559)
-
JSX rendering analysis now runs only on JavaScript-family files, so JSX-looking strings in C/C++ (or any other language) no longer create impossible call edges — in pure-C projects and in mixed-language monorepos alike. (#1560)
Language and framework accuracy
-
Calls to the methods of an exported object-literal constant —
export const api = { call() { … } }used as a module's namespace, a common way to organize a TypeScript API surface — now resolve to the method, both in the defining file and through imports. Previously such a call linked to nothing (or to the constant itself), socodegraph callersand impact analysis reported zero callers for methods that are called from everywhere. Re-index after upgrading to pick up the edges. Thanks @IAliceBobI for the precise report and root-cause. (#1573) -
Import aliases defined in a shared TypeScript config are now picked up. Nx-style monorepos keep every
@scope/...alias in atsconfig.base.jsonthat the roottsconfig.jsononly inherits throughextends, so CodeGraph found no aliases at all and every cross-package import fell back to matching on name alone — which quietly attaches results to unrelated symbols that happen to share a name, exactly where a monorepo needscodegraph_impactandcodegraph_callersto be right. Chains several configs deep, a config inherited from a package innode_modules, and abaseUrldeclared in an inherited config are all followed now, and atsconfig.base.jsonis read directly when the roottsconfig.jsonis only a project-references shell or isn't there at all. Re-index after upgrading. Thanks @maxmilian. (#1534) -
Methods implemented in a generic or lifetime-parameterized
implblock (impl<T> Source for BufSource<T>,impl<'a> Iterator for Parents<'a>) are now recorded under the implementing type instead of the trait. Previously such a method could not be found by its type — "who callsBufSource::read" had no answer — and it collided with the trait's own declaration, which could even invent a call-graph edge out of an impl body that contains no call at all. Impls on a reference (impl Trait for &Foo) and on a module-qualified type (impl Trait for m::Foo) are attributed to their type too. Re-index after upgrading. Thanks @Dshuishui. (#1588) (Rust) -
A method call on a struct field —
self.inner.run()withinner: Inner— now resolves to the method on the field's declared type. Previously the call was reduced to the bare method name and matched whichever same-named method was nearest, which was often the calling method itself, recording recursion that isn't in the source (a few hundred such self-edges in ripgrep alone), or a method of an unrelated type. References andBox/Rc/Arcfields are looked through, as Rust's own method calls are; a field whose type is external (a std or third-party type), a generic parameter, or a container likeOption/Vecis left unresolved rather than guessed. Re-index after upgrading. Thanks @Dshuishui. (#1585) (Rust) -
Erlang functions that share a name but differ in arity are now separate symbols with the language's own
module:fun/arityidentity, so the everydayf/1delegating tof/2shows as a real call edge instead of a self-loop, each arity keeps its own-specand source span,-export([f/1])marks exactly that arity as public, and askingcodegraph_explorefor a symbol the way Erlang spells it —cowboy_req:header/3— returns that definition. Re-index Erlang projects after upgrading. Thanks @Dshuishui. (#1610) (Erlang) -
Erlang behaviour dispatch no longer miscounts a call site's arity when an argument is a binary literal like
<<1,2,3>>— the commas inside were counted as argument separators, which silently dropped (or could mislink) the dispatch edge to the behaviour callback. (#1358) (Erlang) -
A C++
.hheader whose only C++ construct is a plain derived type —struct Derived : Basewith no export macro,classkeyword, or access section — is now recognized as C++ (previously only the export-macro form was). Such a header was read as C, so the derived struct vanished from the index and a phantom function named after the base type appeared in its place. The check now also covers the whole file rather than its first few kilobytes, so a long C-compatible preamble no longer hides the signal. Re-index after upgrading to pick up affected headers. Thanks @Jaysenpeng. (#1592) -
C, C++, Objective-C and Rust unions are now indexed as first-class
unionnodes. Auniondeclaration previously produced no symbol at all, so it never appeared in search orcodegraph_explore, and anything attached to it disappeared with it — in Rust, everyimpl SomeTrait for MyUnionlost its edge, the methods from that impl were left pointing at a type the graph did not contain, and asking which types implement a trait quietly skipped the union ones. A union-shaped dispatch table in C now resolves its function pointers like a struct-shaped one. Atypedef union { … } Name;in C keeps the typedef's name and is no longer mistaken for a plain type alias. Thanks @ctype-lab. Re-index after upgrading to pick up unions in existing projects. (#1515) -
Python classes used as values —
return SomeSerializerfrom a factory method,handler = SomeClassaliases, registry dicts and lists, and classes passed as arguments — now produce reference edges in the graph. Previously these idioms were invisible, so on Django and Django REST Framework projects, asking for a serializer's callers or the impact of editing it missed the views that actually use it. Re-index after upgrading to pick up the new edges. (#1478) -
SAP HANA
.xsjs/.xsjslibimports now resolve across files: an extensionlessimport { x } from './helpers'in a.xsjsfile findshelpers.xsjslib, so the cross-file call edge is created andcodegraph_callers/codegraph_impactsee it. Previously the import path resolved to nothing and the call fell back to same-name matching, which could bind the edge to an unrelated file that happened to export the same symbol. Complements the.xsjs/.xsjslibextraction support. Thanks @maxmilian. (#556)
v1.5.0
2026年07月22日
[1.5.0] - 2026-07-21
⚡ The Rust engine release — with near-instant sync
This release rebuilds CodeGraph's parsing engine as a native Rust kernel, overhauls the resolution pipeline around it, and makes the live graph effectively instant: a save now reaches the graph in well under a second, even on a 27,000-file repository. It is the largest performance upgrade in the project's history — and every graph is verified byte-for-byte identical to the previous engine.
- Native Rust parsing for 20 languages — TypeScript, JavaScript (+TSX/JSX), Java, Python, Go, C, C++, Rust, C#, Ruby, PHP, Swift, Kotlin, Scala, Dart, R, Lua, and Luau now parse in a compiled Rust kernel (Metal and CUDA ride the C++ path). Platforms without a prebuilt binary, and individual files with syntax errors, fall back to the previous engine automatically — same graph either way, proven on repositories from small libraries to the Linux kernel.
- Adaptive to your machine — CodeGraph sizes its parse workers, resolver pool, and caches from what the system actually has: real core counts (container/cgroup-aware, not the host's), honest available memory on macOS and Linux, and measured per-project resolution cost. A big workstation gets the full parallel pipeline; a 2-core VPS gets a pipeline tuned to finish reliably instead of running out of memory — the Linux kernel (70k files) indexes to completion on a 2-core, 6GB machine in under 12 minutes — down from 26 at the start of this cycle.
- Resolution is dramatically faster across the board — adaptive parallel resolution, smarter method-candidate lookup, and memoized supertype/conformance walking. The Swift compiler repository (27k files, Swift + C++) went from over 3 minutes to about 100 seconds within this release cycle; Rust, Lua, and Java-family projects all see double-digit improvements.
- Sync is now near-instant — a save reaches the graph in well under a second, even at compiler scale. The always-on watcher fires after a 300ms quiet window for lone saves (bursts of edits still coalesce), and hands the exact changed paths to sync instead of re-scanning the whole tree — measured save-to-fresh-graph work of ~0.3s on a 4,400-file Java project and ~0.4s on the 27,000-file Swift compiler repository, byte-identical to a full reconciliation.
Full details in the entries below.
New Features
- Indexing TypeScript, TSX, JavaScript, JSX, Java, Python, Go, C, C++, Rust, C#, Ruby, PHP, Swift, Kotlin, Scala, Dart, R, Lua, and Luau projects is faster: parsing and symbol extraction now run in a native engine when a prebuilt binary is available for your platform (release bundles include one), producing exactly the same graph — verified byte-for-byte against the previous engine on real repositories, from small libraries up to vscode-, dubbo-, django-, git-, protobuf-, tokio-, rust-analyzer-, jellyfin-, rails-, symfony-, swift-nio-, kotlinx.coroutines-, ggplot2-, Kong-, Scala-3-compiler-, and Flutter-scale codebases (Lombok-generated members, C function-pointer tables, and Unreal-Engine-style macro-heavy headers included; CUDA and Metal sources ride the C++ path). The speedup is largest on resource-constrained machines like CI runners. No setup needed: platforms without the native binary, and individual files with syntax errors, automatically use the previous engine, and
CODEGRAPH_KERNEL=0turns the native path off entirely. - Reference resolution now runs in parallel on large projects. When a project has enough pending references to make it worthwhile (roughly 150k+, typical for big Java/Kotlin/Spring codebases), resolution fans out across worker threads while results are applied in the exact order the single-threaded path would have used — the graph comes out byte-for-byte identical, about twice as fast end-to-end on a 4,000-file Java project in our testing. Small projects keep the single-threaded path automatically (the fan-out costs more than it saves there). Set
CODEGRAPH_NO_PARALLEL_RESOLVE=1to disable, orCODEGRAPH_PARALLEL_RESOLVE_MIN=<count>to tune when it engages. - Indexing large projects got another sizeable speedup — about a quarter less wall-clock on the same 4,000-file Java project, with the graph still byte-for-byte identical. Two changes: the database no longer interleaves expensive checkpoint housekeeping into the middle of resolution on a fresh index (it's folded once at the end instead), and while one batch's results are being written out, the worker threads are already resolving the next batch instead of sitting idle.
- The dynamic-dispatch analysis that runs at the end of indexing (callback, event, and framework wiring) now runs its passes in parallel on large projects, cutting that stage roughly in half there — and a pass that crashes now retries safely instead of failing the whole index, which also makes very large codebases that previously died in this stage more likely to index to completion. Graphs remain byte-for-byte identical.
- On large projects, indexing writes its relationship data noticeably faster: secondary database indexes are set aside during the bulk of reference resolution and rebuilt once at the end, instead of being maintained row by row. Graphs remain byte-for-byte identical, and small projects are unaffected.
- Very-large-codebase reliability: on multi-million-symbol projects, an analysis pass that fails on a worker thread is now skipped with a clear message instead of being retried in a way that could take down the whole index, and the end-of-indexing index rebuild no longer risks tripping the liveness watchdog on huge graphs. Validated end-to-end on the Linux kernel (70k files, 2M symbols, 6.4M relationships) — it now indexes to completion even on a 2-core machine.
- Indexing is significantly faster — a fresh
codegraph initon a medium TypeScript project takes about a third less wall-clock time, with the same graph produced byte-for-byte. The gains come from batching database writes, storing files on a dedicated writer thread, memoizing repeated import-resolution lookups, skipping per-row search-index maintenance during the bulk build (rebuilt once at the end), and — on completely fresh databases only — deferring disk durability until the index completes, since an interrupted first index is simply re-run. SetCODEGRAPH_NO_FAST_INIT=1to keep full crash-durability during the initial build, orCODEGRAPH_NO_STORE_WORKER=1to store on the main thread. codegraph installandcodegraph upgradenow offer CodeGraph Pro beta access after finishing — answer yes, type your email, and you join the same waitlist as the getcodegraph.com homepage form. Strictly opt-in and asked at most once per machine total: nothing is sent unless you say yes and enter an email, either answer is remembered so no later install or upgrade ever re-asks, and non-interactive runs (--yes, scripts, CI) never see the question.- Every release is now cryptographically verifiable: npm packages publish with npm provenance (the "Provenance" badge on npmjs.com, proving each version was built by this repository's release workflow from a specific commit), and the GitHub Release bundles carry signed build attestations you can check with
gh attestation verify <file> -R colbymchenry/codegraph. - Indexing inside CPU- or memory-limited containers (Docker, CI runners) now sizes its worker pools from the container's actual allowance instead of the host machine's, and giant codebases no longer balloon temporary database files during indexing (previously tens of GB of transient disk on Linux-kernel-scale projects). Together these prevent out-of-memory and out-of-disk failures on constrained machines; set
CODEGRAPH_RESOLVE_WORKERSto override the resolution worker count explicitly. - Indexing very large projects on multi-core machines got faster again: the parallel-resolution workers now periodically refresh their read-only database connections, which lets database housekeeping advance instead of silently building up a backlog behind long-lived readers — a backlog that was taxing the indexer's own writes. Graphs remain byte-for-byte identical; the win is largest at Linux-kernel scale on many-core machines.
- Indexing on macOS now uses the machine's real memory headroom when sizing its parallel-resolution workers. macOS deliberately keeps RAM filled with reclaimable cache, so the previous free-memory reading came back tiny (~1GB on an otherwise idle machine) and silently halved the worker pool — a medium Java project's fresh index ran about 15–20% slower than the hardware allowed. Graphs remain byte-for-byte identical; the same fix also lets a memory-driven analysis cache engage fully on macOS for large C codebases.
- Fresh indexing got a sizeable across-the-board speedup: during the initial build, the database's secondary lookup indexes are set aside and rebuilt once after parsing instead of being maintained row by row — the same proven trick the later linking phase already used, now applied to the whole parse lane — and the reference-resolution loop likewise stops maintaining lookup indexes it never reads, rebuilding them at the end when almost nothing is left in the table. A medium Java project's parse phase runs about 58% faster and its full fresh index about 19% faster end-to-end; a Linux-kernel-scale index that took ~15 minutes on an 8-core machine now completes in about 11, with the resolution phase alone dropping by a third. Graphs remain byte-for-byte identical, and incremental syncs are unaffected.
- Saving a file now updates the graph almost immediately: the file watcher fires after a 300ms quiet window for one or two changed files (bursts still coalesce under the full debounce, and
CODEGRAPH_WATCH_DEBOUNCE_MSremains the upper bound), and watcher-triggered syncs reconcile exactly the changed paths instead of stat-walking the entire repository. Directory deletions and event storms still run the full scan-diff, so nothing the events can't describe is ever missed. Measured: save-to-fresh-graph sync work drops to ~0.3s on a 4,400-file project and ~0.4s on a 27,000-file one, with resulting graphs byte-for-byte identical to a full reconciliation. - Indexing Swift and other protocol/interface-heavy codebases got dramatically faster: the conformance walk that checks whether a method lives on a receiver's supertypes (protocols, base classes, extensions) now remembers its answers for the duration of each resolution batch instead of re-querying the graph for every call site — on the Swift compiler repository (27k files) that walk ran nearly a million times per index. A fresh index of that repo drops from about 185 seconds to under 100, with the graph byte-for-byte identical. Method-candidate lookup also gained a per-name owner index, so overload-heavy names (
initin Swift,executein Java) no longer pay a full candidate scan per receiver type. - Resolving method calls through local variables (
recv.method(), Lua'srecv:method(), R'srecv$method()) got much cheaper on repos where the same receiver is called over and over: the declaration scan that types the receiver now remembers what it has already scanned per scope instead of re-reading the same source lines for every call site, and the regex patterns it scans with are compiled once per receiver instead of per call. Kong's fresh index drops another 8% on top of the require-resolution fix (23% cumulative), with graphs byte-for-byte identical everywhere — including Java projects, where this same scan successfully types tens of thousands of receivers. - Indexing Lua and Luau projects got a sizeable speedup: resolving each
require(...)no longer rescans the project's entire file list four times — a per-project filename index answers the same lookup instantly, cutting per-require resolution from about a millisecond to microseconds. A fresh index of Kong (1,870 Lua files) runs about 16% faster end-to-end, with the graph byte-for-byte identical. The same housekeeping also closes a latent staleness edge where COBOL copybook lookups could keep serving a cached file list after files changed. - Parallel reference resolution now engages adaptively instead of by a fixed project-size cutoff: the indexer measures the actual per-reference resolution rate on the first batch and spins up the worker pool mid-run whenever the remaining work justifies it. Languages whose references are expensive to resolve benefit most — Rust especially: a fresh index of tokio runs about 23% faster, with the graph byte-for-byte identical. Small projects and low-core machines (2-core CI runners) keep the single-threaded path exactly as before.
- The dynamic-dispatch analysis at the end of indexing now skips passes that provably can't produce anything for the project at hand: React re-render bridging when no class has a
rendermethod, React Native and Expo cross-platform pairing when the required languages aren't present, and MyBatis mapper linking when there's no mapper XML. Previously each of these scanned the whole graph before coming up empty — on a 4,000-file Java project that was about 0.9 seconds of wasted analysis per fresh index. The interface-implementation bridging pass also got cheaper on real work: it no longer re-fetches a hub interface's method list once per implementer, and classes that extend or implement nothing are skipped before any per-class lookups. Graphs remain byte-for-byte identical. - Indexing large C and C++ codebases spends much less time in the function-pointer dispatch analysis (the pass that connects handler tables like a command table or an ops struct to their call sites): each source file is now read and prepared once instead of four times, files that can't contribute any dispatch wiring are skipped outright in the later linking steps, and on platforms with the native engine the per-file scanning itself now runs natively too. On a Linux-kernel-scale tree the pass runs about a third faster end-to-end, with graphs byte-for-byte identical; platforms without a native binary keep the same results on the previous path.
Fixes
- TypeScript, TSX, and JavaScript files now parse with up-to-date grammars — modern syntax such as
usingdeclarations and import attributes no longer trips parse errors that could drop surrounding symbols. (The previously bundled grammars dated from 2023.) - Rust files also parse with an up-to-date grammar now (the previously bundled build dated from 2023), which additionally sharpens method-call attribution: calls through struct fields resolve with receiver context instead of falling back to ambiguous bare-name matching, removing a class of wrong call edges on common names like
lenandstart. - Ruby files also parse with an up-to-date grammar now (the previously bundled build dated from early 2024), which fixes a misparse of safe-navigation operator-method calls (
recv&.!= x) that had recorded the wrong callee name. - PHP files also parse with an up-to-date grammar now (the previously bundled build dated from 2023): files using modern PHP features — enum constants, PHP 8.4 property hooks, parenthesis-free
new X()->method()chaining — no longer hit parse errors or misparses that dropped or garbled their symbols, so codebases like Symfony and Laravel index substantially more accurately. - Swift files also parse with an up-to-date grammar now (the previously bundled build dated from 2023): swift-testing
#expect,#Preview-style macros, thepackageaccess modifier, and typedthrowsno longer produce parse errors that dropped surrounding symbols — server-side Swift projects like Vapor see the biggest recovery. - Dart's grammar is now bundled with CodeGraph itself instead of being resolved from a third-party package whose Dart build floated on an unpinned upstream reference — a routine dependency update can no longer silently change how Dart files parse.
- Searching or exploring by field names now finds the code that defines them. A query made of object keys or API field names (
profileInfo isTrialEligible quotaInfo billingMethod) used to return unrelated results while the defining files never appeared, because three retrieval steps each dropped multi-word camelCase terms: an internal case-comparison bug, a match step that only considered classes (never functions or methods), and exploration seeding that required exact symbol-name matches. All three are fixed —codegraph_explorewith a bag of field names now surfaces the controllers and services that assemble those fields. (#1196) codegraph.json'sincludeIgnoredworks again for the "folder of repos" layout: when one.gitignorerule covers a parent directory (/repos/) holding several embedded git repositories, opting in the individual repos ("includeIgnored": ["repos/a/"]— the exact spellingcodegraph init's own hint suggests) previously matched nothing and indexed zero files, looping the same suggestion back at you. Both spellings now work — name the parent directory to opt in everything under it, or name individual repos to opt in just those — and the hint no longer re-suggests repos that are already configured. (#1295)- Method calls on literals (
", ".join(...)in Python,"x".split(...)in JavaScript, and the like) no longer produce call edges to unrelated project functions that happen to share the builtin's name — a codebase with a function calledjoin,get, orupdatecould show phantom callers from every string-builtin use. Additionally, a function nested inside another function is now only matched as a call target from inside its container, since it isn't reachable from anywhere else. Blast-radius and affected-test results get cleaner on Python and JavaScript codebases especially. (#1230) - Go method calls through a struct field (
target.conn.Exec(...)) no longer bind to unrelated same-named local methods when the field's type is external —conn *sql.DBcalls were being attributed to a local interface that happened to declareExec, fabricating internal dependencies. Chained field calls now resolve by inferring the field's declared type from the struct definition: in-project types (including unexported ones like chi'stree *node) gain correct, validated call edges that never existed before, and external types (standard library, third-party modules) are left unlinked instead of guessed. (#1276) - TypeScript/JavaScript method calls through an imported singleton (
import { store } from './store'; store.notify()) now resolve to the class method instead of the exported constant, socodegraph callerssees cross-file callers of the method — previously only same-file calls were attributed and a method used everywhere could look unused. The same declaration-based type inference applies across the languages that share it (Python, Java, Kotlin, Go, and more), and a failed inference keeps the old edge rather than guessing. (#1292) codegraph node <symbol> -f <file>now prints the symbol's source body. Pinning an ambiguous name to a specific file (the whole point of-fwhen many files define the same function) returned only the location and caller trail with no code. (#1284)- Deleting a whole directory is now picked up by watch mode: the files inside it are removed from the index on the next auto-sync instead of lingering as stale records until an unrelated edit happened to trigger one. Operating systems often report a directory deletion as a single event on the directory itself (with no per-file events for its contents), which the watcher previously discarded. (#1285)
codegraph syncnow gets the same slow-disk fix that made full indexing fast in 1.4.0: database checkpointing is deferred for the whole incremental run instead of firing every few megabytes of writes. On mechanical drives and other high-latency storage, a small sync on a large index no longer stalls for minutes at near-zero CPU — the cost of a sync scales with what changed, not with the size of the existing index. The sameCODEGRAPH_NO_WAL_DEFER=1switch turns it off. (#1248)- C functions declared with a project-specific attribute macro in front of a typedef'd return type (
SEC_ATTR UINT32 MyFunc(VOID)— common in embedded and kernel code) are now indexed under their real names. Previously the parser tripped over the unknown macro and stored the parameter list as the function name, leaving entries like"(VOID)"in the graph and making the real function unfindable. (#1211) - Macro-heavy C and C++ code indexes much more completely. Fifteen ubiquitous idioms that previously tripped the parser into error recovery — dropping symbols, garbling names, minting phantom entries, or losing the relationships between real ones — now parse cleanly: the
#ifdef __cplusplus/extern "C" {compatibility guard in C headers, iterator macros in statement position (list_for_each_entry(pos, head, member) { … }and the whole Linux-kernel/git/jemalloc family — including calls that wrap across lines, likehlist_for_each_entry_rcu(…)with alockdep_is_heldargument), the Linux/sparse declaration annotations (static int __init foo(void),void __user *buf,container_of(p, struct T, m)), parameterized annotations (__free(kfree),__printf(4, 0),__counted_by(count)), per-CPU and work-queue declaration macros (static DEFINE_PER_CPU(struct T, name);, initialized forms included), bare type arguments to allocator and list macros (kzalloc_obj(struct T),list_entry(p, struct T, member)),va_argwith a qualified or pointer type, GNU named-variadic macro definitions (#define dbg(fmt, args...)),static notrace-style compiler markers, C23autodeclarations, trailing parameter annotations (int argc UNUSED, git's house style), namespace-management macros alone on a line (FMT_BEGIN_NAMESPACE, Qt'sQ_OBJECT), and function attribute macros in front of C++ return types. On the Linux kernel this cuts files lost to parse errors on the core directories by nearly half and recovers thousands of call and reference relationships that error recovery silently dropped, with git and redis seeing smaller cuts of the same kind; graphs stay byte-for-byte identical between the native and fallback engines. A related fix stops the macro handling itself from corrupting#definelines that mention the same macro names, which removed a class of phantom parse errors in fmt-style headers. - C++ methods defined out-of-line inside a namespace (
namespace sim { Output MyClass::Apply(...) { ... } }) now carry the namespace in their qualified name, matching their class. Fully-qualified call sites from other files (sim::MyClass::Apply(...)) resolve to the definition again, socodegraph callersand file impact no longer come up empty for this pattern. (#1291) - C++ methods defined out-of-line on a template class (
template <typename T> T Box<T>::get() { ... }) no longer keep the template parameter list in their qualified name. They now index asBox::get— identical to an inline definition of the same method — so they link to their class and resolve from call sites again, and pathological multi-line template parameter lists can no longer blow the qualified name past filesystem name limits. (#1286) - Go route detection no longer misidentifies ordinary method calls that share HTTP verb names —
cache.Put("key", value),store.Get("config", out),bus.Handle("user.created", handler)and the like were being indexed as HTTP routes, polluting route listings in cache-heavy codebases. A registration now has to look like one: its first argument must be a/-prefixed path (all routers) or a Go 1.22"METHOD /path"pattern onHandle/HandleFunc, which now also extracts the method instead of listing the route asANY. (#1259) - Progress output on Windows no longer mixes ASCII
|rails with the Unicode│ ◆ ●frame around them. In terminals that render Unicode (Windows Terminal, VS Code, ConEmu/Cmder, JetBrains, Alacritty), the wholecodegraph init/index/syncblock now draws with matching box-drawing characters; unrecognized legacy consoles keep the safe all-ASCII output that avoids garbled characters.CODEGRAPH_ASCII=1/CODEGRAPH_UNICODE=1still override in either direction. (#398) - CLI output now honors the
NO_COLORconvention and new--color/--no-colorflags, and goes plain automatically when piped: commands likecodegraph status,query,callers, andfilesno longer embed ANSI color codes when stdout isn't a terminal, and a pipedcodegraph init/index/syncprints simple per-phase lines instead of progress-animation control characters.FORCE_COLORor--colorforces color back on for pipes that render it. (#1281) - Callers and impact analysis no longer silently under-count a function that calls the same callee many times. When one caller contained several call sites to the same callee and an internal resolution batch boundary happened to split them, cleanup after the first batch removed the later sites' pending rows before they were ever attempted — their edges were never created, deterministically, and which edges went missing shifted with unrelated changes to the project's total reference count. Post-pass cleanup now targets the exact database row each processed reference came from. Found while validating the operator-call fix on nlohmann/json, where
write_cbor's 11 calls toto_char_typeindexed as 10. (#1269) - C++ explicit operator calls —
a.operator+(b),p->operator+(b),a.operator[](3), and the other symbolic forms — now produce acallsedge to the operator method, so an operator invoked only through the explicit syntax no longer looks uncalled in callers and impact analysis. tree-sitter parses these call sites with the operator name stranded in an error node (never as a normal member access), so the call's target was silently read as just the receiver variable; the operator name is now recovered from the error node and resolved through receiver-type inference like any other member call — a same-named operator on an unrelated class can never capture the edge. Infix uses (a + b,a[i]) need real type inference and are tracked separately. (#1247) codegraph initandcodegraph indexno longer look hung after "Resolving refs" reaches 100%. The dynamic-dispatch linking that runs after resolution (callbacks, React re-renders, C function pointers, and the rest) had no progress display, so on repos where it takes a while — large C codebases especially — the bar just sat frozen at 100% until it finished. That work now shows as its own "Linking dynamic dispatch" progress phase, and the heaviest pass — C function-pointer linking — additionally reports progress within the pass, so a large C codebase advances the bar smoothly instead of parking it on one number for the bulk of the phase.- Indexing no longer prints repeated "SQLite is an experimental feature" warnings that garbled the progress display. The warning comes from Node's built-in SQLite and fired once per parsing worker; it's now suppressed on every launch path.
v1.4.1
2026年07月11日
[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 incodegraph_status. Nothing updates by itself, and being offline just means no notice. Opt out withCODEGRAPH_NO_UPDATE_CHECK=1;DO_NOT_TRACK=1disables it too. (#1243)
Fixes
codegraph upgradeon a Windows npm install actually runs npm again — modern Node refuses to launchnpm.cmddirectly, so the upgrade failed with a spawn error before doing anything. npm is now invoked the way a terminal would run it. (#1238)codegraph uninstallnow actually uninstalls CodeGraph. It used to remove only the agent configurations and leave every installed binary behind, socodegraphstill 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 (--yesskips the prompt). Machine-level settings like your telemetry choice are preserved, a source checkout is never touched, and the new--keep-cliflag restores the old configs-only behavior. (#1071)codegraph_exploreno 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 upgradenow 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 ascodegraph install --refresh, and skippable withCODEGRAPH_NO_INSTALL_REFRESH=1. (#1238)codegraph upgradeon an npm install now upgrades through npm again instead of quietly creating a second copy that never wins the PATH race — previouslycodegraph --versionkept reporting the old version forever, no matter how many times you upgraded. (#1238)- After every upgrade, CodeGraph now checks that the
codegraphcommand 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 initthe 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
2026年07月10日
[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 withCODEGRAPH_WAL_VALVE_MB. (#1231) - New
CODEGRAPH_PARSE_TIMEOUT_MSenvironment variable to raise the per-file parse budget on unusually slow storage, the same wayCODEGRAPH_PARSE_WORKERSalready 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
2026年07月09日
[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 syncstay 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
2026年07月08日
[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:letand attrset bindings, functions (simple, destructured{ pkgs, ... }, and curried), andinheritbindings all become searchable symbols, with call edges between bindings. File-level wiring follows the ways Nix actually connects files:import ./relative/path.nix(withimport ./dirreaching the directory'sdefault.nix), NixOS moduleimports = [ ./hardware.nix ../common ]lists, flake-stylemodules = [ ./configuration.nix ]lists, and the nixpkgscallPackage ./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 = { ... }orhome.file.".gitconfig" = { ... }links to the module that declares that option (options.launchd.user.agents = mkOption { ... }— flat and nested declaration spellings both count, quoted keys likesystem.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/@ComponentV2structs 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/@Stylesfunctions they invoke,@Buildermethods 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 bareimport { CartRepository } from "data"follows theoh-package.json5file:dependency to the right module — honoring each module's declaredmainentry, from.etsand.tsconsumers alike — while ambiguous names in multi-app monorepos deliberately stay unlinked rather than guessed, and mixed.ets/.tscodebases 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'sbuild()(the re-render hop — assignment-gated, so a method that merely reads state gets no edge);emitter.emit(eventId)links to the matchingemitter.on/oncesubscriber 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); androuter.pushUrl({ url: 'pages/Detail' })links to the target page's@Entrystruct, 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 statusreports as a truncated index, a completed run that dropped files reports itself as partial — both in the human output and instatus --json— andcodegraph indexprints 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 everylocalsattribute become symbols (e.g.aws_s3_bucket.my_bucket,var.region,module.vpc,local.prefix), and uses likevar.region,module.vpc.id,data.aws_caller_identity.current, oraws_s3_bucket.my.arnare 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: amoduleblock's inputs link to the child module's variables,module.vpc.vpc_idreaches the child'soutput "vpc_id"definition, and the block's localsourcepath 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/atmosremote-statemodule connects too:module.vpc.outputs.vpc_cidrin one component reaches thevpccomponent'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, andprovider = aws.easton a resource (or a module'sprovidersmap) links to that configuration, found up the module tree the way Terraform actually inherits it.moved/import/removedstate-migration blocks andcheckassertions reference the resources they name, so a refactor's paper trail is part of the graph..tfvarsassignments 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 onvar.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'sDEFINE_FLASH_FORWARD_KERNEL(kernel_name, ...) { ... }style), which now index under their real kernel names. CUDA that lives in plain.h/.hppheaders — 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
namespaceblocks now carry the namespace in their qualified name (flash::compute_attn, C++17namespace 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 followemit,revert, modifier guards (onlyOwner-style, including base-constructor chains likeconstructor() ERC20(...)), and library/method calls (includingusingdirectives).importdirectives resolve to the imported file, so cross-contract questions like "tracetransferFromthrough allowance and balance updates" or "how doesonlyRolereach 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:executefolds, a plugin manager'sMod: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/-opaquealiases,-definemacros, and-specsignatures attached to every function. Cross-modulemod:fn(...)calls resolve to the target module's function,fun name/arityvalues are captured as references (so callback registrations likelists:foreach(fun submit/1, ...)link up),-include/-include_libconnect to the header files they pull in,-behaviourdeclarations link a callback module to its behaviour (and only ever to a module — a same-named macro or function elsewhere in the repo is never mistaken for one), and-exportlists (plus-compile(export_all)) drive each function's public/private flag. OTP's indirection idioms are followed where the target is static:spawn/apply/proc_lib/timer/rpccalls that name their target as(Module, Function, Args)arguments produce call edges, andgen_server:call/castconnects to the target module'shandle_call/handle_cast— its own when targeting?MODULE(including the-define(SERVER, ?MODULE)idiom), and the named module when a registered name follows OTP's name-the-server-after-its-module convention (gen_server:call(other_mod, ...), directly or through a-define(STORE, other_mod)macro); a registered name that matches no module stays unlinked. Macros participate in the graph too: a-definebody's calls belong to the macro, each?MACRO(...)use site links into the call chain (and bare?CONSTANTreads are tracked as references), so a call path hidden behind a macro —set_password → ?SQL_UPSERT_T → sql_query_t— traces end-to-end and "where is this macro used" is answerable. escripts index like any module (the shebang line is understood), and OTP application resource files (.app.src,.app) join the graph:{mod, ...}links an app to its callback module and{applications, [...]}connects umbrella sibling apps — resolving only ever to modules, so an OTP app name likesslis never mistaken for a same-named function. Truly dynamic dispatch (Mod:handle(...), message sends, var-module spawns) is deliberately left unlinked rather than guessed.codegraph_explorealso understands Erlang-native symbol spelling in queries —mod:fn/3andinit/2find the symbols they name. (#635, #648) - CodeGraph now indexes Visual Basic .NET (
.vb) — classes, Modules, interfaces, structures, enums, properties, events,MustOverrideabstract members, andDeclareP/Invoke signatures, withInherits/Implementshierarchy edges, call edges (resolved through VB's ambiguous call-vs-index parentheses), andNew/As Newinstantiation links. Real-world VB styles parse cleanly: WinForms designer files, interpolated and multi-line strings, XML literals (embedded<%= %>expressions included), single-line and multi-line LINQ queries, multi-line lambdas,Handles/WithEventsevent wiring, Custom Events, date literals, classic type-character identifiers (i%,name$), and non-English (Unicode) identifiers. (#648, #639, #170) - CodeGraph now indexes COBOL (
.cbl,.cob,.cpy) — programs, sections and paragraphs withPERFORM/GO TOcall edges,CALLcross-program calls,COPYcopybook imports (standalone copybooks included), and DATA DIVISION records with 88-level condition names, in both fixed and free source format. Impact queries work on data items: everyMOVE/ADD/COMPUTE/SUBTRACTwrite-site links back to the field it changes, so "what touches this copybook field" answers across programs. CICS flows connect too:EXEC CICS LINK/XCTLprogram targets,EXEC SQL INCLUDEcopybooks, and pseudo-conversationalRETURN TRANSID(...)hops resolve to the program owning the transaction id. (#590, #648) - CodeGraph now indexes CFML (
.cfc,.cfm,.cfs) — both the classic tag-based style (<cfcomponent>/<cffunction>) and modern bare-scriptcomponent { ... }syntax, includingextends/implements, embedded<cfscript>blocks (at any nesting depth, including inside<cfif>/<cfloop>/<cftry>), call edges, and calls embedded in#hash#expressions inside<cfquery>SQL bodies. Files saved with a UTF-8 byte-order mark and tags with unquoted attribute values — both common in long-lived CFML codebases — are handled too. Thanks @ghedwards. (#1118) - CFML inheritance written as a component path now links to the right component.
extends="coldbox.system.web.Controller"names its supertype by dotted path andextends="../base"by relative path (the FW/1 style) — both previously produced no inheritance edge at all, which on framework-style CFML apps hid most of the type hierarchy from impact and blast-radius analysis (on ColdBox's own core, over 90% of inheritance was invisible). Resolution is deliberately conservative: the target's directory layout must corroborate the declared path — so a supertype that lives in an out-of-repo library (testbox, mxunit, an installed framework) correctly stays unlinked rather than being guessed at, and an ambiguous path produces no edge rather than a wrong one. (#1152) - CFML method calls made through a local variable, typed argument, or component property now resolve to the right method — the same receiver-type inference the other object-oriented languages already had.
var svc = new UserService(); svc.save(),createObject("component", "path.UserService"), a typed<cfargument>or cfscript parameter, andvariables./this.-scoped fields — including the pseudoconstructor pattern (variables.svc = new UserService()ininit()) and WireBox-injected properties (property name="svc" inject="UserService") — all now link the call to the declared component's method, with methods inherited from a supertype resolved through the inheritance links above. This makes callers, impact/blast-radius, andcodegraph_exploreflow traces follow CFML service calls instead of dropping them or guessing among same-named methods. - The Claude Code context hook now recognizes prompts that describe code in plain words — in any language — by checking the prompt's words against the symbol names actually in your project's index. Asking about "the state machine des commandes" finds
OrderStateMachinewith no keyword involved. Confidence decides how much gets injected: structural questions and prompts naming a real symbol still get full context up front; a plain-words match gets a short pointer to the matching symbols so the agent queries them itself; everything else stays silent, exactly as before. - Anonymous usage telemetry now counts how often the context hook injected context, offered a hint, or stayed silent — fixed counter names only; the prompt's content is never stored or sent. This makes the hook's accuracy measurable instead of guessed. The counters record what actually happened, not what was attempted: a lookup that errors or comes back empty counts as a distinct silent outcome, never as delivered context (#1143, thanks @inth3shadows).
- Metal shader files (
.metal) are now indexed. Metal Shading Language is close enough to C++ that vertex/fragment/kernel functions, structs, type aliases, and the calls between them all land in the graph — so shader pipelines in Apple-platform projects show up in impact analysis and flow traces instead of being silently skipped. Metal's[[buffer(0)]]-style attribute annotations are handled so they can't corrupt what gets extracted. Thanks @FluxKo for the report. (#1121) - CodeGraph now indexes legacy iBatis 2 SQL maps (
<sqlMap>), not just MyBatis 3<mapper>files.<select>/<insert>/<update>/<delete>, iBatis's<statement>/<procedure>, and<sql>fragments inside a<sqlMap>become searchable statement symbols — for both namespaced maps and the namespace-lessMap.statementid style — and<include>references resolve to the fragment they pull in, so search, callers, and impact queries return results on iBatis codebases that previously produced no statement symbols at all. Thanks @ESPINS for the report and the reproduction. (#1182) - You can now force gitignored first-party source into the index with an
includelist incodegraph.json. The case this solves: a project tracked by a second VCS (SVN, Perforce, …) alongside Git, where some real source is committed to that VCS and deliberately listed in.gitignoreso it never lands in Git — git never lists those files, so CodeGraph never indexed them, and neitherincludeIgnored(which only revives embedded git repositories inside a gitignored directory) norexclude(its opposite) could help. Add a rootcodegraph.jsonwith, e.g.,{ "include": ["Tools/", "Local/typescript/"] }and CodeGraph discovers those files directly off disk — overriding.gitignore— and indexes them on the full index, incrementalsync, and file-watching, on both git and non-git projects. Patterns are gitignore-style and matched against project-root-relative paths (a directory, a recursive**glob, or a single file). An explicitexcludestill wins, and built-in skips likenode_modules,dist, and.gitare never re-included. This complements the existingexclude(its opposite — keep tracked files out) andincludeIgnored(opt in to gitignored embedded repos).
Fixes
- Indexing a large Java or Kotlin Spring monorepo is dramatically faster. The reference-resolution phase — the bulk of a first-time
codegraph index— could run for the better part of an hour on a big multi-module project and now finishes in a few minutes, producing the same graph. The cause: everyreceiver.method()call in the codebase was repeatedly scanning the project's entire set of configuration keys looking for a match — work that only ever applies to Spring@Value/@ConfigurationPropertiesbindings, never to ordinary method calls. As part of the same fix, a method call whose name coincides with a configuration key (say aservice.process()call alongside aservice.processentry inapplication.yml) is no longer mislinked to that config key — it now resolves to the actual method. Thanks @bayernjava for the report. (#1180) codegraph initat a parent repository whose.gitignoreexcludes its child repositories no longer silently indexes nothing and reports success. The "super-repo of gitignored child repos" layout — a top-level Git repo that.gitignores eachservice-*/orpackages/*child sogit statusstays quiet — used to index only the parent's few top-level files and print "Done" with 0 nodes, even though runningcodegraph initinside any child worked fine (CodeGraph respects.gitignoreby default, so the excluded children were skipped). Now, when an index comes up empty, CodeGraph detects the gitignored child repositories that were skipped, names them, and — in an interactive terminal — offers to index them (writing anincludeIgnoredentry tocodegraph.jsonand re-indexing on the spot); non-interactive runs print the exactcodegraph.jsonsnippet to add. Projects that legitimately keep gitignored reference clones out of a working index are never nagged: the offer only appears when the index would otherwise be empty. Thanks @small-thanks for the report. (#1156)- The MyBatis mapper reader is sturdier on real-world XML. Single-quoted attribute values (
id='getById', legal XML and common in older mappers) are no longer skipped, so those statements make it into the graph. Statements and<include>s that were commented out with<!-- ... -->no longer produce phantom symbols. And two vendor-split statements — the sameidwithdatabaseId="oracle"/databaseId="mysql"— written on a single line no longer silently drop one of the pair. Thanks @ESPINS for the report, the reproductions, and the fixes. (#1182) codegraph initandcodegraph indexno longer get killed by the safety watchdog at the "Resolving refs" step on large method-name-heavy codebases (big Java/enterprise monorepos were the main victims, especially on slower machines). Resolution used to come up for air only every 500 references, so a dense stretch of expensive ones could starve the watchdog long enough for it to assume the process was stuck and kill a perfectly healthy index. Resolution now checkpoints after every reference, and two of the expensive steps got much cheaper: repeated method lookups on the same type are now cached, and source files are no longer re-split line-by-line for every call being resolved — indexing such repos is several times faster as a result. Generated or minified single-line files are also skipped during receiver-type inference instead of being scanned per call. Thanks @UchihaYong and @wangmeng-95 for the reports. (#1122)- An index left incomplete by an interrupted run now heals itself on the next sync instead of silently staying wrong forever. If indexing died partway through resolving references (a crash, Ctrl-C, or the watchdog kill fixed above), the affected files still looked indexed but their caller/impact edges were missing — a too-small blast radius clustering by package or module, e.g. a Spring
@Resource-injected method reporting 3 of its 10 real caller files — and because incremental syncs only re-resolve files that changed, the damage was permanent until a full re-index. Any sync (a watched file change, or a barecodegraph sync) now detects the leftover references and finishes resolving them,codegraph statuswarns when an index is in that state instead of passing it off as healthy, and a rare early-stop that could abandon resolution on repos whose first files reference only external libraries is fixed too. Thanks @KnifeOfLife for the report and the package-correlation observation that pinned it down. (#1187) - The shared background server no longer shuts down out from under a live editor/agent session that simply hasn't queried CodeGraph in a while. A safety timer meant to reap an abandoned server — one whose client vanished without the connection ever closing — was reaping any server that saw no requests for 30 minutes, including a perfectly live session that just wasn't asking CodeGraph anything; that silently dropped the session (and every other session sharing the same background server) to a slower in-process mode for the rest of its life. On one machine over a day it fired 20 times on live sessions and caught zero real phantoms. The timer now checks whether the connected clients are actually still alive and only reaps when none of them are, so a quiet-but-live session keeps its shared server while a genuinely abandoned one is still cleaned up. (#1200)
- CodeGraph's background server no longer leaves a lingering Node process behind when your editor or agent kills its launcher during startup. If the app that started CodeGraph (Codex, Claude Code, or another MCP client) was killed within the server's first fraction of a second — a config probe, a cancelled request, a startup timeout — while keeping the connection's pipes open, the server could be handed off to the system before its orphan-detection watchdog had captured a reference point, leaving it running (idle, ~30 MB) until the launching app itself exited; over a long day of repeated launches these accumulated. The server now records its parent at the earliest possible moment, and the npm and standalone launchers pass the real host's process id down to it so it can watch the host directly instead of only the launcher that may already be gone. As a final backstop, a server that never receives a single request after starting now shuts itself down instead of waiting for the host to exit — tunable with
CODEGRAPH_STARTUP_HANDSHAKE_TIMEOUT_MS(0 disables). Thanks @ruslan33321 for the report. (#1185) - The automatic context hook for Claude Code now fires for structural questions asked in nearly thirty languages — French, Spanish, Portuguese, German, Italian, Dutch, Polish, Czech, Romanian, Hungarian, Greek, Swedish, Danish, Norwegian, Finnish, Russian, Ukrainian, Turkish, Indonesian, Vietnamese, Thai, Hindi, Arabic, Farsi, Hebrew, Japanese, Korean, and both simplified and traditional Chinese — instead of just English and simplified Chinese. Previously a natural question like "comment marche la state machine des commandes ?" injected nothing unless it happened to contain a code-shaped symbol name, making the hook look broken for non-English teams. English questions phrased with derived word forms ("explain the architecture…", "what are the dependencies…") now fire too, and prompts in any other language still fire when they name a symbol from the index. Thanks @anthonyle-roy-lgtm for the report. (#1126)
- Lua and Luau method calls with capitalized names (
obj:Method()— the standard Roblox convention) now link to the right method. Because Lua's method-call syntax looks identical to a Luau type annotation, a capitalized call likelg:Log()was misread as declaring the variable's type, so whenever two or more classes shared a method name (Init,Update,Destroy, …) the call was silently dropped from callers, impact/blast-radius, and flow traces. Lowercase method names were unaffected. Thanks @inth3shadows for the precise root-cause analysis and repro. (#1124) - Removed dead code left behind by the discontinued managed-reasoning feature. Its
codegraph loginflow was unplugged before ever shipping in a release, but the unused module still shipped inside the platform bundles, and a security review flagged its Windows browser-open step (it routed the login URL throughcmd, which would have been unsafe had the flow ever been wired back up). The leftover module and its tests are now fully deleted. Thanks @inth3shadows for the report. (#1114) - The Claude Code context hook no longer treats ordinary English words that merely start with "call", "trace", "affect", or "connect" — callus, calligraphy, Connecticut, connective, affectionate, Tracey — as structural questions, which used to inject full CodeGraph context into prompts that had nothing to do with code structure. Genuinely structural forms (calls, callers, callbacks, call site, traced, tracing, affected, connections, connectivity, …) still fire exactly as before. Thanks @inth3shadows for the report. (#1138)
- A stuck git command can no longer hang CodeGraph indefinitely. The git checks behind worktree detection and git-hook setup, and the installer's optional
npm install -gstep, now time out and fail gracefully instead of blocking forever — this matters most for the background MCP server, where an unbounded git hang (network filesystems, a wedged fsmonitor) could previously freeze it long enough for the safety watchdog to kill it. Thanks @inth3shadows for the report. (#1139) - The context hook's new plain-words matching works immediately on projects indexed by an older CodeGraph version. The word lookup it relies on is built at index time, so a project indexed before the upgrade had an empty one, and the hook would silently find nothing until something else happened to refresh the index; the hook now fills it in on first use (a one-time step — normally the background MCP server's startup catch-up gets there first). Thanks @inth3shadows for the report. (#1142)
- Several accuracy fixes to the plain-words matching: a renamed symbol (for example a NestJS route after its module prefix is applied) stays findable under its new name (#1141); a word that only appears in your code as an import statement's package name is no longer presented as a matched symbol (#1144); plural words no longer generate garbled lookup keys ("services" no longer also looks up "servic") (#1145); and a name matching both the singular and plural of one word can no longer squeeze out a genuine two-word match (#1146). Thanks @inth3shadows for the reports.
- Heavily-reflected Unreal Engine C++ classes are no longer dropped from the index. Reflection markup that decorates members —
UPROPERTY(...),UFUNCTION(...),UCLASS(...),GENERATED_BODY(),UE_DEPRECATED_*(...),DECLARE_DELEGATE_*(...)— are no-semicolon macro calls that tree-sitter doesn't recognize, so each drops into error recovery; in a big class the errors pile up until the wholeclass_specifiercollapses and the class, its base clause, and its members vanish (UCharacterMovementComponent, with ~240 such macros, disappeared entirely, breaking every subclass/type-hierarchy and blast-radius query that went through it). These line-leading annotation macros are now blanked (offset-preserving) before parsing so the class survives. Thanks @luoyxy for the report and root-cause analysis. (#1093 follow-up) - Unreal Engine members and methods prefixed by an export/visibility macro are no longer lost. The
*_APImacro doesn't only sit on the class header — it prefixes almost every exported member of a large UE class (ENGINE_API virtual void Tick(...),static ENGINE_API void AddReferencedObjects(...)); the parser read the macro as an extra type token and each such declaration fell into error recovery, so on headers likeActor.handWorld.hhundreds of return types piled up as orphan errors and could still tip the class into collapse. Member/method-level*_API/*_EXPORT/*_ABImacros (Unreal, Qt/Boost, LLVM) are now blanked before parsing, mirroring the existing class-header recovery. (#1093 follow-up) - Unreal Engine annotation macros that appear mid-line — an enum value's
UMETA(DisplayName=...), a parameter'sUPARAM(ref), or a deprecation tag wedged into ausingalias (using FOnNetTick UE_DEPRECATED(5.5, "...") = ...;, which alone collapsedUWorldinWorld.h) — are now stripped too. These sit in positions the line-leading recovery structurally can't reach, and a single one could take down the surrounding enum or class. They are matched by an Unreal-only name list (UMETA,UPARAM,UE_DEPRECATED*) so no standard-C++ or other-library code is affected. Together these three fixes recover the main class of every large Unreal Engine header tested (Actor,ActorComponent,SkeletalMeshComponent,World,LightComponent,CharacterMovementComponent). (#1093 follow-up) - A C++ header whose only C++ signal is an export-macro-annotated class is no longer misdetected as C — which had silently dropped the class. A
.hfile defaults to C and is only reclassified as C++ when it shows a C++-specific construct, but that check couldn't see through an export/visibility macro:class ENGINE_API UFoo : public UObjectdidn't match the macro-blindclass Name :pattern, so a lean Unreal-Engine-style header carrying justGENERATED_BODY()and no explicitpublic:/virtual/namespace/templatewas parsed as C. The C extractor emits no class nodes, so the class — and its inheritance link — vanished from the graph, quietly undoing the macro-class recovery added in #1061. The C++ detection heuristic now recognizes an export-macro-annotatedclass/structdeclaration (the same shape #1061 blanks before parsing), matching howclass Foo : Barwas already detected; the two-token<keyword> <MACRO> <Name>before a[:{]never occurs in valid C, so genuine C headers are unaffected. Thanks @luoyxy for the report and root-cause analysis. (#1133)
v1.2.0
2026年07月02日
[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, andcodegraph_exploreflow 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.lognow links toLogger#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(), Rlg <- Logger$new(); lg$log(), or Pascalvar 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 toCODEGRAPH_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 loginwas 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'sclass Emptyand 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() constinstead ofGetActiveTags, and a conversion operator likeoperator EALSMovementState() constkept its trailing() constinstead of readingoperator 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(...); theFORCEINLINEmacro made the parser read the return type as part of the function's name (FString GetEnumerationToStringinstead ofGetEnumerationToString) 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 genericALWAYS_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 asCreateThingreturningHRESULT). 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
Loggerclass with its ownlog()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 asobj.log(),Logger.log(), andLogger::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 animportalready pins to another file are unaffected. Thanks @inth3shadows for the minimal repro and root-cause analysis. (#1079)
v1.1.6
2026年06月30日
[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/versionsfrom earlier upgrades is safe to delete. Thanks @lalanbv for the report. (#1074) codegraph indexcan 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 indexis 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
2026年06月30日
[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 UActorComponentstyle used throughout Unreal Engine — where anXXX_APImacro sits betweenclass/structand the type name — as well as the equivalent*_EXPORT/*_ABImacros 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_explorenow 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 itsWith…builders living in a separateoptions.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 toolscodegraph_search/codegraph_impact/codegraph_noderemain available viaCODEGRAPH_MCP_TOOLSfor anyone who prefers driving each step explicitly.) Thanks @wauxhall for the detailed investigation. (#1064)
v1.1.4
2026年06月30日
[1.1.4] - 2026-06-29
Fixes
- CodeGraph again respects
.gitignorefor nested repositories that git tracks as gitlinks. The recent change that taught CodeGraph to descend into nested repos recorded as160000"commit" pointers (#1031, #1033) did so even when your.gitignoreexcludes 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 gitignoredbenchmark/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 withcodegraph.jsonincludeIgnored. Nested repos in non-ignored locations — the case #1031/#1033 fixed — are unchanged. Thanks @AriaShishegaran for the detailed report. (#1065)