Repository navigation
Releases: JeelGajera/OpenInvar
Release list
v0.3.0
OpenInvar 0.3.0
OpenInvar builds a deterministic symbol relationship graph for a repository and gates CI on it. No model participates in graph construction or in any gating decision — identical input produces identical output, byte for byte, because you cannot gate CI on an opinion.
This release closes the gap between what the tool claimed and what it could show.
Seven of eight languages now resolve
Java and C# were promoted from Tier 2 to Tier 1. They parse the same as before; what changed is that imports, aliases and declared types now resolve, so gates may act on them.
| Tier 1 — resolved | Tier 2 — structural |
|---|---|
| TypeScript / JavaScript, Python, Rust, Go, C / C++, Java, C# | Ruby |
Ruby is the honest caveat rather than a backlog item: autoloading, monkey-patching and method_missing leave a large share of its references undecidable statically, so it may stay Tier 2 rather than be promoted on a claim the analysis cannot support.
C# needed three rules nothing else here needed — using names a namespace rather than a type, so the ambiguity Java reaches only through wildcards is C#'s ordinary case; enclosing namespaces are in scope with no using at all; and a partial class split across files is one type with the union of its members.
Enforcement
openinvar check reads openinvar.toml and returns one of four verdicts per rule — satisfied, violated, inconclusive, skipped. Only violated fails a gate. An undecided region reports as undecided rather than as a pass.
Ten rule kinds: forbid-dependency, forbid-reference, no-field-removal, max-fan-in, max-fan-out, layers, independence, no-cycles, requires-dependency, no-orphans, requires-test, naming-convention.
openinvar audit detects changes that look made to pass a check rather than to work, with four detectors: test-tampering, contract-erosion, dead-on-arrival and assertion-removal (a test that kept its coverage but stopped checking anything). Three more are held back with their reasons recorded in the source — a detector that cannot be built honestly is named as absent rather than shipped weak.
This repository gates its own CI on its own rules.
Honest measurement
status now reports two figures, because one of them was being read as something it is not:
Resolved 99.8% (6019 of 6031 edge(s))
References bound 69.5% (6019 of 8659 reference(s))
2640 reference(s) named in source bound to nothing in the graph.
The first is the share of recorded edges that resolved. An edge exists only once something bound it, so a reference the analysis could not place leaves no trace — it never enters that denominator, and failing to bind more references makes the percentage go up. The second supplies the missing denominator.
An unbound reference is not automatically a defect: a type from a package whose source was never analysed is indistinguishable, to an adapter, from one it should have found. Read it as an upper bound on what is absent.
There is also now an evaluation against four real repositories nobody here wrote — rust-lang/log, spf13/cobra, pallets/click, google/gson — with thresholds fixed in eval/criteria.md before each run, and the runner and summariser kept in separate files so a threshold cannot move in the same edit that produces the result it judges. Determinism held 32 of 32 revisions byte-identical. Reference coverage came in at 63.2% against a 65% pass line; that is recorded as an investigate verdict with the investigation, not scored as a pass.
Also new
analyze --at <rev>— analyse the tree at a revision instead of the working tree, without disturbing the working graph.openinvar context— a minimal working set for orienting on a symbol or a change.openinvar tests <symbol> | --diff— which tests exercise a symbol, via realtestsedges rather than filename guessing.openinvar impact <file>— what depends on one file.- Two MCP tools,
graph_diffandcheck_rules. - Agent hooks for Claude Code and others, a GitHub Action, and contributor documentation.
Upgrading
The project was renamed from graphyn. The binary is openinvar, the config is openinvar.toml, the crates are openinvar-*. Commands are otherwise unchanged.
The graph store moved to .openinvar/graph.db — a SQLite file, not a directory. There is no migration, deliberately: the graph is derived data that rebuilds in about a quarter of a second, so converting a cache would be wasted work. An old store directory is reported, not deleted — a read command names it and says to run openinvar analyze, and .graphyn/db is recognised too, so an upgrade from before the rename gets the same message rather than a bare "no graph found".
Snapshot format version 5. Older snapshots are read, with fields added since recorded as absent rather than as zero — "this graph does not know" and "this graph counted none" are different answers.
One binary per platform, carrying every language. The per-language Cargo features still work — cargo install openinvar-cli --no-default-features --features python builds a Python-only binary — but the released artifact no longer omits anything the README describes.
Install
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/JeelGajera/OpenInvar/master/install.sh | bash
# Windows (PowerShell)
irm https://raw.githubusercontent.com/JeelGajera/OpenInvar/master/install.ps1 | iex
# Cargo
cargo install openinvar-cliQuick start
openinvar analyze . --snapshot HEAD # record the graph before the change
openinvar audit . --base HEAD --head worktree # what did the change actually do
openinvar check . # gate on the rules in openinvar.tomlFull detail in CHANGELOG.md, including the fixes and the limits each one left behind.
v0.2.0
Graphyn v0.2.0 — Five languages, one graph 🌐
Graphyn is no longer TypeScript-only.
v0.2.0 adds Python, Rust, Go, and C/C++ adapters behind a shared dispatch layer, so mixed-language repositories can now be indexed in a single pass — with property resolution grounded in declared types across every adapter.
graphyn analyze ./my-repoThis now indexes .ts, .py, .rs, .go, .c, and .cpp together.
🚀 Language support
| Language | Extensions | Resolves |
|---|---|---|
| TypeScript / JavaScript | .ts .tsx .js .jsx .mts .cts .mjs .cjs |
tsconfig paths, barrel re-exports, decorator DI |
| Framework files | .vue .svelte .astro |
Script blocks within the component |
| Python | .py .pyi |
Relative imports, __init__ re-export chains, star imports, TYPE_CHECKING guards, Pydantic / Django / dataclass fields |
| Rust | .rs |
Module tree, use groups and aliases, glob imports, trait impls, #[derive], macro token trees |
| Go | .go |
Package imports via go.mod, structural interface satisfaction |
| C | .c .h |
#include resolution, typedef aliases |
| C++ | .cpp .cc .cxx .hpp .hxx .hh |
using aliases, base classes, namespace-qualified names |
Every adapter attributes member access to the type a value was declared as. So payload.user_id is recorded against UserPayload regardless of what the variable is actually named.
✨ Added
- Added five new crates:
graphyn-adapter-pythongraphyn-adapter-rustgraphyn-adapter-gographyn-adapter-cgraphyn-adapter-dispatch
- The dispatch layer routes files to the correct language adapter and runs adapter groups in parallel.
- Added shared symbol-ID and AST traversal helpers to
graphyn-core, replacing five per-adapter copies. - Added parse, resolution, and skip diagnostics across adapters. Pruned directories are now reported instead of silently disappearing.
- Added a cross-language regression suite and polyglot fixtures.
- Test coverage grew from 39 to 185 tests, replacing 27
assert!(true)stubs with real coverage.
🐛 Fixed
Property resolution
- Property access was previously matched against a hardcoded variable name.
- The new adapters compared receivers against the literal string
"data", which meant property tracking failed for any other variable name in Rust, Go, and C/C++. - Receivers are now bound to declared types from parameters,
let/varbindings, annotations, and declarators. - Struct fields no longer leak from one struct into another.
Imports & symbols
#includepreviously produced a graph with zero edges because includes becamelocal_header::<name>, whichadd_relationshipdrops. Includes now resolve to the header's module symbol.- C struct names were incorrectly reported as ambiguous. A
struct Foo *pparameter is astruct_specifier, but not a new definition; we no longer mint a symbol for every reference. - Go imports previously pointed at an arbitrary package member instead of the package itself.
- Rust
usepaths now resolve through the declaring module and followpub usechains instead of matching leaf names repository-wide. - Python now indexes the relevant symbol kinds so importing a function no longer fabricates a dependency that does not exist.
- An alias equal to the symbol's own name is no longer treated as a rename, reducing noise around genuine renames.
Publishing
- The crates.io publish job now publishes all ten crates in dependency order.
- Previously, publishing could fail partway through after
graphyn-corehad already been released.
🔧 Changed
- Graph construction order is deterministic again. Dispatch groups files using a stable ordering key instead of relying on
HashMapiteration order. - AST traversal is now iterative and depth-bounded, preventing deeply nested input from overflowing a rayon worker's stack.
- Unresolved edges are removed with a warning instead of being silently dropped.
env,gen, andprotoare indexable again.- An explicit
--includenow overrides the built-in excludes.
⚠️ Known limits
A few limitations are worth calling out explicitly:
- Imports are language-local. A Python module importing a TypeScript file through a build step is not linked.
- Chained access only tracks the first receiver. In
a.b.c,cis not attributed to the type ofa.b. - C++ templates are parsed, not instantiated.
vector<Foo>records a reference toFoo. - Go structural matching is per-package. Matching every method set against every interface repository-wide creates more noise than signal.
- Rust macro bodies are token trees. Field access inside
format!and similar macros is recovered by scanning tokens; macro-generated code is not expanded.
📦 Install
macOS / Linux
curl -fsSL https://raw.githubusercontent.com/JeelGajera/graphyn/master/install.sh | bashWindows
irm https://raw.githubusercontent.com/JeelGajera/graphyn/master/install.ps1 | iexCargo
cargo install graphyn-cli🔗 Full changelog
v0.1.3
v0.1.3: The Performance & Dependency Injection Update ⚡
This is a massive update for Graphyn that brings up to a 20x performance increase for large repositories, first-class support for Dependency Injection (DI) frameworks (like NestJS/Angular), and critical stability fixes for Windows users.
✨ Highlights
- Parallel Parsing: Dropped analysis time for 1,000+ file projects from ~10 minutes to under 30 seconds.
- DI & Decorator Tracking: Graphyn now perfectly tracks
this.service.method()property accesses originating from constructor-injected dependencies. - Rock-solid Windows Support: Fixed RocksDB path crashes and glob pattern matching on Windows machines.
- Agent Setup Pack: Added pre-built
.mdrule files for Cursor, Claude, Copilot, and Gemini.
🚀 New Features
- Constructor Injection Tracking: Graphyn now parses constructor parameters (e.g.,
constructor(private userRepo: UserRepository)) and accurately mapsthis.userRepo.findById()calls to the underlying class. This eliminates blind spots in DI-heavy TypeScript codebases. - Decorator Support: AST extraction now parses
@Module({ providers: [...], controllers: [...] })arrays, automatically creatingUsesTypedependency edges for framework wiring. - Method-Level Tracking: Queries like
blast-radiusanddepsnow accurately traverse individual method-level relationships instead of just falling back to the parent class. - Agent Setup Pack: Added the
agent-configs/directory containing out-of-the-box system instructions (AGENTS.md,.cursorrules,CLAUDE.md, etc.) to instantly teach your AI agents how to query Graphyn via MCP.
⚡ Performance
- Parallel AST Parsing: Replaced sequential loops with
rayon, maxing out all CPU cores to parse files simultaneously. - Zero-Syscall Probing: Replaced hundreds of thousands of expensive disk syscalls (
.is_file()) with anO(1)memory lookup (HashSet), dramatically speeding up local import resolution. - Eager Barrel Expansion: Pre-computes and caches
export *paths upfront, eliminating exponential lookup loops when resolving imports across massive barrel files.
🐛 Bug Fixes
- Windows RocksDB Crash (CRITICAL): Safely strips
\\?\and\\?\UNC\extended-path prefixes from Windows paths before they hit RocksDB, preventing mixed-separator crashes when writing to the DBLOGfile. - Glob
--includeFilters (CRITICAL): Fixed an issue where the directory walker failed to descend into matching paths on Windows, resulting in0 files parsed. - Zero-File Warnings:
graphyn analyzenow exits gracefully with a helpful warning and troubleshooting tip if your--include/--excludefilters result in 0 files. - Cleaned CLI Output: Removed ugly UNC path prefixes from terminal output on Windows.
- Ambiguous Symbol UX: Improved error messages to explicitly suggest querying by
ClassNameif a method name query is ambiguous. - Intel Mac Installer: Updated the install script to clearly direct
x86_64macOS users to thecargo installfallback.
📦 How to Upgrade
macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/JeelGajera/graphyn/master/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/JeelGajera/graphyn/master/install.ps1 | iexCargo:
cargo install graphyn-cli --git https://github.com/JeelGajera/graphyn --forceFull Changelog: v0.1.2...v0.1.3
v0.1.2
What's Changed - v0.1.2 🚀
- feat(graphyn): add ESM and framework file support with durable re-export persistence by @JeelGajera in #3
- remove stdout debug trace from re-export chain resolver
- persist file re-export metadata in GraphSnapshot (v2) and restore on load
- keep incremental graph updates in sync for file re-exports
- support .mts/.cts/.mjs/.cjs across scanner, parser, resolver, tsconfig probing, and watch mode
- add Vue/Svelte/Astro script extraction preprocessor with line-preserving blanking
- extend import resolution probing to .vue/.svelte/.astro
- add fixtures and tests for dist exclusion, ESM extensions, and framework support
- update architecture and README support matrix
Installation:
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/JeelGajera/graphyn/master/install.sh | bash
# Windows (PowerShell)
irm https://raw.githubusercontent.com/JeelGajera/graphyn/master/install.ps1 | iexFull Changelog: v0.1.1...v0.1.2
v0.1.1
What's New 🚀
- Automated Native Binaries: Graphyn is now compiled for Linux, macOS (Intel & Apple Silicon), and Windows via GitHub Actions explicitly wrapped in native
.tar.gzand.zippayload structures for immediate distribution without build friction. - Agent Skill API (
refresh_graph): Shipped a 4th native MCP Tool specifically built for AI coding agents giving them manual graph reloading mechanics alongside complete internal path filtering capabilities. - Decoupled Architecture: System-wide file filtering, directory crawling, and
.gitignoreintegration have been abstracted natively into the orchestrators (cli+mcp), converting language adapters (likegraphyn-adapter-ts) into pure semantic pipelines.
Frictionless Installers
Developers no longer require a cargo toolchain locally to execute Graphyn CLI or its MCP server locally. Universal bash and powershell upgrade/install scripts are officially mounted and supported.
- Linux/Mac:
curl -fsSL https://raw.githubusercontent.com/JeelGajera/graphyn/main/install.sh | bash - Windows:
irm https://raw.githubusercontent.com/JeelGajera/graphyn/main/install.ps1 | iex
Full Changelog: v0.1.0...v0.1.1
v0.1.0
🚀 Graphyn v0.1.0
Understand the blast radius before you pull the trigger.
Graphyn is a code intelligence engine that models your codebase as a living graph of symbol relationships — so you (and your coding agents) know exactly what will break before making a change.
This is the first public release (v0.1.0) of the Graphyn ecosystem.
✨ What’s New
-
🧠 Deterministic relationship graph engine (Rust)
-
🔗 Alias-aware dependency tracking (
import { A as B }) -
🎯 Property-level access tracking (
.userId,.timestamp, etc.) -
⚡ Fast queries (<100ms target) using in-memory graph
-
📦 RocksDB persistence for near-instant startup
-
🛠️ CLI tooling
analyze,query,watch,serve,status
-
🤖 MCP server support (works with Cursor, Claude Code, etc.)
-
🌐 TypeScript & JavaScript support (v1) via tree-sitter adapter
-
🧪 Real-world bug coverage
- Detects deep alias-import issues that typical tools miss
🧩 Why Graphyn?
Most tools search code.
Graphyn understands relationships.
It answers questions like:
- What breaks if I change this class?
- Where is this symbol used — even under aliases?
- What depends on this function?
This solves real production issues like:
import { UserPayload as ResponseModel } from '../../../models/user_payload'Traditional tools miss this.
Graphyn doesn’t.
⚡ Quick Start
# Install
cargo install graphyn-cli
# Index your repo
graphyn analyze ./my-repo
# Query blast radius
graphyn query blast-radius UserPayload
# Start MCP server (for agents)
graphyn serve --stdio🧱 Workspace Overview
This release includes:
graphyn-core→ graph enginegraphyn-adapter-ts→ TS/JS parsergraphyn-cli→ developer interfacegraphyn-mcp→ agent integration (MCP server)graphyn-store→ persistence layer
🧪 Status
v0.1.0 — Initial stable release
- ✅ Core graph engine
- ✅ Alias resolution (critical feature)
- ✅ Property-level tracking
- ✅ CLI + MCP integration
- ✅ TypeScript/JavaScript support
🔮 What’s Next
- Python adapter (v2)
- More language support (Rust, Go, Java)
- VS Code extension
- Web dashboard
- Advanced analysis (data flow, cross-project graphs)
📜 License
Apache 2.0
💡 Final Note
Graphyn exists because of a real problem:
A deeply nested aliased import broke production — and no tool caught it.
Graphyn is built to never miss that again.
Full Changelog: https://github.com/JeelGajera/graphyn/commits/v0.1.0