github colbymchenry/codegraph v1.1.2

5 hours ago

[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 large list of ids — it issued one unbounded query, so a list longer than SQLite's parameter limit aborted the call. It now splits the work into batches like every other bulk query in the API. CodeGraph's own indexing and reference resolution never called this method (they use a different, already-batched path), so the CLI and MCP server were unaffected. Thanks @inth3shadows for the static analysis. (#1001)
  • Swift computed properties are now indexed, so you can search for them. A computed property — a var isCloudProxy: Bool { … } read all over a codebase, a SwiftUI view's var body: some View { … }, a protocol's var title: String { get } requirement — produced no symbol at all, so codegraph query and codegraph_explore answered "No results found" for it, and an agent that trusts an empty result would wrongly conclude the property doesn't exist. Computed properties (and protocol property requirements) are now graph symbols you can find and explore like anything else. A computed property's getter is also read as its body, so a SwiftUI view's body links to the subviews and helpers it builds — making a view's render flow traceable through the property. Stored properties were already indexed; this closes the computed-property gap. Thanks @monochrome3694 for the precise report and repro. (#1020)

Don't miss a new codegraph release

NewReleases is sending notifications on new releases.