Skip to content

Releases: colbymchenry/codegraph

v1.1.4

29 Jun 21:58

Choose a tag to compare

[1.1.4] - 2026-06-29

Fixes

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

v1.1.3

29 Jun 04:04

Choose a tag to compare

[1.1.3] - 2026-06-29

Fixes

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

v1.1.2

28 Jun 06:34

Choose a tag to compare

[1.1.2] - 2026-06-28

New Features

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

Fixes

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

v1.1.1

24 Jun 22:20

Choose a tag to compare

[1.1.1] - 2026-06-24

Fixes

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

v1.1.0

23 Jun 21:46

Choose a tag to compare

[1.1.0] - 2026-06-23

New Features

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

v1.0.1

13 Jun 21:10

Choose a tag to compare

[1.0.1] - 2026-06-13

New Features

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

Fixes

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

v1.0.0

12 Jun 18:23

Choose a tag to compare

[1.0.0] - 2026-06-12

Security

  • Closed a path-traversal hole where a symbolic link inside an indexed project that pointed outside the project root could make CodeGraph serve that out-of-root file's contents (for example a file under your home directory) to the AI agent. CodeGraph now resolves symlinks when validating file access and refuses to read anything whose real location is outside the project, while still allowing symlinks that stay within it. Thanks @sulthonzh. (#527)
  • CodeGraph now indexes Spring configuration files (application.properties / application.yml) by key only, and never includes their values in codegraph_explore or codegraph_node output. Previously a secret committed to one of these files — a database password, API key, or connection string with embedded credentials — could be surfaced to an AI agent that asked about nearby code, even though the agent never opened the file. The configuration keys are still indexed, so reference and impact analysis are unaffected; an agent that genuinely needs a value reads the file itself. Shopify Liquid {% schema %} blocks are likewise indexed by name only. (#383)

New Features

  • CodeGraph now indexes R (.R / .r) — functions in every assignment form (name <- function(...), name = function(...), nested definitions), S4 / Reference / R6 classes with their methods, setGeneric/setMethod generics, top-level variables and constants, library() / require() imports, source() file references, and call edges — including calls inside tidyverse pipe chains. Statistical and research codebases get the full explore / impact / callers surface. (#828) (R)

  • Workspaces holding multiple git repositories now index as a whole. Running codegraph init at the root of a directory that contains several independent git repos — including the common "super-repo" layout where the parent repo's .gitignore hides the child repos to keep git status quiet — now indexes every nested project into one graph, with each child repo's own .gitignore respected. codegraph sync and live file watching pick up changes inside the nested repos too (previously change detection only consulted the parent repo, so edits in child repos were invisible until a full re-index). Git repositories inside node_modules (npm git-dependencies) remain excluded. (#514)

  • codegraph_explore now explains where a flow ends instead of going silent. When the symbols you ask about don't connect statically — because the code dispatches through a runtime mechanism like a computed call (handlers[action.type](...)), Python's getattr, a command/mediator bus (sender.Send(new DeleteCommand(...))), reflection, or new Proxy — explore now announces the exact dispatch site (file and line) where the static path stops, and when the dispatch key is visible in the source it shortlists the likely runtime targets (for example pointing a MediatR command straight at its Handler.Handle method). Detection is deterministic and runs only when a flow fails to connect; fully connected flows are unchanged, and nothing about indexing or the graph itself changes. Relatedly, a custom event bus whose emit and handler connect through a single synthesized hop now shows that hop explicitly (with the registration site) — it previously rendered nothing because the connection was "too short" for the flow section. (#687)

  • Anonymous usage telemetry, documented field-by-field and easy to turn off. CodeGraph now collects a small set of anonymous usage statistics — which commands and MCP tools get used, which languages get indexed, which agents connect — so language and agent support work goes where real usage is. Never any code, file paths, file or symbol names, search queries, or IP addresses; usage aggregates locally into daily totals before anything is sent, and the ingest endpoint is public, auditable code in the repository that enforces the documented field list. The installer asks up front with a visible default-on toggle (and never re-asks); everywhere else a one-line notice prints before the first send. Disable any time with codegraph telemetry off, CODEGRAPH_TELEMETRY=0, or the cross-tool DO_NOT_TRACK=1 standard — off means off: nothing is recorded, nothing is sent, and buffered data is deleted. TELEMETRY.md documents every field.

  • Subagents and non-MCP agents can now reach CodeGraph. Two new CLI commands — codegraph explore "<symbols or question>" and codegraph node <symbol-or-file> — print exactly what the matching MCP tools return (relevant symbols' source + call paths; one symbol's source + callers; file reads with line numbers), so any agent with a shell can use the graph. And codegraph install now writes a small marker-fenced CodeGraph section into each agent's instructions file (CLAUDE.md / AGENTS.md / GEMINI.md) pointing at both surfaces — that file is what Task-tool subagents actually see, where the MCP server's own guidance only reaches the main agent. Measured on a delegated code-exploration task: subagents went from almost never using CodeGraph (~1 in 9 runs) to using it in every run, including runs with zero grep/file-reading fallback. The section is small, survives your own content, upgrades cleanly from the old long block, and codegraph uninstall removes it. Thanks @liuyao37511. (#704)

  • The MCP tool list is now a focused default of fourcodegraph_explore, codegraph_node, codegraph_search, and codegraph_callers. The other four (codegraph_callees, codegraph_impact, codegraph_files, codegraph_status) remain fully functional — the CLI and library API are unchanged, and CODEGRAPH_MCP_TOOLS re-enables any of them — but they're no longer listed to agents by default: measured agent behavior shows they're never or rarely picked, and the information they carry already arrives inline on the tools agents do use (explore's blast-radius section, node's dependents note, a symbol's own body as its callee list). A leaner list saves context tokens every session and steers agents to the right tool by presence alone.

  • CodeGraph now goes quiet instead of failing loudly in unindexed projects. When an AI agent's session starts in a workspace that has no CodeGraph index, the MCP server now announces itself as inactive with a short note and lists no tools at all — instead of presenting the full toolset and erroring on every call, which taught agents to distrust CodeGraph even where it works. Querying another project that isn't indexed likewise returns clear guidance (use your regular tools for that codebase; the user can run codegraph init there to enable CodeGraph) instead of an error, and genuine internal errors now tell the agent to retry once rather than give up on CodeGraph entirely. Indexing stays your decision — agents are told not to run it themselves. (#769)

  • Astro projects are now indexed. .astro files previously weren't parsed at all — on a typical Astro site that left most of the codebase invisible to search, impact, and codegraph_explore. CodeGraph now extracts the TypeScript frontmatter (functions, imports, getStaticPaths, …) and client-side <script> blocks, captures function calls and <Component> usages in template markup so cross-component dependencies trace end-to-end, resolves the Astro global and astro:* module imports as framework-provided, and maps src/pages/ file-based routing to route nodes (.astro pages and .ts endpoints, including [param] and [...rest] dynamic segments, with underscore-prefixed files correctly excluded). Validated on two real-world Astro sites with 93% measured cross-file coverage and every page mapping to its route. Thanks @xingwangzhe. (#768) (Astro)

  • Same-named symbols across a monorepo's apps are no longer conflated. In a NestJS-style workspace with one UserService per app, codegraph_callers, codegraph_callees, and codegraph_impact now report one section per distinct definition — each app's callers and blast radius under its own file-labeled heading — instead of a single merged list, and accept a file argument to focus exactly the definition you mean (like codegraph_node already did). Impact in particular no longer overstates a change's blast radius by merging unrelated same-named classes. Thanks @Igorgro. (#764)

  • Fixed a related source of cross-package wrong edges: PascalCase type references from plain .ts files were being resolved as React components, which could link a file's own type alias to an arbitrary same-named class in another package (on one large monorepo this produced over a thousand wrong cross-package reference edges; 96% are now gone, and the remainder are genuine shared-model imports). Component resolution now applies only to references from JSX-capable files and never guesses between multiple candidates without a positional signal. The Svelte and Vue component resolvers had the same arbitrary-pick flaw (Vue resolved the first same-named .vue file found anywhere in the tree) and now follow the same rule: same-directory first, otherwise only an unambiguous name resolves. Re-index a project to benefit. (#764) (TypeScript, React, Svelte, Vue)

  • TypeScript and JavaScript class fields are now reported as properties instead of methods. A plain field like public fonts: Fonts; previously extracted as a method, misrepresenting class shape and letting calls to same-named functions resolve to data fields (a boolean field named isArray was soaking up Array.isArray(...) call edges). Fields holding arrow functions or function expressions (onClick = () => {…}, including wrapped ones like onScroll = throttle(() => {…})) correctly remain methods and their bodies are still analyzed. Field initializers are analyzed too, so history = createHistory() records its call — and JavaScript class fields, which previously produced no symbol at all, now appear in the graph. Re-index a project to benefit. (#808) (Typ...

Read more

v0.9.9

02 Jun 15:37

Choose a tag to compare

[0.9.9] - 2026-06-02

New Features

  • codegraph_explore is now the primary tool, and one call is usually all an agent needs: it returns the verbatim source of the symbols relevant to your question (a plain question works as the query — you no longer need exact symbol names), grouped by file and Read-equivalent, so the agent answers without falling back to read/grep. The narrower codegraph_context and codegraph_trace tools were removed in favor of it — explore already surfaces the call flow among the symbols you name (the job trace did), so there's one obvious tool to reach for instead of three.
  • codegraph_explore now includes a compact "Blast radius" for the symbols you're looking at — who depends on each (just the locations, not their source) and which test files cover it — so before editing, the agent can see what else to update and which tests to run, without a separate impact lookup. Symbols nothing depends on are skipped, so it stays short.
  • Functions defined inside a store or handler object — the actions in a Zustand create((set, get) => ({ … })) store, and the same shape in Redux, Pinia, MobX, or any exported handler/route map — are now indexed as real symbols. Previously they existed only as object properties, so looking one up by name or asking who calls it returned "not found" and the agent had to read the whole store file to follow the flow; now codegraph_node, codegraph_callers, and codegraph_explore resolve them directly — including calls made through useStore.getState().fetchUser() or a destructured const { fetchUser } = useStore.getState().
  • codegraph_explore now surfaces the right definition when a method name is overloaded across types. Asking about, say, DataRequest's task and validate used to return a same-named method from an unrelated file (or an abstract base stub) and bury the one you meant; explore now recognizes the type you named in the query and leads with that type's own overloads, in full.

Fixes

  • Search ranking no longer lets a common word in your request hijack the results: asking about, say, a "flat object" screen used to surface an unrelated constant that merely happened to be named the same, because the exact-name match outweighed everything else. Ranking now weighs how well each result is corroborated by the rest of your request, so the symbols you actually meant come first (this improves codegraph_explore's results).
  • codegraph_node now returns every definition when a name is ambiguous — an overloaded method, or the same method name on different types — instead of returning one (sometimes the wrong one) with a note listing the rest. Asking for such a symbol now hands back all of the matching definitions with their source in a single call, so the agent stops having to read the file by hand to find the specific overload it wanted (common in Swift, Go, Java, and C#). For a heavily-overloaded name (a poll/validate with dozens of definitions), pass file (and/or line) — e.g. the file:line shown in a trail — to get that exact definition's body. Large overload sets show the most relevant ones in full and list the remainder by location.
  • codegraph_explore never returns half a method anymore: when output runs up against its size budget it drops whole methods or whole files (and lists what it dropped, so you can ask for them in another call) instead of cutting off a method body partway. A truncated method was the one case that still sent the agent to read the file for the rest — so the source explore returns is now always complete and usable as-is.

v0.9.8

01 Jun 00:22

Choose a tag to compare

[0.9.8] - 2026-06-01

New Features

  • codegraph init now builds the initial index by default — you no longer need the -i/--index flag (it's still accepted, so existing commands and scripts keep working). (#483)
  • Go: Gin middleware chains now connect end-to-end in codegraph_trace and codegraph_explore — following a request reaches the middleware and route handlers registered via .Use() / .GET() instead of dead-ending where the framework dispatches the chain dynamically.
  • codegraph_explore now sizes its response to the answer instead of the file count: it shows the mechanism and the exact methods you asked about in full — even when they're buried deep in a large file — while collapsing the redundant interchangeable implementations of an interface (an HTTP interceptor chain, a query-compiler family) down to signatures. Fewer tokens for a more complete answer, so on the flows that used to occasionally cost more than plain grep/read it's now clearly cheaper — and the win holds across small, medium, and large codebases. Distinct, non-interchangeable code is shown in full as before. Disable with CODEGRAPH_ADAPTIVE_EXPLORE=0.
  • Swift deferred-validation flows (and similar "handler array" patterns) now connect end-to-end in codegraph_trace and codegraph_explore — following a request's lifecycle reaches the validators registered with .validate { … } instead of dead-ending where the framework runs them by iterating a stored list of closures. Any pattern where closures are appended to a collection and later invoked by looping over it is now traced.
  • codegraph_explore now spells out the dynamic-dispatch relationships of the symbols you ask about — e.g. "the closures registered here are run by didCompleteTask" — so the indirect hops you'd otherwise grep to reconstruct are listed alongside the call flow.
  • codegraph_explore answers multi-phase questions that span a large "god file" far more completely. For a flow like "build, send, and validate a request" — where one big file holds the build chain and the validate logic lives in others — it now keeps every method on the flow path in full, collapses the file's off-path methods to one-line signatures, and guarantees each phase's defining file is shown (instead of truncating at a fixed size and dropping whichever phase came last, which sent you to read it by hand). Incidental files that merely name-drop the flow are still trimmed, so the response stays focused on the code that answers the question.
  • CodeGraph is usable as an embedded library again: require("@colbymchenry/codegraph") and import now resolve the programmatic API — the CodeGraph class plus building blocks like DatabaseConnection, QueryBuilder, initGrammars, and FileLock — so you can drive the graph directly from your own app (for example an Electron process) instead of only through the CLI or MCP server. Embedding runs on your own runtime, so it needs Node 22.5+ for the built-in SQLite. (#354)

Fixes

  • codegraph_trace now resolves an overloaded symbol name to its real implementation instead of an empty protocol/delegate stub. Tracing a flow through a heavily-overloaded API (common in Swift, Java, C#, and Go) could land on an unrelated no-op method that happened to share the name and report "no path"; it now picks the substantive definition the flow actually runs through.
  • CodeGraph's MCP server now answers an agent's opening handshake the instant it launches instead of blocking while the index loads, so a fresh session's very first tool call no longer occasionally races a server that's still warming up and falls back to grep/read. The first question in a new session now reliably goes through CodeGraph.
  • Indexing a project that contains only config-style files (YAML, Twig, or .properties) no longer misleadingly reports "No files found to index" — these files are tracked at the file level and are now counted as indexed. Thanks @luojiyin1987 (#357).

v0.9.7

28 May 20:28

Choose a tag to compare

[0.9.7] - 2026-05-28

New Features

  • Go: gRPC interface stubs now connect to their hand-written implementation, so callers, callees, impact, and trace land on the real method instead of an empty generated stub.
  • Generated files (protobuf, gRPC stubs, mocks, build output) now rank last in search, trace, and explore, so results land on your real implementation instead of an auto-generated placeholder.
  • When codegraph_trace can't find a static path (a dynamic-dispatch break), it now inlines both endpoints' source, callers, and callees in one response, so the agent gets the full picture without a flurry of follow-up calls.
  • Trace now picks the right endpoints in large multi-module repos by preferring symbols that share a directory, instead of grabbing an arbitrary same-named symbol from an unrelated module.
  • Test files are now deprioritized in codegraph_explore (Go, Ruby, JS/TS, Java/Kotlin/Scala), so the explore budget goes to your real implementation source.
  • Small projects (under ~500 files) now resolve flow questions in fewer MCP calls, with a leaner tool surface and tuned context and explore output sized for the project.
  • codegraph_context now auto-traces flow questions like "how does X reach Y" or "trace the path from A to B", splicing the trace into the response so you don't need a separate codegraph_trace call.
  • codegraph_context now inlines a URL-to-handler routing table and the source of your main routes file for routing questions on small projects, so you don't have to go read routes.rb or web.php yourself.
  • codegraph_context search now boosts results in the directory of a project's core framework file, so a small same-named extension file no longer outranks the actual framework core.
  • Interface-to-implementation linking now works for C#, TypeScript, JavaScript, Swift, and Scala (previously Java/Kotlin only), so investigating an interface method surfaces its concrete implementations.
  • MCP tool descriptions are now shorter, trimming per-session overhead while keeping the steering guidance.
  • Java and Kotlin imports now resolve by fully-qualified name, so same-name classes in different packages are told apart correctly in multi-module Spring and Android codebases, including across the Java/Kotlin interop boundary.
  • Java and C# anonymous classes (new T() { ... }) and their overridden methods are now indexed as real class nodes, so an agent sees those hidden overrides in its trail without a Read.
  • The installer no longer writes a duplicate ## CodeGraph instructions block into your agent's instructions file (CLAUDE.md, AGENTS.md, GEMINI.md, Cursor's .cursor/rules/codegraph.mdc, or Kiro's steering doc) — the MCP server is now the single source of truth, and re-running codegraph install or codegraph uninstall strips a block a previous version left behind (#529). If you added your own notes inside the CODEGRAPH_START/CODEGRAPH_END markers, move them outside the markers first, since the whole marked block is removed.

Fixes

  • MCP tools no longer return results for files that were deleted while no server was running — the first query of a session now waits for the catch-up sync, so you get the correct index instead of stale rows.
  • Windows: black console windows no longer flash on every file save or MCP reconnect (#485, #510, #530).
  • codegraph index and init -i now report the true edge count in their summary, instead of undercounting by missing resolution and synthesizer edges.