Skip to content
New · v0.9.35 is out
Changelog

What's new

Every release, straight from GitHub, newest first.

  1. v0.9.35Aug 6, 2026

    v0.9.35

    Correctness release: revives the merge shrink guard, fixes prune/eviction on absolute paths and newly-ignored files, stops a Java external-annotation conflation, and makes callflow and query direction/relation aware.

    • Fix: the build_merge #479 shrink guard is no longer effectively dead (#2497, thanks @sortakool). It read the post-replace node count, so a broken partial re-extract could silently destroy nodes without tripping the guard, and the guard was skipped entirely under prune_sources. The guard now diffs the on-disk baseline by node identity and refuses any loss from a source that was neither re-extracted nor pruned this run (active even under prune_sources, skipped only under dedup), and reports how many nodes a re-extract replaced.
    • Fix: build_merge/merge_raw_extraction prune_sources now prunes correctly when given absolute paths under a non-standard layout, deriving the scan root by suffix-matching stored source paths, and warns (instead of reporting "already clean") when a prune matches nothing (#2446, thanks @AI-invest).
    • Fix: graphify update now removes newly-ignored files from an existing graph (#2495, thanks @alisson-acioli). A file added to .graphifyignore/--exclude (or a skip rule) is evicted even though it still exists on disk; .gitignore-driven eviction applies on an explicit full update. Files that merely changed are still preserved, and a file that leaves the corpus without matching any live ignore rule stays (fail-closed, #1795).
    • Fix: a Java local class and a same-named external annotation (e.g. a local class Component and Spring's @Component) no longer collapse into one node (#2504, thanks @te7ina-honey). The Java type resolver now runs before the unique-label stub rewire and parks an imported-but-external type on its fully-qualified name, and cross-file import resolution checks the package. In-corpus annotation resolution is unchanged.
    • Fix: graphify callflow now respects edge direction, so the caller/callee columns are correct (#2508, thanks @Tomaskobel). The call-flow HTML loads the graph directed and recovers direction from the stored _src/_tgt markers (consistent with the path fix), and indirect calls are counted.
    • Fix: relational-intent verbs in a query ("calls", "uses", "extends", ...) no longer seat spurious seeds (#2507, thanks @filipechagas). Such a verb is excluded from the per-term seed guarantee, so a decoy matching only the verb no longer becomes a traversal root, while a verb that is a genuine symbol name can still be seeded on merit.
  2. v0.9.34Aug 5, 2026

    v0.9.34

    Correctness release: a C# receiver-typing regression fix, direction-respecting shortest paths, and a set of hyperedge merge/load integrity fixes.

    • Fix: C# receiver typing no longer drops a true call when a same-named variable is declared untypeably elsewhere in the method (#2472, thanks @JensD-git). Receiver types are now tracked per lexical declaration scope and resolved by the call's position, so a typed static local-function parameter keeps resolving even when an out var reuses the name in the enclosing body. This fixes a regression from 0.9.32 (#2346). Cross-method independence (#2299) and field-conflict poisoning are unchanged; an out var receiver itself remains untyped.
    • Fix: graphify path (and the MCP shortest_path tool) now respect edge direction by default instead of running on an undirected view, so a returned path no longer traverses edges backwards (#2487, thanks @luliaz0601). Direction is recovered from the stored _src/_tgt markers. Pass --undirected (CLI) or undirected=true (MCP) to search ignoring direction; when no directed path exists the command says so instead of silently returning a reversed one.
    • Fix: semantic extraction no longer aborts at merge with a TypeError when a hyperedge carries dict-shaped members (#2486, thanks @adminwat). Members are normalized to ids (or dropped with a warning) so a malformed hyperedge can no longer destroy a completed extraction.
    • Fix: graphify merge-graphs no longer drops hyperedges (#2484, thanks @sortakool, and @oleksii-tumanov for the approach in #1691). Hyperedge member ids and ids are now relabeled with the per-repo prefix, both inputs' hyperedges are unioned instead of one clobbering the other, and they are written to both the top-level and nested slots.
    • Fix: build_from_json now reads hyperedges from both the top-level and nested graph slots, so label and re-cluster runs no longer silently empty a graph's hyperedge set (#2485, thanks @sortakool); a full validation wipeout is now reported loudly.
    • Fix: the skill flow now passes the curated community labels to to_json, so graph.json ships with community_name on nodes instead of dropping it (#2490, thanks @PapiScholz).
  3. v0.9.33Aug 5, 2026

    v0.9.33

    Data-integrity release: fixes a C# partial-class regression from 0.9.32, stops incremental rebuilds from dropping cross-file call edges, and stops extract from silently losing a file when a worker crashes.

    • Fix: the C# partial class merge (#2332) no longer conflates two same-named classes that live in different assemblies (#2411, thanks @JensD-git). The merge now keys on assembly (nearest ancestor directory containing a .csproj/.fsproj/.vbproj) in addition to namespace and name, so genuine partial halves within one project still merge while same-name types in separate projects stay distinct. A corpus with no project file keeps merging by namespace and name as before.
    • Fix: graphify update no longer drops member-call and indirect_call edges from a changed file into an unchanged target (#2437, #2438, thanks @aryanbonigala). Incremental re-resolution now sees the unchanged corpus (its nodes, contains/method edges, and the _callable markers, which now persist to graph.json like _origin), so cross-file calls survive an incremental rebuild while edges to a genuinely removed target are still evicted.
    • Fix: graphify extract no longer silently substitutes an empty result when a worker crashes (#2444, #2445, thanks @Baziar). A BrokenProcessPool now triggers the sequential fallback instead of being swallowed per future, a failed worker file is retried sequentially rather than merged as empty, and a whole-pass AST failure on a fresh build exits non-zero instead of writing a zero-node graph (use --allow-partial to opt into a best-effort partial graph).
    • graphify install now prints a one-time pointer to the hosted platform (early access is open free before the public v1 launch) after the setup summary.
  4. v0.9.32Aug 1, 2026

    v0.9.32

    Correctness release: a tier-aware merge that stops incremental/rebuild from dropping a file's other layer, plus a batch of language-resolution and CLI fixes.

    • Fix: incremental extraction and _rebuild_code no longer drop a file's other tier (#2333, #2334, #2336). Merge is now tier-aware (an AST re-extract replaces only AST nodes and keeps the semantic layer, and vice versa), the _origin provenance marker is backfilled on load so old graphs self-heal, and the full-rebuild drop is scoped to sources actually regenerated.
    • Fix: graphify update preserves the graph's directed flag instead of rebuilding it undirected (#2342, thanks @Rishet11).
    • Fix: a numeric or otherwise non-string node id from an LLM fragment no longer aborts the build with a TypeError (#2326, thanks @Rishet11).
    • Fix: graphify query renders every edge between visited nodes, not just the traversal-tree edges (#2323, thanks @Rishet11).
    • Fix: graphify update writes manifest.json to the target's graphify-out instead of the current working directory (#2316, thanks @Rishet11).
    • Fix: a real Python package named coverage/ is no longer silently dropped; the prune is gated on coverage-report artefacts (#2339, thanks @Manoj21k).
    • Fix: a custom GRAPHIFY_OUT name no longer prunes every same-named directory in the tree (#2273, thanks @oleksii-tumanov).
    • Fix: C# member calls resolve for receivers declared inline via out var, is, case, and switch-arm patterns (#2346, thanks @JensD-git), and members of a partial class split across files now attach to one merged class node (#2332).
    • Fix: members of a Kotlin anonymous object (object : Foo { ... }) are now extracted, with their implements and calls edges (#2347).
    • Fix: Ruby mixins declared with compact/nested syntax now resolve, and a qualified external mixin can no longer fabricate a phantom hub (#2302, thanks @FolatheDuckofDuckingburg). module Foo::Bar and module Foo; module Bar canonicalize to the same label; extend ActiveSupport::Concern no longer binds to a local module named Concern; a genuine in-corpus include Foo::Concern still resolves.
    • Perf: dedup drops an O(nodes x components) scan in remap construction (#2328, thanks @stupidprogrammer4), with identical results.
  5. v0.9.31Jul 30, 2026

    v0.9.31

    Resolution-accuracy fixes, an MCP SDK compatibility widening, and community extractor fixes.

    MCP

    • The MCP server is now dual-compatible with the mcp SDK 1.x and 2.x, lifting the mcp<2 cap from 0.9.30 to mcp>=1,<3 (#2308, thanks @NiSHoW). _build_server binds the same handlers via the 1.x decorator API or the 2.x on_* constructor callbacks at runtime, and adapts Tool.inputSchema, Resource.uri, and the dropped AnyUrl re-export. Verified with full stdio handshakes under mcp 1.29 and 2.0.

    Resolution / graph accuracy

    • C# member calls on a typed receiver no longer drop true calls edges when the same local name is reused across methods (#2299, thanks @JensD-git). Receiver typing is now per-method (mirroring the Java resolver) instead of per-file, so an untypable var x = ... in one method can't delete a typed-parameter call edge in another.
    • SQL cross-file table references (e.g. a prisma migration referencing a table created in an earlier one) resolve to the real table node instead of leaking an absolute-path id and losing the foreign key (#2324). References mint a sourceless stub that collapses onto the real definition, and identifiers are normalized so "public"."users" matches public.users.
    • graphify path and explain no longer print reversed hops (#2309): they recover edge direction from the stored _src/_tgt markers instead of the persisted endpoint order.
    • export const X = <scalar> now emits a graph node, so a named import of a scalar export is no longer left dangling (#2266, thanks @oleksii-tumanov).
    • Go predeclared functions (make, len, append, ...) no longer fabricate call edges to same-named user symbols (#2313, thanks @PathGao); the filter is scoped to Go bare-identifier callees.
    • graphify explain refuses and lists candidates when a name matches symbols in more than one file, instead of silently resolving to an arbitrary one (#2233, thanks @0bLoM).
    Full notes ↗
  6. v0.9.30Jul 29, 2026

    v0.9.30

    Fixes a fresh-install failure of the MCP server, plus node-id portability, cache, bedrock, and merge-graphs fixes.

    Install

    • Pin mcp below 2.0 so a fresh graphifyy[mcp] / graphifyy[all] install works again (#2277, #2279, #2291). mcp 2.0.0 dropped the mcp.types.AnyUrl re-export and the Server decorator-registration API that graphify/serve.py uses, so an unpinned resolve broke graphify-mcp on every new install with an ImportError. The mcp and all extras now require mcp>=1,<2 (resolving to 1.29.0) and starlette>=1.3.1,<2. Porting to the mcp 2.x API is tracked in #2308.

    Node-id portability

    • TypeScript .tsx files no longer leak absolute-path / machine-slug ids into edge endpoints (#2262). The symbol-resolution pass parsed .tsx with the plain TypeScript grammar; JSX misparsed, nested handlers floated to top level, and calls edges were emitted from an absolute-stem source with no node. .tsx now uses the TSX grammar, a calls edge is never emitted from an unowned source, and a general backstop canonicalizes any node-less absolute-derived endpoint.
    • A warm AST-cache hit after a corpus move or clone no longer replays node ids minted under the original root (#2257, thanks @Kaushik2003). Cached ids are stored root-relative and re-anchored on read.

    Backends / graph ops

    • The Bedrock backend reads the first text block of a Converse response instead of block 0, so reasoning-capable models no longer parse to zero nodes (#2287, thanks @zhiyanliu).
    Full notes ↗
  7. v0.9.29Jul 28, 2026

    v0.9.29

    Portability, hook-safety, and resolution-accuracy fixes.

    Node-id portability

    • Absolute-path / machine-slug node ids no longer leak into edge endpoints (#2231, #2243). Module-top-level indirect_call sources, bash source/script-invocation targets, and other producers that minted an id from an absolute path are now canonicalized to the root-relative node id by a general backstop, so graph.json link endpoints are portable across machines and clones.

    Hook safety

    • The post-commit hook no longer overwrites an existing graph.json it merely failed to read (#2251). If the existing graph is over the size cap or unparseable, the rebuild refuses to write (matching the CLI) instead of replacing it with a code-only extraction; the --no-cluster write is now atomic with a protected-graph backup.
    • The post-commit hook launcher no longer pops a focus-stealing console window on Windows (#2253, thanks @hopstreax).

    Resolution / extraction

    • False indirect_call edges from JS/TS closure arguments are gone (#2241, thanks @Yyunozor): a closure parameter now shadows outer names, so rows.map(r => ...) no longer binds r to a corpus-wide callable of the same name.
    Full notes ↗
  8. v0.9.28Jul 27, 2026

    v0.9.28

    Fixes for incremental extraction correctness, graph loading, uninstall scoping, macOS paths, and Swift extraction.

    Incremental extraction

    • Incremental runs no longer drop cross-file edges whose target file wasn't in the batch (#2211, #2213). Python relative imports and markdown reference links emitted absolute-path target ids without the stamp the incremental canonicalization needs, so a re-extracted file's imports/references dangled or vanished. Both now canonicalize to the root-relative node.
    • Incremental extraction no longer prunes alive files as "deleted" (#2210). The stale-source check compared paths with a raw string test (no Unicode NFC) and pruned non-matches without a liveness check, so macOS NFD paths and legacy basename spellings lost their nodes. It now compares NFC on both sides and is fail-closed.
    • --update on macOS no longer re-extracts everything when the corpus path or a filename contains non-ASCII characters (#2221, thanks @SyedFahad7). Manifest keys are NFC-normalized.
    • Incremental rebuilds no longer reuse stale community labels, and a graph that outgrows the visualization cap now keeps an aggregated view instead of deleting graph.html (#2218, thanks @bobspryn).

    Other fixes

    • graphify benchmark, the graph merge-driver, and the call-flow HTML export no longer crash or silently fail on a --no-cluster graph.json (#2212), which stores edges under edges rather than links.
    • claude/gemini/codebuddy uninstall no longer delete the user-global skill when called with a project_dir (#2215); this also fixes graphify uninstall --project deleting the global codebuddy skill.
    • Swift computed and observed properties (var body: some View { ... }, get/set, willSet/didSet) now emit graph nodes, so SwiftUI views are no longer erased (#2181, thanks @ozdemirsarman).
  9. v0.9.27Jul 26, 2026

    v0.9.27

    A large maintenance release: install-safety fixes, node-identity/canonicalization fixes, cross-file resolution improvements, and a batch of community contributions.

    Install and data safety

    • claude/gemini/codex/codebuddy install no longer overwrite a settings/hooks file they cannot parse (#2167). On any JSON parse error they used to fall back to an empty config and rewrite the whole file, destroying the user's settings (most often triggered by a UTF-8 BOM). They now read utf-8-sig, refuse to modify a non-JSON-object file, and back up to <name>.graphify-bak before any write.
    • Incremental extract --no-cluster no longer overwrites the full graph with just the changed files (#2169). It now merges the existing graph forward with the same replace/prune semantics as the clustered path and canonicalizes cross-file edge targets.
    • Running the test suite no longer touches the developer's real ~/.claude/~/.gemini/~/.codebuddy/~/.copilot (#2168).

    Node identity and caching

    • stat-index.json is stored with root-relative keys (re-anchored on load, mirroring manifest.json) and pruned of deleted-file entries, so a moved or cloned corpus keeps its cache hits instead of re-extracting everything (#2199).
    • JavaScript/TypeScript regex-rescued imports (Svelte/Astro/Vue) no longer create ghost target nodes with absolute-path ids (#2195).
    • Cross-file concept nodes with identical normalized labels now merge, matching the behavior already applied to near-identical labels (#2182).
    • Absolute source_file paths (for example from a Windows scan) no longer break node identity (#2197), and build_from_json folds legacy field aliases (name/path/type/confidence_score) so alias-carrying nodes stop entering the graph invisible and unmergeable (#2194).
    Full notes ↗
  10. v0.9.26Jul 24, 2026

    v0.9.26

    Maintenance release. Correctness fixes across Python call-graph inference, the git hook (Windows), and bash source resolution.

    Fixes

    • graphify query/explain no longer fabricate indirect_call edges to class definitions (#2137, thanks @Rishet11). Passing a class as a value (select(Model), db.get(Model, id), except (ErrorA, ErrorB), getattr(obj, "Name", 0)) produced a false inferred call edge; classes are now excluded from indirect_call in both the intra-file and cross-file paths, while direct instantiation still emits its calls edge.
    • The post-commit hook's interpreter allowlist now accepts Windows backslash paths (#2126, thanks @Rishet11). The shell case glob silently emptied any interpreter path containing a backslash, so the hook failed on Windows uv/venv installs. Both allowlist sites use a verified character class that admits backslashes while still rejecting shell metacharacters.
    • The hook rebuild timeout is now armed on Windows (#2148, thanks @Rishet11). It relied on signal.SIGALRM, which does not exist on Windows, so GRAPHIFY_REBUILD_TIMEOUT was a silent no-op and a hung rebuild ran unbounded. A threading.Timer fallback now terminates a runaway rebuild where SIGALRM is unavailable; the Unix path is unchanged.
    • Bash calls into functions defined in a sourced file now get calls edges (#2141, thanks @HerenderKumar). Resolution was gated on same-file definitions, so a call to a sourced-library function looked like an external command and produced no edge. Both source file and . file are handled; resolution is in-corpus and single-match only, so a genuine external command still fabricates nothing.
    • Bash source edges built from a variable path now resolve (#2079, thanks @HerenderKumar). source "${BENCH_DIR}/lib/x.sh" baked the unexpanded ${VAR} into a dead node id; the leading expansion is stripped and the literal suffix resolved against the script's directory, emitted as INFERRED only when it resolves to a real file. Calls into a ${VAR}-sourced library resolve too.
    • Ignore files saved with a UTF-8 BOM are now honored (#2163). .gitignore/.graphifyignore/info/exclude were read as utf-8, so a leading BOM stayed on the first line and silently dropped the first pattern. The ignore read sites now use utf-8-sig, matching git.
  11. v0.9.25Jul 22, 2026

    v0.9.25

    Maintenance release: a license change to Apache 2.0 and a dead-code removal.

    License

    • graphify is now licensed under the Apache License, Version 2.0 (previously MIT). Apache 2.0 adds an explicit patent grant, a patent-retaliation clause, and explicit inbound-contribution terms. Contributions made before the relicensing were submitted under MIT and remain available under those terms; the original MIT text is retained in LICENSE-MIT and referenced from NOTICE.

    Removed

    • .graphifyinclude handling is gone (#2112). The file had been non-functional since dot directories became indexed by default (#873): its loader and matchers had no consumers, so detect parsed the file on every run and then discarded the result, making a .graphifyinclude a silent no-op. The dead loader and matchers are deleted, a leftover .graphifyinclude no longer appears in the unclassified list, and detect prints a one-time note when one is present at the scan root. To re-include ignored paths, use ! negation patterns in .graphifyignore.
  12. v0.9.24Jul 22, 2026

    v0.9.24

    Maintenance release. Correctness fixes across extraction, dedup, query rendering, and the sensitive-file filter, plus a hang fix in the .NET/XAML path.

    Fixes

    • The XAML code-behind .cs scan is now bounded and prunes noise directories, so it can no longer hang. A standalone extraction on a .xaml under a large or shared parent (a temp dir, a big monorepo) could resolve the project root to a broad ancestor and recursively scan the whole tree. It now walks with node_modules/.venv/.git/dot-dir pruning and a directory cap: a real project scans fully, a runaway root degrades to a fast partial scan.
    • The sensitive-file filter no longer silently drops topic docs and real source (#2106). Prose files whose slug merely ends in a keyword (privacy-tokens.md) and real source like service_account.py were dropped with no trace, while some genuine secrets (.npmrc, .pypirc, .git-credentials, case variants) were missed. The filter is now stricter on real secrets and no longer loses legitimate files, and both graphify extract and the skill flow now name the skipped files instead of only a count.
    • calls edges now resolve through an aliased Python import (#2082, thanks @Yyunozor). from pkg import mod as alias recorded the import but dropped every downstream alias.func() call, so the callee looked like dead code.
    • dedup preserves a node's attributes when two exact-ID records from the same source file collapse (#2091, thanks @Synvoya). Non-conflicting attributes are retained deterministically, records from different files stay isolated, and a dropped record can never stamp a false origin onto the survivor.
    • The claude-cli backend now reads the CLI's structured-output channel instead of free-form prose (#2076, thanks @Yyunozor), which had parsed to zero nodes and bisected forever on newer Claude Code.
    • graphify explain on a high-degree node groups the cut connections by file instead of a bare ... and N more (#2009, thanks @Yyunozor).
    • graphify query and MCP query_graph no longer print calls edges backwards (#2080, thanks @Yyunozor); the renderer recovers the stored direction from the edge.

    Features

    Full notes ↗

Full release history: github.com/Graphify-Labs/graphify/releases ↗

We use privacy-friendly analytics to improve Graphify. Cookies only load if you accept. Privacy policy