Release history
graphify releases
AI coding assistant skill (Claude Code, Codex, OpenCode, Cursor, Gemini CLI, OpenClaw, Factory Droid, Trae). Turn any folder of code, docs, papers, images, videos, or YouTube links into a queryable knowledge graph
All releases
126 shown
Import cycles + LLM registry + fil-PH docs
Case‑sensitive resolution + drop cross‑lang calls
- Run `pip install -U graphifyy` to upgrade.
Full changelog
Bug Fixes
- #811 Unicode identifiers (CJK, Cyrillic, Arabic, accented Latin) no longer collapse to a bare file stem —
_make_idnow uses[^\w]+withre.UNICODEto preserve non-ASCII word chars. Added NFKC normalization so composed/decomposed forms of the same character produce the same ID. Switched tocasefold()for correct locale-sensitive lowercasing._normalize_idinbuild.pykept in sync. - #803 Dedup edge remap uses explicit key-presence check instead of
orso empty-stringsourceisn't silently swapped for thefromfallback. Stalefrom/tokeys are now popped after remapping so they can't leak into edge attributes ingraph.json. - #801
--updatemerge block inskill.mdnow callsbuild_merge()directly instead of an inline NetworkX round-trip that re-introduced the direction-flip bug from #760. Dict merge ordering fixed so explicitsource/targetalways win over stale attrs. Hyperedges pulled fromG.graph(full merged set) rather than just the new extraction. - #808 Subagent prompts now receive an absolute
CHUNK_PATHderived fromgraphify-out/.graphify_rootat dispatch time — chunk files no longer silently land in the wrong directory due to undefined subagent cwd. - Skill version mismatch warning suppressed during
hook-check(runs on every editor tool use, must be silent) and routed to stderr for all other commands.
Upgrade
pip install -U graphifyy
- `graphify export callflow-html` generates a self‑contained Mermaid architecture/call‑flow HTML page
- Living architecture diagram auto‑regenerates on `--watch` rebuilds and post‑commit hooks
Full changelog
What's new
Fixes
- Ollama VRAM exhaustion (#798):
num_ctxis now derived from the actual chunk size instead of hardcoded 131072. With--token-budget 8192, the old value forced Ollama to allocate 128k KV-cache slots on a 31B model — 4×128k slots by chunk 4 caused OOM. New formula:min(input_tokens + output_cap + 2000, 131072)so an 8k chunk gets ~26k instead. - Hollow-response warning improved: now mentions VRAM pressure and points to
GRAPHIFY_OLLAMA_NUM_CTX/GRAPHIFY_OLLAMA_KEEP_ALIVEenv vars as tuning knobs.
Features
graphify export callflow-html(#797): generates a self-contained Mermaid architecture/call-flow HTML page fromgraphify-out/graph.json— community sections, interactive flowcharts with zoom/pan, call detail tables, and graph report highlights.- Living architecture diagram (#800): callflow HTML now auto-regenerates on every
--watchrebuild and post-commit hook if the file already exists. Run once, stays current forever.
Upgrade
uv tool upgrade graphifyy
# or: pip install --upgrade graphifyy
- `graphify extract` tuning flags: --max-workers, --token-budget, --max-concurrency, --api-timeout; removed hard 8‑worker cap
- Pascal/Delphi/Lazarus support via regex fallback extractor for .pas, .pp, .dpr, etc.
- `/graphify --help` now prints Usage block and exits without running pipeline
Full changelog
What's changed
- Fix: MultiGraph crash in explain/path —
G.edges[u, v]crashed on graphs withmultigraph: true. Newedge_data()/edge_datas()helpers inbuild.pyhandle all graph types; all 8 production call sites and 30 skill-file heredocs updated (#796) - Fix: hollow Ollama response drops chunk — when a local model is overwhelmed and returns empty/null content, chunks were silently dropped instead of retrying. Now rerouted into the existing bisection path via
_response_is_hollow()(#792) - Fix: hook OOM on concurrent commits — per-repo
fcntl.flocklock prevents unbounded parallel rebuilds;changed_pathswired through so only modified files re-extract; stale nodes evicted on deletion;GRAPHIFY_REBUILD_TIMEOUTwatchdog (#791) - Fix: Antigravity
.agent→.agents— corrected folder name in platform config, paths, workflow body, and help text (#453) - Fix: Antigravity rules frontmatter —
trigger: always_onYAML frontmatter added so Antigravity recognises the rules file (#785) - Feat:
graphify extracttuning flags —--max-workers,--token-budget,--max-concurrency,--api-timeout; hard 8-worker cap removed; ollama API key gate skipped for loopback URLs (#792) - Feat: Pascal/Delphi/Lazarus — regex fallback extractor works without
tree-sitter-pascal; covers.pas .pp .dpr .dpk .lpr .inc .dfm .lfm .lpk(#781) - Feat:
/graphify --help— all 12 skill files now print the Usage block and stop instead of running the pipeline (#795) - README: 35 languages — updated language count and extension list
Upgrading
uv tool upgrade graphifyy
# or
pip install --upgrade graphifyy
- `graphify uninstall` removes skill files from all platforms and `--purge` deletes `graphify-out/`
- SQL `ALTER TABLE` statements with foreign‑key syntax now emit `references` edges
Full changelog
What's changed
- Fix: context-window retry — API calls that fail with
context_length_exceedednow automatically bisect the file chunk and retry, up to 6 levels deep. No more hard failures on large files. (#789) - Fix: Windows pipeline — three fixes shipped together:
print_benchmark()falls back to ASCII on cp1252 consoles;BrokenProcessPool(spawn mode without__main__guard) now falls back to sequential extraction instead of crashing; Windows skill file rewrites allpython -c "..."blocks as PowerShell heredocs to fix quote-escaping failures. (#788) - Fix: reversed
callsedges after--update—build_merge()now reads saved JSON directly instead of round-tripping through NetworkX, which was silently reversing edge direction on reload. (#760) - Fix: atomic SKILL.md install — temp-file +
os.replace()prevents half-installed empty skill directories; version-stamp guard and warning added for missing installs. (#725) - Feat:
graphify uninstall— removes skill files from all platforms in one shot;--purgealso deletesgraphify-out/. - Feat: SQL
ALTER TABLEFK extraction —ADD CONSTRAINT ... FOREIGN KEYandADD FOREIGN KEYDDL now emitreferencesedges; schema-qualified table names resolved correctly. (#779)
Upgrading
uv tool upgrade graphifyy
# or
pip install --upgrade graphifyy
- Cypher escape strips C0 control chars and \n/\r; YAML frontmatter escapes U+2028, U+2029, tabs, and C0; MCP sanitize_label applied to all LLM‑derived fields; C preprocessor blocked from #include exfiltration via -nostdinc -I /dev/null; merge-driver limited to 50 MB files and 100k nodes; detect_backend() places Ollama last for API key precedence; Neo4j --password reads from NEO4J_PASSWORD env var by default; hooks exception handling narrowed to configparser.Error, OSError
- Skill YAML descriptions now trigger‑oriented
- CLAUDE.md / AGENTS.md / GEMINI.md templates strengthened with graph‑first directives
Full changelog
What's new
- Fix:
.tsxfiles now uselanguage_tsxgrammar for JSX-aware parsing -- previouslylanguage_typescriptwas used, silently dropping all JSX-specific nodes from.tsxfiles (#766) - Fix:
edgeskey in saved graph JSON now normalised tolinksbefore loading -- preventsKeyError: 'links'on graphs written by older NetworkX versions inquery,path,explain, and serve (#768) - Fix: Google Workspace
gws exportdrops unsupportedresourceKeyquery param -- Drive API requires it as an HTTP header; sending it as a query param was a silent no-op (#772) - Security: eleven hardening fixes -- Cypher escape strips C0 control chars and
\n/\r; YAML frontmatter escapes U+2028, U+2029, tabs, and C0; MCPsanitize_labelapplied to all LLM-derived fields; C preprocessor blocked from#includeexfiltration via-nostdinc -I /dev/null; merge-driver 50 MB file size cap and 100k node cap;detect_backend()places Ollama last so paid API keys take precedence over ambientOLLAMA_BASE_URL; Neo4j--passwordreads fromNEO4J_PASSWORDenv var by default; hooks exception handling narrowed to(configparser.Error, OSError) - Refactor: skill YAML descriptions rewritten to be trigger-oriented -- describe what invokes the skill rather than its internal pipeline (#774)
- Refactor: generated
CLAUDE.md/AGENTS.md/GEMINI.mdtemplates strengthened withALWAYS/NEVER/IF ... EXISTSgraph-first directives (#775)
Install / upgrade
pip install -U graphifyy
- Extended SSRF guard to block RFC 6598 CGN range 100.64.0.0/10 on Python <3.11
- TypeScript extraction parity: interface, enum, type alias, module-level const nodes; new_expression emits call edges.
- Quarto (`.qmd`) file support via existing Markdown extractor.
- Optional Google Workspace shortcut export converts `.gdoc`, `.gsheet`, `.gslides` to Markdown sidecars using `gws` CLI; adds `[google]` extra for Sheets table rendering.
Full changelog
What's new
- Feat: TypeScript extraction parity -- interface, enum, type alias, and module-level const nodes extracted; new_expression emits calls edges; parity with Java/C# class_types (#708)
- Feat: Quarto (
.qmd) file support -- routed through existing Markdown extractor (#761) - Feat: optional Google Workspace shortcut export --
graphify extract ./docs --google-workspaceconverts.gdoc,.gsheet, and.gslidesfiles into Markdown sidecars via thegwsCLI; account email pseudonymized via SHA256 hash;[google]extra adds Sheets table rendering support (#752) - Feat: AWS Bedrock backend --
graphify extract ./docs --backend bedrock; credentials via standard AWS provider chain (AWS_PROFILE, AWS_REGION, IAM roles, SSO); model via GRAPHIFY_BEDROCK_MODEL (default anthropic.claude-3-5-sonnet-20241022-v2:0);[bedrock]extra adds boto3 (#757) - Security: SSRF guard extended to block RFC 6598 CGN range 100.64.0.0/10 on Python <3.11
Install / upgrade
pip install -U graphifyy
- hooks.py execution now validates scripts are within repo root — closes supply‑chain attack vector (#747)
- Gemini and OpenAI backends with respective environment key requirements
- Groovy and Spock source code support via tree‑sitter‑groovy
- Luau (Roblox) parsing using the Lua parser
Full changelog
What's new
- Gemini + OpenAI backends —
graphify extract ./docs --backend gemini(GEMINI_API_KEY / GOOGLE_API_KEY) or--backend openai(OPENAI_API_KEY);pip install graphifyy[gemini]/graphifyy[openai] - Groovy + Spock support —
.groovyand.gradlevia tree-sitter-groovy; Spockdef "feature"()syntax handled via regex fallback - Luau support —
.luau(Roblox Luau) extracted using the Lua parser - Markdown structural extraction — headings, code blocks, and nesting hierarchy extracted as graph nodes from
.md/.mdxfiles (zero new deps) collect_files()extension sync — 18 extensions (.sql,.vue,.svelte,.jsx,.ex,.jl, etc.) were silently skipped in skill-mode extraction; now auto-syncs with_DISPATCH- TS import resolution — bare-path,
.svelte.ts,.svelte.js,index.tsdirectory, and multi-dot imports now resolve correctly
Bug fixes
cluster-onlynow loads and saves.graphify_labels.json— human labels survive re-clustering (#744)graphify export wikifails fast (exit 1) when.graphify_analysis.jsonis missing — prevents silent wiki deletion (#746)detect_incrementalforwardsfollow_symlinks— symlinked subtrees no longer vanish on--update(#736)- Ollama import error now says "Ollama" and points to
pip install openai(#750) - hooks.py path execution validates scripts are within repo root — closes supply-chain attack vector (#747)
Upgrade
uv tool upgrade graphifyy
pip install --upgrade graphifyy
- Run both `uv tool upgrade graphifyy` and `pip install --upgrade graphifyy` to update
- `merge-graphs` now supports both `edges` and `links` keys in graph.json
- Ollama backend integration via `--backend ollama` and `pip install graphifyy[ollama]`, auto‑detected with `OLLAMA_BASE_URL`
- Cross‑project global graph commands (`graphify global add/remove/list/path`) storing registrations in `~/.graphify/global.json` with prefixed node IDs to avoid collisions
- `--global --as <name>` flag on `graphify extract` for one‑step registration into the global graph
Full changelog
What's new
- Ollama backend —
graphify extract ./docs --backend ollama; auto-detected whenOLLAMA_BASE_URLis set; defaults toqwen2.5-coder:7b; zero cost;pip install graphifyy[ollama] - Cross-project global graph —
graphify global add/remove/list/pathregisters multiple project graphs at~/.graphify/global.jsonwith<repo>::<id>prefixed node IDs preventing silent collisions --global --as <tag>flag ongraphify extract— registers into the global graph in one stepmerge-graphscollision safety — inputs are now prefix-relabeled before composing, preventing silent node ID collisions
Bug fixes
deduplicate_entitiesraisesValueErrorif called with nodes spanning multiple repos (cross-project dedup disabled by design)--dedup-llmflag now correctly threads through to both fresh and incremental extract pathsgraphify antigravity installwrites to.agent/(not.agents/)- Pi skill YAML frontmatter parse error fixed
merge-graphsnow accepts bothedgesandlinkskeys in graph.json
Upgrade
uv tool upgrade graphifyy
pip install --upgrade graphifyy
Fixed false positives for `_is_sensitive()` causing legitimate files like `tokenizer.py`, `password_verification.py`, and `SecretManager.java` to be dropped.
Full changelog
Bug Fixes
- cluster-only
--graphflag (#724) —graphify cluster-onlynow accepts--graph <path>to specify a non-default graph.json location; positional path and flags can appear in any order _is_sensitive()false positives (#718) — word boundaries on the keyword pattern prevent legitimate source files liketokenizer.py,password_verification.py,SecretManager.javafrom being silently droppedmax_tokenstruncation cascade (#730) — headlessgraphify extract --backend claude/kiminow defaults to 16384 output tokens (was 8192), eliminating the recursive split cascade on dense doc corpora; override withGRAPHIFY_MAX_OUTPUT_TOKENSenv var- Prune message clarity (#539) —
--updatenow clearly distinguishes "N nodes pruned from M deleted files" from "M deletions detected but graph already clean" - Svelte stub node
source_file(#712) — stub nodes created for imported.sveltefiles now carry the resolved import path assource_fileinstead of the importer's path - Svelte static imports (#713) —
extract_svelte()now catches staticimport X from './foo.svelte'via a dedicated regex pass over<script>block content; previously tree-sitter's JS parser silently dropped all static imports - Manifest on full rebuild (#538) —
graphify extract(full rebuild path) now savesmanifest.jsonon every successful run; previously only--updatesaved it, causing stale-manifest drift - Antigravity install paths (#704) —
graphify antigravity installnow writes to.agent/(no trailing s) matching Antigravity's actual config paths - Pi skill YAML parse error (#737) — Pi skill frontmatter description simplified to avoid "nested mappings" error on Pi startup
--dedup-llmwiring — flag now correctly threads LLM backend through todeduplicate_entitiesin both fresh and incremental extract paths; fresh extract path now also runs dedup (previously bypassed it entirely)
- graphify extract runs incrementally, detecting prior manifest.json and caching results by content hash
- Entity deduplication pipeline adds entropy gate, MinHash/LSH blocking, Jaro-Winkler verification, and same‑community boost
- --dedup-llm flag for optional LLM tiebreaker on ambiguous entity pairs
Full changelog
0.7.5
- Feat:
graphify extractnow runs incrementally — auto-detects priormanifest.jsonand re-extracts only changed/new files; semantic results cached by content hash so unchanged docs cost zero LLM tokens on repeat runs (#698) - Feat: Entity deduplication pipeline runs on every build — entropy gate + MinHash/LSH blocking + Jaro-Winkler verification + same-community boost collapses near-duplicate entities (typos, spacing, plurals) before clustering
- Feat:
--dedup-llmflag forgraphify extract— optional LLM tiebreaker for ambiguous entity pairs (~$0.01 for 10k-node graphs), off by default - Fix:
graphify hook installrebuild now preserves human-readable community labels from.graphify_labels.jsoninstead of resetting to generic "Community N" names on every commit (#705) - Fix:
graphify install --platform gemininow works correctly (#706) - Deps:
datasketchandrapidfuzzadded as base dependencies
Fixed dynamic import edge extraction for Svelte projects with aliased and synthetic node IDs.
Full changelog
What's new
Fix: tsconfig JSONC parsing (#700)
_read_tsconfig_aliases() now handles the format every TypeScript tool generates — // comments, /* */ block comments, trailing commas. Previously json.loads threw JSONDecodeError which was silently swallowed, causing alias resolution to return {} for essentially every real TS project (SvelteKit, NestJS, T3, Astro, Vite, Nx). The extends-following logic from v0.7.1 was correct all along — it was just unreachable. Both now work together.
Fix: Svelte dynamic import edges (#701)
Two bugs in the extract_svelte() regex fallback that caused 100% of generated edges to be dropped:
- Bug A: Aliased imports (
$lib/...,$partials/...,@/...) were skipped by a.startswith('.')filter — now resolved via the tsconfig alias map - Bug B: Synthetic node IDs used the wrong
_make_idsignature so both endpoints were phantom nodes; fixed to match_extract_genericand_import_jsconventions
For a real 1,870-file SvelteKit app: 4,246 $lib/... + 478 $partials/... imports now resolve correctly, recovering ~150 previously orphaned .svelte files.
- `graphify extract` enables headless semantic extraction (code AST + doc/paper/image LLM) with configurable backend, output directory, and optional clustering
- Added `export`, `query`, `path`, and `explain` CLI subcommands with full integration test coverage
Full changelog
What's new
graphify extract — headless semantic extraction for CI (#698)
Docs-only and mixed corpora can now run full LLM extraction without Claude Code:
pip install --upgrade graphifyy
export MOONSHOT_API_KEY=... # or ANTHROPIC_API_KEY
graphify extract ./docs
What it does: detect → AST extract on code files → semantic LLM extract on docs/papers/images → merge → cluster → write graph.json + .graphify_analysis.json.
Flags:
--backend kimi|claude— explicit backend (auto-detected from env if omitted)--out DIR— output root (default:<path>/graphify-out/)--no-cluster— skip community detection, write raw extraction only
Supported backends: Anthropic (ANTHROPIC_API_KEY) and Kimi (MOONSHOT_API_KEY). When using the /graphify skill interactively, any model your IDE session runs is used instead.
Also in this release
- Export/query/path/explain CLI subcommands (from 0.7.2) now have full integration test coverage
- skill.md reduced from 63KB to 47KB (#696)
- Requires installation of the base dependency `tree-sitter-fortran` via `pip install tree-sitter-fortran` for Fortran support.
- Adds parsing for Fortran source files (26th supported language) with preprocessor handling for *.F extensions via `cpp -w -P`.
- Introduces `graphify export` subcommands: html, obsidian, wiki, svg, graphml, neo4j replacing prior Python snippet workflow.
Full changelog
What's new
Fortran support (26th language)
- Parses
.f,.F,.f90,.F90,.f95,.F95,.f03,.F03,.f08,.F08files - Extracts modules, subroutines, functions, programs, use statements, and calls
- Capital-F extensions (
*.F,*.F90, etc.) are preprocessed withcpp -w -Pbefore parsing to handle#ifdef/#definedirectives
Export CLI subcommands
New graphify export <format> subcommands replace the Python snippet workflow:
graphify export html # interactive graph.html
graphify export obsidian # Obsidian vault (--dir PATH)
graphify export wiki # wiki/ markdown articles
graphify export svg # static SVG
graphify export graphml # GraphML for Gephi/yEd
graphify export neo4j # cypher.txt (or --push URI for live import)
Also available: graphify query, graphify path, graphify explain
skill.md size reduction
Reduced from 63KB to 47KB by replacing multi-line Python heredocs with single-line CLI calls. Fixes #696.
Large graph aggregation
to_html() now accepts node_limit — when exceeded, automatically renders a community meta-graph instead of the full graph.
Requires: pip install tree-sitter-fortran for Fortran support (added as base dependency in this release)
Fixed recursion crash on large codebases by raising Python's recursion limit to 10,000.
Full changelog
Three bug fixes for edge cases that were causing silent failures or broken outputs.
What's fixed
Obsidian tags with special characters (#690)
Community labels containing ., &, (, ) were producing invalid Obsidian tags that broke Dataview queries. Tags are now sanitized to [a-zA-Z0-9_\-/] only before being written to the vault.
SvelteKit / Nuxt / NestJS path aliases (#691)
tsconfig.json path aliases defined in extended configs (via the `extends` field) were silently dropped. The alias resolver now follows the full extends chain, so `@/components` resolves correctly even when the alias lives in a base config two levels up.
Svelte template-layer dynamic imports (#692)
Tree-sitter only parses the script block of .svelte files. Markup-level dynamic imports like `{#await import('./Modal.svelte')}` in the template were invisible to the graph. A regex pass now runs after AST extraction to catch these.
Recursion crash on large codebases (#695)
Files with deeply nested AST trees (generated code, minified output, some auto-generated schemas) could hit Python's default 1000-frame recursion limit and crash the whole extraction run. The limit is now raised to 10,000 at startup and in each worker process. A `_safe_extract` wrapper catches any file that still overflows and skips it with a clear warning — the rest of the run completes normally.
How to get it
pip install --upgrade graphifyy
or
uvx graphifyy
- Run `graphify hook install` in each repository to add the merge driver entry in `.gitattributes` and register the driver in `.git/config`
- Existing repos without the hook will continue to experience `graph.json` conflicts until the hook is installed
- Automatic union-merge driver for `graph.json` eliminating merge conflicts via git attributes
- Seeded Leiden community detection producing deterministic community IDs across rebuilds
- `graph.json` records the building Git commit hash; `GRAPH_REPORT.md` displays it for staleness checks
Full changelog
Hey everyone,
One of the most common pain points I kept hearing about: graphify works great on a solo project, but once you have multiple people committing, things get messy. graph.json ends up with conflict markers, two devs rebuild from the same code and get different community IDs, renamed files blow away the cache. This release fixes all of that.
What's new
No more merge conflicts in graph.json
Run graphify hook install once in your repo. It now sets up a git merge driver that union-merges two graph.json files automatically. When two teammates commit at the same time and git tries to merge their graphs, it just combines the nodes and edges from both sides. No conflict markers, no manual resolution, nothing to think about.
It also writes the right .gitattributes entry and registers the driver in .git/config for you.
Deterministic community IDs
Leiden community detection is now seeded. Before this, two people rebuilding the graph from identical code could get different community numbers, which meant a 500-node diff for a 2-line code change. Now parallel rebuilds produce the same output.
Renamed files reuse their cache
The file hash used to include the file path, so renaming utils.py to helpers.py would invalidate the cache and re-extract the whole file. Now it's content-only. Rename 50 files in a refactor and the cache still hits.
Graph freshness signal
graph.json now records which git commit it was built from. GRAPH_REPORT.md shows the short hash so your AI assistant (or you) can compare against git rev-parse HEAD and know if the graph is stale before answering architecture questions.
Mixed code/doc commits handled correctly
If a commit touched both Python files and markdown docs, watch mode used to skip the code rebuild entirely. Now it rebuilds the code immediately and queues the docs for LLM re-extraction separately.
How to get it
pip install --upgrade graphifyy
or
uvx graphifyy
Then run graphify hook install in your repo to set up the merge driver and post-commit hooks.
- `GRAPHIFY_OUT` env var overrides the output directory
Full changelog
0.6.9 (2026-05-03)
- Fix:
source_filepath separators normalized to forward slashes at graph ingestion — same physical file emitted with backslashes (Windows AST extractor) and forward slashes (semantic subagents) now merges into one node instead of splitting into two disconnected components (#683) - Fix: two-phase cohesion re-clustering — communities with cohesion < 0.05 and ≥ 50 nodes are re-split, preventing doc-hub nodes (e.g.
CLAUDE.md) from merging unrelated subsystems into one giant community (#683) - Fix: VS Code Copilot instructions rewritten to be prescriptive — agent's first tool call must read
GRAPH_REPORT.md, explicit trigger list, narrow allowlist for raw source reads (#688) - Feat:
GRAPHIFY_OUTenv var overrides the output directory — accepts a relative name or absolute path, wires throughcache.py,watch.py, and the CLI; useful for sharing one graph across multiple git worktrees (#686) - Fix:
graphify antigravity installnow auto-updates stale rules and workflow files on re-run instead of silently skipping them (#652) - Docs: README simplified — less dense, plain language; technical pipeline details moved to
docs/how-it-works.md
Fixed file‑ignore negation patterns so excluded files inside ignored directories are correctly processed.
Full changelog
0.6.8 (2026-05-03)
- Fix:
.graphifyignorenegation patterns (!src/**) now work correctly — when any!pattern is present, directory pruning is deferred to per-file checks so negated files inside ignored directories are reached (#676) - Fix: Antigravity slash command
/graphifynow appears in the command dropdown — workflow file now includes YAML frontmatter withname: graphifyrequired for Antigravity discovery (#678) - Fix: Gemini CLI BeforeTool hook replaced
[ -f ... ] && echo(bash-only) with cross-platformpython -cusingjson.dumps— fixes hook failure on Windows CMD and Git Bash (#681) - Fix: Codex hook-check exits silently — resolves
additionalContextrejection on Codex Desktop PreToolUse (#651) - Fix:
graphify install --platform codexnow writes absolute path tographifyexecutable — fixes PATH resolution in VS Code extension on Windows (#651) - Fix: thin communities (fewer than 3 concept nodes) are now omitted from the Communities section in
GRAPH_REPORT.mdby default; report header shows(N total, M thin omitted)and Knowledge Gaps collapses thin communities to one summary line (#664)
- `graphify tree` – self‑contained D3 v7 collapsible‑tree HTML view of `graph.json` with expand/collapse controls, depth‑based colours and hover inspector
- Token‑aware chunking – split‑and‑retry on output truncation; chunk size adapts to token budget instead of static file count
- MCP context filters – `query_graph` now accepts `context_filter` for cross‑language edge filtering
Full changelog
What's new
Features
graphify tree— self-contained D3 v7 collapsible-tree HTML view ofgraph.json; expand/collapse controls, depth-based colours, hover inspector (#557)- Token-aware chunking — split-and-retry on output truncation; chunk size adapts to token budget instead of static file count (#625)
- MCP context filters —
query_graphtool now acceptscontext_filterfor cross-language edge filtering (#573) - Dynamic
import()extraction — JS/TS dynamic imports now appear asimports_fromedges (#579)
Bug fixes
- Fix:
save_semantic_cachecrashed withIsADirectoryErrorwhen a node'ssource_filewas a directory — changedp.exists()top.is_file()(#655) - Fix:
sanitize_label(None)raisedTypeError, crashingto_htmlon graphs with rationale nodes that have nullsource_file(#656) - Fix: chunk-extraction prompt omitted
rationalefrom validfile_typevalues — model hallucinatedconcepton every doc/paper run; all skill variants updated (#657) - Fix:
cost.jsonalways reported 0 tokens — added explicit chunk-merge step that globs and sums real token counts across all skill variants (#658)
Install / upgrade
pip install --upgrade graphifyy
uvx graphifyy install
- MD5 hash usage marked usedforsecurity=False in detect.py (non‑cryptographic file change detection)
- SHA1 hash usage marked usedforsecurity=False in transcribe.py (filename generation only)
- .graphifyinclude hidden path allowlist for opting specific hidden files/dirs into traversal
- --no-viz flag now works in cluster-only path to remove stale graph.html
- GRAPHIFY_VIZ_NODE_LIMIT env var to override the 5000‑node HTML threshold
Full changelog
What's new
New platform: Pi coding agent (#661)
graphify pi install/graphify pi uninstall— installs skill to~/.pi/agent/skills/graphify/SKILL.mdgraphify install --platform pialso supported
Bug fixes
- Windows skill (
skill-windows.md) — complete rewrite from PowerShell to bash. Claude Code on Windows uses git-bash, so PowerShell syntax (\$null,\$LASTEXITCODE,Select-Object,Remove-Item) caused exit code 49 failures. Now mirrorsskill.mdexactly, withpythonadded as fallback afterpython3for Windows Conda environments (#39) - Wiki stale clearing —
to_wiki()now clears old.mdfiles before regenerating, preventing orphan article accumulation across runs (#558) - Windows filenames in wiki —
_safe_filename()now strips all Windows-reserved characters (< > : " / \ | ? *) and caps length at 200 chars (#594) - Rationale node leakage — rationale nodes were leaking into cross-file INFERRED call resolution, inflating god_node rankings with spurious edges. Filtered in 3 places in
extract.py(#576) - Edge direction in exports —
callsandrationale_foredges were being flipped ingraph.jsonandgraph.htmldue to NetworkX undirected storage canonicalizing endpoint order. True direction now restored from_src/_tgtmetadata stashed bybuild.py(#576) skill-trae.mdSyntaxError — stray colon in--cluster-onlyblock caused install failures (#603)
Security fixes
- MD5 hash in
detect.pymarkedusedforsecurity=False(used for file change detection only, not cryptography) - SHA1 hash in
transcribe.pymarkedusedforsecurity=False(used for filename generation only)
Packaging fix
pyproject.toml: tightened wheel packaging to only include thegraphifypackage — wheel drops from 1.7MB to 285KB
New features
.graphifyincludehidden path allowlist — opt specific hidden files/dirs into traversal (e.g..hermes/plans/) (#583)--no-vizflag now works incluster-onlypath — removes stalegraph.htmlwhen passed (#565)GRAPHIFY_VIZ_NODE_LIMITenv var — override the 5000-node HTML threshold (set to0to disable viz entirely, useful for CI) (#565)
Skill updates
- INFERRED confidence score guidance changed to discrete rubric (0.55 / 0.65 / 0.75 / 0.85 / 0.95) — continuous ranges were collapsing to a bimodal distribution (>50% at 0.5, >40% at 0.85+) (#546)
--updateprune output now splits into drift-detected vs no-drift cases for clarity (#544)--updatemerge step now callssave_manifestto prevent deleted files reappearing as ghost nodes on subsequent runs (#545)
Install / upgrade
pip install graphifyy==0.6.6
# or
uv tool install graphifyy
- After upgrading via `pip install --upgrade graphifyy`, Windows Codex users must re-run `graphify codex install` to regenerate the hook.
- `graphify update --force` bypasses node‑count safety check
- Checkbox multi‑select for community sidebar replaces show/hide buttons
Full changelog
Changes
- Fix: Codex PreToolUse hook on Windows (#651, #522) — replaced
python3 -c "..."(breaks on Conda, broken by PowerShell JSON parsing) withgraphify hook-check, a new shell-agnostic subcommand. Re-rungraphify codex installto regenerate the hook. - Fix: Kotlin zero calls edges (#659) — call-walker now accepts both
simple_identifierandidentifiernode types across grammar versions - Feat:
graphify update --force(#639) — bypass node-count safety check after refactors that legitimately shrink the graph; alsoGRAPHIFY_FORCE=1env var - Feat: checkbox multi-select for community sidebar (#647) — replaces show/hide buttons with checkboxes + indeterminate select-all state
Upgrade
pip install --upgrade graphifyy
Windows Codex users: also re-run graphify codex install after upgrading to regenerate the hook.
- After upgrading, re-run `graphify codex install` to regenerate the fixed Codex PreToolUse hook.
Full changelog
Bug Fix
- Codex PreToolUse hook fails on Windows (#651) — the hook used
[ -f graphify-out/graph.json ]which is bash-only and crashes oncmd.exe. Replaced with a cross-platform Python one-liner (pathlib.Path.exists()) that works on Windows, Linux, and macOS.
Upgrade
pip install --upgrade graphifyy
# or
uvx graphifyy install
After upgrading, re-run graphify codex install to regenerate the hook with the fixed command.
- Upgrade using `pip install --upgrade graphifyy` or `uvx graphifyy install`.
Full changelog
Bug Fixes
- Incremental rebuild drops semantic nodes (#653) —
graphify updateand post-commit hooks now preserve INFERRED/AMBIGUOUS nodes by ID membership rather thanfile_type, so LLM-extracted call/data-flow edges survive code-only rebuilds - Git hooks block commit for hours (#650) — post-commit and post-checkout rebuilds now detach via
nohup & disown, git returns in ~100ms, rebuild log at~/.cache/graphify-rebuild.log - Common names inflate god_nodes (#543) — cross-file INFERRED
callsnow skips any callee resolving to 2+ candidates (ambiguous short names likelog,execute,findno longer accumulate hundreds of spurious edges) - cluster-only crashes on large graphs (#541) —
to_htmlin cluster command now guarded with try/except ValueError matching the watch/hook path
Upgrade
pip install --upgrade graphifyy
# or
uvx graphifyy install
- Run `pip install --upgrade graphifyy` to apply the license cleanup and all other changes.
- Removed `html2text` (GPL‑3.0) dependency; replaced with MIT‑licensed `markdownify`.
- `graphify query "MyFunction"` now returns the exact function first via exact‑match boost.
- Added support for R language files (`.r`) using LLM semantic extraction.
- Extensionless shell scripts are now detected and processed via shebang line.
Full changelog
Highlights
- Query exact-match:
graphify query "MyFunction"now returns the actual function first, not hub modules - Kimi K2.6 fixed: reasoning mode was eating all tokens leaving graphs empty — disabled on Moonshot calls
- Smarter --update: mtime bumps from sync tools (Obsidian, Nextcloud) no longer trigger re-extraction — content hash verified first
- License cleanup: replaced
html2text(GPL-3.0) withmarkdownify(MIT) — no more copyleft in a MIT project - R language support + extensionless shell scripts via shebang detection
All fixes
- Fix: Kimi K2.6 thinking mode consumed entire token budget — disabled on Moonshot calls (#623)
- Fix:
graphify updatenever persisted manifest — every run re-extracted everything (#621) - Fix: inline comments in
.graphifyignore(vendor/ # legacy) now stripped correctly (#605) - Fix: exact-match query boost — queried symbol renders first, not degree-sorted hubs (#638)
- Fix: concurrent extractors raced on shared
.tmpcache file — unique tempfile per writer (#589) - Fix: branch names starting with
-could inject git flags in_clone_repo(#589) - Fix: replaced
html2text(GPL-3.0) withmarkdownify(MIT) (#586) - Fix: content hash check before re-extracting mtime-bumped files (#593)
- Fix: cross-language INFERRED calls no longer surface as top surprising connections (#630)
- Fix:
cluster-onlyCLI flipped directed graphs to undirected (#590) - Fix: Windows UNC paths normalize to consistent cache keys (#629)
- Fix:
.graphifyignorenegation patterns (!pattern) now work with last-match-wins (#628) - Feat: R language (
.r) support via LLM semantic extraction (#617) - Feat: extensionless shell scripts detected via shebang (#619)
Upgrade
pip install --upgrade graphifyy
- Run `pip install --upgrade graphifyy` to apply the fix.
Full changelog
What's fixed
- Correct gitignore semantics: outer rules load first so inner (closer) rules always win via last-match-wins — matching standard gitignore behavior exactly (#643)
- Hermetic non-VCS scan: without a VCS root,
.graphifyignorediscovery stops at the scan folder — no leakage across sibling projects in a shared workspace (#643) - Anchored patterns: leading
/patterns in a parent.graphifyignorenow apply only relative to their own directory, not the scan root (#643) - Trailing space spec: unescaped trailing spaces are stripped,
vendor\(escaped) is preserved per gitignore spec (#643)
Upgrade
```
pip install --upgrade graphifyy
```
- Install 'graphifyy[sql]' for SQL support
- Graphify now supports Python up to 3.14 (upper bound removed)
- YAML indexing automatically extracts semantics from Kubernetes, Helm, and config YAML files
- SQL AST extraction via tree-sitter adds CREATE TABLE/VIEW/FUNCTION nodes and REFERENCES/JOIN edges
Full changelog
What's new in v0.6.0
SQL AST extraction
.sql files are now processed deterministically via tree-sitter — no LLM needed, no tokens spent.
graphify extracts:
CREATE TABLE→ table nodesCREATE VIEW→ view nodesCREATE FUNCTION/CREATE PROCEDURE→ function nodesREFERENCESconstraints → foreign key edges (EXTRACTED confidence)FROM/JOINclauses →reads_fromedges (EXTRACTED confidence)
This means your entire backend — application code + database schema — maps into one graph. Tables, views, stored functions, and their relationships are first-class nodes just like Python classes or Go structs.
Supports standard SQL, PostgreSQL, Snowflake, and any dialect the tree-sitter-sql grammar covers.
Setup:
```
pip install 'graphifyy[sql]'
/graphify .
```
YAML indexing (v0.5.7)
.yaml and .yml files are now picked up for semantic extraction. Kubernetes manifests, Kustomize overlays, Helm values, and any YAML config are indexed automatically — no extra setup needed.
Bug fixes (v0.5.6 / v0.5.7)
- Fixed
NameError: _os is not definedcrash aftergraphify update - Fixed Kimi K2.6 400 error — temperature param now omitted for Kimi backends
- Fixed community labels deleted on cleanup —
.graphify_labels.jsonnow persists across re-clusters - Removed Python upper bound — now supports Python 3.14+
- Fixed
SyntaxWarningin shell glob pattern
Install / upgrade
```
pip install --upgrade graphifyy
pip install 'graphifyy[sql]' # for SQL support
```
- Optional Kimi K2.6 backend for semantic extraction (3x lower cost, 6x richer relations)
- Fixed phantom god node cross-file resolution in member-call callees
- graphify update command auto-discovers root directory
Full changelog
What's new in v0.5.5
- Kimi K2.6 backend —
pip install 'graphifyy[kimi]'then setMOONSHOT_API_KEYto route semantic extraction through Kimi K2.6 instead of Claude subagents. 3-6x richer relation extraction at ~3x lower cost. Claude remains the default; Kimi is opt-in. A tip is printed when the key is not set so users discover it naturally. - Phantom god node fix (#598) — member-call callees (
this.logger.log()→log) are no longer cross-file resolved. Go package-qualified calls (pkg.Func()) are correctly preserved. Affects JS/TS, Go, Rust, Swift, Kotlin, Scala, PHP, C++, C#, Zig, Elixir. - concept file_type fix (#601) — nodes with
file_type: conceptno longer produce validation warnings. - graphify update remembers scan root — saves root to
graphify-out/.graphify_rootsographify updatewith no args finds the right directory automatically.
Fixes #598, #601.
- SSRF DNS rebinding attack in safe_fetch: socket.getaddrinfo patched for entire request duration; DNS lookup failures now raise errors
- SSRF bypass in yt-dlp download_audio: validate_url validation added before URL handoff to block private IPs and disallowed schemes
Full changelog
What's new in v0.5.4
- SSRF DNS rebinding fix —
safe_fetchnow patchessocket.getaddrinfofor the entire duration of each HTTP request so a DNS rebinding attack cannot swap a public IP (returned during validation) for a private one during the actual connection. DNS lookup failures now also raise an error instead of silently skipping the IP check. - yt-dlp SSRF bypass fix —
download_audionow runsvalidate_urlbefore handing the URL to yt-dlp, blocking private IPs and disallowed schemes on the video/audio ingest path.
Fixes #591, #592.
Fixes update command breaking on mixed code+docs corpora
Full changelog
Fixes graphify update broken on mixed code+docs corpora (#582)
AST and semantic cache entries now live in separate cache/ast/ and cache/semantic/ subdirectories. Previously both wrote to the same flat cache/ directory — semantic results silently overwrote AST entries for code files, causing the shrink guard to fire on every subsequent graphify update run.
Existing flat cache entries are read as a migration fallback so no cache is lost on upgrade.
Upgrade: pip install --upgrade graphifyy
PreToolUse hook fixed for Claude Code v2.1.117+ where Grep/Glob removal broke searches.
Full changelog
Hotfix for Claude Code v2.1.117+
The PreToolUse hook installed by graphify claude install was silently broken on Claude Code v2.1.117+ because dedicated Grep and Glob tools were removed — searches now go through Bash. The hook never fired, meaning the graph context reminder was never injected.
Fix: Hook matcher changed from Glob|Grep to Bash. The hook now reads the tool input JSON from stdin and pattern-matches on the command string, firing only on search-like calls (grep, rg, find, fd etc.) — not on every shell command.
Upgrade: pip install --upgrade graphifyy && graphify claude install
Closes #578
- Relative paths in `source_file` make graphs portable across machines and git worktrees
- TypeScript `compilerOptions.paths` aliases resolve to real file nodes
- Node ID collisions resolved for files with same name in different directories
Full changelog
6 bug fixes shipped in this release:
- Node ID collisions — files with the same name in different directories (e.g. two
utils.pyfiles) now get unique node IDs via parent-directory-qualified stems - Portable
source_filepaths —extract()relativizes all paths before returning;graph.jsonis now portable across machines and git worktrees - Desync guard —
to_json()returns a boolean;graphify updateonly writesGRAPH_REPORT.mdandgraph.htmlif the JSON write succeeded (shrink guard fired = no stale report) - TypeScript path aliases —
@/and othercompilerOptions.pathsaliases intsconfig.jsonnow resolve to real file nodes instead of being dropped as external packages - Show All / Hide All — community panel in the HTML visualization now has bulk-toggle buttons
- Skill prompt corrections — rationale stored as a node attribute (not a spurious fragment node);
callsedge direction explicitly enforced (caller → callee)
Also includes tooling fixes from the v0.5.0 patch: ~ expansion in core.hooksPath, correct .gitignore inline comment placement, # nosec annotations on file write sinks.
- Clone GitHub repos with graphify clone
- Cross-repo knowledge graph merging
- Data-loss protection on --update
Full changelog
What's new
Clone any GitHub repo directly
graphify clone https://github.com/karpathy/nanoGPT
Clones to ~/.graphify/repos/<owner>/<repo>, reuses existing clones on repeat runs. Supports --branch and --out.
Cross-repo knowledge graphs
graphify merge-graphs repo1/graphify-out/graph.json repo2/graphify-out/graph.json
Every node carries a repo tag so you can filter by origin.
Data-loss protection on --update
graphify now refuses to overwrite graph.json with a smaller graph. New build_merge() library function for safe incremental updates that only ever grows the graph.
Duplicate node deduplication
Chunk-suffix contamination (_c2, _c4) blocked at the prompt level. Post-merge deduplication pass catches any stragglers.
Bug fixes
CLAUDE_CONFIG_DIRenv var respected on install (#527)graphify-out/excluded from source scanning (#524)- Louder field-drift warning with edge count (#479)
Full announcement: https://github.com/safishamsi/graphify/discussions/528
Fixed graphify directory placement and git hook worktree compatibility.
Full changelog
What's fixed
#520 — /graphify <path> now respects the specified directory
The skill was placing graphify-out/ in the current working directory instead of inside the target path. Fixed by adding cd INPUT_PATH as the very first command in Step 1, and changing detect(Path('INPUT_PATH')) → detect(Path('.')) so all relative paths resolve correctly from the target directory. Applied to both skill.md and skill-opencode.md.
#516 — git hook install/uninstall works from worktree checkouts
_hooks_dir() was using git config core.hooksPath which doesn't resolve the shared hooks directory for worktree checkouts. Now uses git rev-parse --path-format=absolute --git-path hooks which git resolves correctly for both normal repos and worktrees. Includes regression tests for install/uninstall from a worktree.
#517 — GitHub dependency graph (no code change needed)
pyproject.toml already points to the correct repository. GitHub's dependency graph cache will update itself.
- Java inheritance extraction (extends, implements)
- Schema canonicalization for legacy formats
- Aggregated HTML view for graphs >5000 nodes
Full changelog
Features & Fixes
- #488 Legacy edge/node schema canonicalization —
source→source_fileon nodes,from/to→source/targeton edges now handled before validation - #482 Java inheritance —
extends,implements, and interface-extendsedges now extracted from AST; two-pass cross-file import resolver emits realimportsedges instead of silently dropping them - #472 Aggregated HTML view for large graphs — corpora >5000 nodes now get a community meta-graph in
graph.htmlinstead of no output at all; updated in bothskill.mdandskill-opencode.md - #490
graphify check-update <path>— cron-safe CLI subcommand that checks for pending semantic updates and notifies without running LLM extraction
441 tests passing.
Minor fixes and improvements.
Full changelog
Fixes
- #513 Windows hook null byte warning — hook now skips
head -1for.exebinaries, goes straight to python3 fallback - #514
to_canvas()hardcodedgraphify/obsidian/path — file refs are now vault-root-relative ({fname}.md), canvas opens correctly regardless of where the vault lives
Tests
- Added
test_to_canvas_file_paths_relative_to_vault— would have caught the hardcoded path bug - Added
test_hook_skips_head_on_exe— verifies the Windows fix is present in the hook script
Fixed garbled Chinese (CJK) characters in terminal output on Windows by enabling UTF-8 mode for Python.
Full changelog
Fix
- #504 Garbled Chinese (CJK) output on Windows — added
export PYTHONUTF8=1to Step 1 ofskill-opencode.mdso all Python subprocesses run in UTF-8 mode on Windows, preventing garbled non-ASCII characters in terminal output and intermediate files
- opencode.json now written to .opencode/opencode.json instead of project root
Full changelog
Fixes
- #498 OpenCode install bugs (3 sub-issues)
opencode.jsonnow written to.opencode/opencode.jsoninstead of project root — consistent with OpenCode's config directory- All intermediate temp files (
.graphify_detect.json,.graphify_extract.json, etc.) inskill-opencode.mdnow correctly usegraphify-out/prefix instead of leaking to project root - Added missing
--wikistep (Step 6b) toskill-opencode.md, matching all other platform skills
- GRAPH_REPORT.md is now deterministic across runs on graphs >1000 nodes (seed=42 added to betweenness_centrality calculation)
- graph.json edge endpoints are now stable across machines (file node IDs normalized to project-relative paths)
Full changelog
Fixes
- analyze.py (#499): Add
seed=42tobetweenness_centrality()—GRAPH_REPORT.mdis now byte-identical across runs on graphs >1000 nodes, eliminating infinite commit churn from the post-commit hook - extract.py (#502): Fix common-root inference to stop at first diverging path segment (not sum of all matching segments); resolve root to absolute path; post-process file node IDs to project-relative after extraction so
graph.jsonedge endpoints are stable across machines
Minor fixes and improvements.
Full changelog
Fixes
- wiki.py (#496): Add
encoding="utf-8"to allwrite_text()calls — fixes crash on Windows cp1252 when articles contain Unicode characters like→ - wiki.py (#497): Deduplicate wiki filenames with
_unique_slug()— prevents silent article overwrites when two communities get the same label - hooks.py (#485): Skip post-commit and post-checkout hooks during
git rebase,git merge, andgit cherry-pick— prevents unstaged changes blocking--continue - detect.py (#495): Resolve
rootpath atdetect()entry — fixes.graphifyignorepatterns from parent directories not matching when graphify is run with a relative path like./raw - README.md (#369): Document
manifest.jsonandcost.jsongitignore recommendations; add.graphifyignoreexample for platform install files
Minor fixes and improvements.
Full changelog
Fixes
- report.py: Complete empty-community fix — Community Hubs navigation now skips empty-community entries, Summary line reflects non-empty community count, Knowledge Gaps excludes zero-node clustering artifacts (extends the Communities section fix from v0.4.24)
- main.py: Added graph-query CLI rule to CLAUDE.md, AGENTS.md, and GEMINI.md install sections — agents now know to prefer `graphify query`, `graphify path`, and `graphify explain` over grep for cross-module questions; added MCP CLI fallback line to Antigravity rules
- Added 17 new language translations (Italian, Polish, Dutch, Turkish, Ukrainian, Vietnamese, Indonesian, Swedish, Greek, Romanian, Czech, Finnish, Danish, Norwegian, Hungarian, Thai, Traditional Chinese)
- Fixed IsADirectoryError crashes in NestJS/TS monorepos by skipping source_file directories during caching
- Fixed git hook failures on macOS by allowing @ in Python path allowlist
Full changelog
Bug fixes
- cache: skip directory
source_fileinsave_cached— preventsIsADirectoryErrorcrash on NestJS/TS monorepos (#448) - report: skip structural-only communities with no real nodes — removes empty
Nodes (0):sections from reports (#443) - hooks: allow
@in python path allowlist — fixes silent git hook failures on macOS with Homebrew Python (#473) - watch: keep
source_filepaths project-relative after code rebuild — fixes absolute paths leaking into graph.json (#434) - skill: clean up
.graphify_chunk_*.jsontemp files at end of run (#464)
Translations
- Added 17 new language translations (Italian, Polish, Dutch, Turkish, Ukrainian, Vietnamese, Indonesian, Swedish, Greek, Romanian, Czech, Finnish, Danish, Norwegian, Hungarian, Thai, Traditional Chinese)
- All 28 translations moved to
translations/subdirectory
- Go import node IDs now use `go_pkg_` prefix with full import path instead of basename — existing graphs with Go imports will have different node IDs
- Added HTML files to indexed documentation extensions
- Enabled analysis of graphs with over 5,000 nodes
Full changelog
What's fixed
- #178 — Stale skill version warning persists after
graphify installwhen multiple platforms were previously installed.graphify installnow refreshes.graphify_versionin all known skill dirs so the warning clears across the board. - #260 —
.htmlfiles silently skipped during detection. Added.htmltoDOC_EXTENSIONS— HTML pages, docs, and web content now indexed. - #432 —
_rebuild_code(watch/update/git hook) failed entirely on graphs > 5000 nodes becauseto_htmlraisedValueError. Wrapped in its own try/except sograph.jsonandGRAPH_REPORT.mdalways land; stalegraph.htmlfrom a previous smaller run is removed. - #431 — Go stdlib imports (e.g.
"context") producedimports_fromedges pointing at local files of the same basename, creating false cycle-dependency pairs. Go import node IDs now prefixedgo_pkg_using the full import path.
Upgrade
pip install --upgrade graphifyy
Minor fixes and improvements.
Full changelog
What's fixed
- #429 — AST cache written to
src/graphify-out/cache/instead of project root when all code files share a common prefix (e.g.src/).extract()now called with explicitcache_rootin_rebuild_codeand the Codex skill AST step. - #428 —
.mdxfiles silently skipped during detection. Added.mdxtoDOC_EXTENSIONS— Next.js, Docusaurus, and Astro corpora now indexed correctly.
Upgrade
pip install --upgrade graphifyy
Fixed `--update` dropping all existing graph nodes when merging.
Full changelog
What's fixed
- #422 —
graphify cluster-onlycrashed withKeyError: 'total_files'inreport.py. Cluster-only skips detection so the stats dict was empty — now passes a warning key so the report skips the file-stats section gracefully. - #423 —
/graphify --updatedropped all existing graph nodes. The merge block built a correct in-memory merged graph but never wrote it back to.graphify_extract.json, so Step 4 rebuilt from the new-extraction-only file. Merged result is now serialized back before Step 4 runs.
Upgrade
pip install --upgrade graphifyy
- graphify update . and graphify cluster-only now generate graph.html alongside graph.json and GRAPH_REPORT.md
Full changelog
What's fixed
- #414 — JS/MJS
imports_fromedges silently dropped for files using../subdir/file.mjsstyle imports.Path.parent / rawleft.." segments unnormalized so the target ID didn't match the actual file node. Fixed withos.path.normpath`. - #418 —
graphify update .andgraphify cluster-onlynow generategraph.htmlalongsidegraph.jsonandGRAPH_REPORT.md. Previously only the skill generated the interactive HTML viewer. - #374 —
graphify vscode installreturningunknown command 'vscode'is fixed as of v0.4.19 (command was missing from the published wheel). Upgrade to resolve.
Upgrade
pip install --upgrade graphifyy
Cross-file call resolution extended to Go, Rust, Zig, PowerShell, and Elixir.
Full changelog
What's fixed
- #390 — AST/semantic node ID mismatch: edges were dropped when the LLM generated slightly different casing or punctuation than the AST extractor.
build_from_jsonnow normalises IDs before dropping edges. - #298 — Cross-file call resolution extended to Go, Rust, Zig, PowerShell, and Elixir. Unresolved callees are saved as
raw_callsand resolved globally in a post-pass. - #410 — Windows
graphify-out/graphify-outnesting bug.cache_dirand_rebuild_codenow call.resolve()on the root path. - #401 —
graphify hook installnow respectscore.hooksPathgit config (Husky and similar tools). - #385 — Kiro skill YAML
descriptionfield now quoted — fixes parse error in Kiro's YAML loader.
Docs
- Windows PATH tip and macOS
pipx ensurepathtip added to install section (#413) - Team workflow section: committing
graphify-out/,.graphifyignoreusage, recommended.gitignoreadditions (#369)
Upgrade
pip install --upgrade graphifyy
- Updated skill.md includes explicit node ID generation rules with examples to minimize LLM ID drift
- Cross-file call resolution for Go, Rust, Zig, PowerShell, and Elixir
- build.py reconciles semantic/AST node ID mismatches to preserve LLM-generated edges
Full changelog
- Cross-file call resolution for Go, Rust, Zig, PowerShell, and Elixir (raw_calls saved and resolved globally)
- Fix semantic/AST node ID mismatch: build.py now reconciles mismatched IDs so LLM-generated edges survive the merge
- skill.md: explicit node ID generation rules with example to reduce LLM ID drift
- Move llm.py out of graphify package into scripts/ so it is not shipped in the PyPI wheel
- Fix NameError: name 'sys' is not defined in graphify watch (v0.4.15 regression) - Fix .mjs files detected but producing 0 nodes (missing _DISPATCH entry) - Exclude llm.py from wheel
- macOS: `graphify watch` now uses PollingObserver by default instead of FSEvents to avoid missed file events
- Windows: Gemini CLI skill installs to `~/.agents/skills/` instead of `~/.gemini/skills/`
- `god_nodes()` return field renamed: `edges` → `degree`
- VS Code Copilot Chat integration with `graphify vscode install` command, including Python-only skill and `.github/copilot-instructions.md` generation
Full changelog
What's new
- VS Code Copilot Chat —
graphify vscode installconfigures VS Code Copilot Chat with a Python-only skill (works on Windows PowerShell) and writes.github/copilot-instructions.mdfor always-on graph context (#206) - Fix: OpenCode plugin path used backslashes on Windows causing duplicate
opencode.jsonentries — fixed via.as_posix()(#378) - Fix: Gemini CLI on Windows now installs skill to
~/.agents/skills/(correct higher-priority path) instead of~/.gemini/skills/(#368) - Fix:
.mjsand.ejsfiles now recognised by the AST extractor as JavaScript (#365) - Fix:
god_nodes()return field renamededges→degreefor clarity - Fix:
graphify watchon macOS now usesPollingObserverby default to avoid missed events with FSEvents (#373)
Upgrade
pip install --upgrade graphifyy
- PHP: static method call edges and class constant reference edges now supported
- Wiki flag (--wiki) now fully functional; generates documentation in graphify-out/wiki/
- Betweenness centrality: early return for 5000+ node graphs, k=100 sampling for 1000+ nodes
Full changelog
What's new
Cross-file call resolution for all languages
AST extraction now emits cross-file calls edges for Swift, Go, Rust, Java, C#, Kotlin, Scala, Ruby, PHP, and every other supported language. Previously only Python had this. Unresolved call sites are saved per file and resolved against a global label map after all files are processed. Cross-file edges are marked INFERRED with confidence 0.8.
PHP static method calls and constant references
Two node types were missing from the PHP extractor. scoped_call_expression (static calls like Helper::format()) now emits calls edges. class_constant_access_expression (enum and constant references like Status::ACTIVE) now emits references_constant edges.
Wiki flag implemented
--wiki now actually runs. Step 6b added to the skill pipeline (before the cleanup step so community labels are still available). Calls to_wiki() and writes graphify-out/wiki/ with index.md and one article per community and god node.
Performance: betweenness centrality on large graphs
edge_betweenness_centrality now returns early for graphs over 5000 nodes. betweenness_centrality in suggest_questions uses k=100 approximate sampling for graphs over 1000 nodes. Eliminates hangs on large repos.
OpenCode plugin installed on both install paths
graphify install --platform opencode now also writes .opencode/plugins/graphify.js and registers it in opencode.json. Previously only graphify opencode install did this.
Cache root fix for subdirectory runs
extract() accepts an explicit cache_root parameter. When graphify narrows to a subdirectory on a large repo, the cache stays at ./graphify-out/cache/ instead of /graphify-out/cache/.
Windows stability
os.replace in the cache writer falls back to shutil.copy2 on PermissionError (WinError 5). graphify update exits with code 1 when rebuild fails instead of silently returning. All generated config files now use graphify update . instead of a hardcoded python3 invocation.
Kiro package data
skill-kiro.md was missing from pyproject.toml package-data, causing graphify kiro install to fail on fresh pip installs. Fixed.
Upgrade
pip install -U graphifyy
- Verilog and SystemVerilog file extraction via tree-sitter-verilog
- HiDPI hyperedge rendering fix for Retina and 4K displays
- Null label guards in MCP server tools prevent crashes on missing fields
- Cache format changed to use relative paths; delete graphify-out/cache/ after upgrade
- Add Kiro IDE/CLI support with skill and steering injection
- Portable cache using relative paths for cross-machine deployments
- Add Dart/Flutter language support (23 languages total)
- Add Hermes Agent platform integration
- Add 6 new CLI commands: path, explain, add, watch, update, cluster-only
- Dart/Flutter language support with regex-based extraction of classes, mixins, functions, and imports
- Diacritic-insensitive search via Unicode NFKD normalization across queries and graph operations
- Hermes Agent platform support for deploying graphify skills
Platform skill files now work correctly on any agent platform by removing Claude-specific language.
- Blade template support: .blade.php files now extracted with @include, components, and wire:click bindings
- Watch now correctly preserves semantic edges on rebuild (was silently dropping edges)
Full changelog
Fixes
- Watch semantic edge loss —
watchwas silently dropping all semantic edges on every rebuild becausegraph.jsonuses thelinkskey but code readedges. Now reads both (#269) - OpenClaw install path —
graphify claw installnow correctly writes to.openclaw/skills/graphify/(#208) - Blade template support —
.blade.phpfiles now extracted:@include,<livewire:\>components, andwire:clickbindings (#242) - WSL/Linux MCP docs — added note covering
graphifyypackage name, venv setup, and full path in.mcp.json(#250)
PyPI: https://pypi.org/project/graphifyy/0.4.7/
- Google Antigravity IDE support with `graphify antigravity install` command
- Auto-generated `.agent/rules/graphify.md` rules and `.agent/workflows/graphify.md` workflows
Full changelog
What's new
Google Antigravity support
graphify now works with Google Antigravity — the agent-first IDE built on Gemini.
pip install --upgrade graphifyy
graphify antigravity install
This writes:
.agent/rules/graphify.md— always-on rules (Antigravity reads these every session).agent/workflows/graphify.md— registers/graphifyas a slash command
Then open Antigravity and type /graphify .
Full changelog: https://github.com/safishamsi/graphify/blob/v4/CHANGELOG.md
PyPI: https://pypi.org/project/graphifyy/0.4.6/
If graphify has been useful, consider sponsoring — we're closing in on 100k PyPI downloads and every bit of support helps keep the project moving.
Fixes MCP server crash when clients send blank lines between JSON messages.
Preserves cross-type edges in watch mode, recovering ~95 edges lost in mixed repositories.
Fixes critical bug where JS/TS relative imports were silently dropped on large codebases.
Minor fixes and improvements.
Full changelog
Bug fixes — 8 issues addressed.
Bug fixes (our commits)
- #211 Same-basename files produced colliding node IDs — now uses full path
- #216 Edges using
from/tokeys were silently dropped — now normalized - #217 Empty graphs caused
ZeroDivisionErrorduring visualization — guarded - #222 Post-commit hook silently skipped
.tsx,.jsxetc — removed staleCODE_EXTSfilter
Community fixes (cherry-picked)
- #212 NetworkX ≤3.1 serialises edges as
links— now accepted alongsideedges - #220 Version warning fired during
install/uninstalland duplicated on shared paths — fixed - #204 All file IO now uses
encoding="utf-8"— prevents crashes on Windows CJK/emoji corpora; hook writes usenewline="\n"to prevent CRLF shebang breakage - #221 Obsidian: node labels ending in
.mdproduced.md.mdfilenames;GRAPH_REPORT.mdnow links to community hub files so the vault stays in one connected component
Upgrade
pip install --upgrade graphifyy
- Local video/audio transcription with faster-whisper
- YouTube link support via yt-dlp
- Automatic Whisper prompt generation from corpus
Full changelog
Video and audio files are now first-class corpus inputs.
Drop .mp4, .mp3, .wav, .mov, .webm, .m4a, .ogg, .mkv, .avi, or .m4v files into any folder and graphify transcribes them locally with faster-whisper before extraction. Transcripts are cached in graphify-out/transcripts/ so re-runs skip already-transcribed files.
You can also add YouTube links directly:
/graphify add https://www.youtube.com/watch?v=...
yt-dlp downloads audio-only (no video stream, much smaller) and the same Whisper pipeline picks it up from there.
The Whisper prompt is built from your corpus automatically. The coding agent reads the top god nodes from your non-video files and writes a one-sentence domain hint for Whisper itself. No separate API call, no configuration needed.
To use:
pip install 'graphifyy[video]'
This installs faster-whisper and yt-dlp. The default Whisper model is base. Pass --whisper-model medium or --whisper-model large-v3 for higher accuracy.
Audio never leaves your machine. Transcription runs fully locally.
Hook installer now properly reinstalls, fixing PreToolUse errors when upgrading from older versions.
Fixed graphify install --platform gemini not copying the skill file to ~/.gemini/skills/graphify/SKILL.md. The /graphify trigger was not working without it. Upgrade with pip install --upgrade graphifyy
- MCP server path validation now validates path exists and ends in .json
- Aider platform integration
- GitHub Copilot CLI support
- --directed flag preserves edge direction
Fixed idempotency in `graphify codex install` to handle existing AGENTS.md sections and recover from incomplete installs.
- Gemini CLI support with hook auto-configuration
Full changelog
What's new
- Add: Gemini CLI support —
graphify gemini installwrites aGEMINI.mdsection and aBeforeToolhook in.gemini/settings.jsonthat fires before file-read tool calls (#105) - Add: sponsor nudge at pipeline completion — all skill files now print a one-line sponsor link after a fresh build (not on
--updateruns)
Install / upgrade
pip install --upgrade graphifyy
graphify gemini install # Gemini CLI users
Full changelog: CHANGELOG.md
- Cursor IDE support with .cursor/rules auto-configuration
Full changelog
What's new
- Add: Cursor support —
graphify cursor installwrites.cursor/rules/graphify.mdcwithalwaysApply: true;graphify cursor uninstallremoves it (#137) - Fix:
_rebuild_code()KeyError — git hooks were silently failing on every commit becausedetected[FileType.CODE]didn't matchdetect()'s actual return shape (#148) - Fix: crash on NetworkX 3.2.x —
node_link_data()now falls back gracefully on older NetworkX, same shim already used everywhere else (#149) - Fix: official package clarification in README —
graphifyyis the only official PyPI package (#129)
Install / upgrade
pip install --upgrade graphifyy
Re-run graphify hook install to get the fixed git hooks.
Full changelog: CHANGELOG.md
Fixed Windows compatibility for git hooks and Codex hook JSON schema validation.
- XSS in interactive HTML graph; node labels, file types, community names, source files, edge relations now HTML-escaped
- OpenCode tool.execute.before plugin support
- AST call edges EXTRACTED status
- Tree-sitter version pinning
Install process now attempts plain pip install first, only using --break-system-packages as fallback.
- graphify save-result CLI subcommand
Full changelog
Fixes
- Watch + .graphifyignore:
--watchmode now respects.graphifyignore—_rebuild_codewas callingcollect_files()directly instead ofdetect(), bypassing ignore patterns (#120) - Codex PreToolUse hook: now uses
systemMessageinstead ofadditionalContext— Codex does not supportadditionalContextand was returning an error (#121) - Trae link: corrected from
trae.comtotrae.aiacross all READMEs (#122) - HTML graph click detection: hover-tracking (
hoveredNodeId) replaces unreliable vis.js click params — small/dense nodes now reliably selectable (#82) .graphify_pythonpersistence:mkdir -p graphify-outruns before writing.graphify_python; file no longer deleted in Step 9 cleanup — pipx users no longer hitModuleNotFoundErroron follow-up commands (#93)- Trae skill packaging:
skill-trae.mdadded topyproject.tomlpackage-data — Trae users were gettingModuleNotFoundErrorafterpip install(#102) - Extension drift:
analyze.pyandwatch.pynow import extension sets fromdetect.pyinstead of local copies — Swift, Lua, Zig, PowerShell, Elixir, JSX, Julia, Objective-C files were being misclassified as documents (#109)
Additions
graphify save-resultCLI subcommand — saves Q&A results to memory dir; replaces inline Python blocks in all 6 skill files (#114)- Korean README added (README.ko-KR.md) (#112)
- Interpreter guard section in
skill.mdfor whengraphify-out/is deleted before follow-up commands (#93)
Refactors
- Dead
build_graph()function removed fromcluster.py(#109)
Install
pip install graphifyy==0.3.18 && graphify install
- Julia (.jl) language support with AST extraction
- Semantic extraction chunk grouping by directory
Full changelog
- Add: Julia (.jl) support — modules, structs, abstract types, functions, short functions, using/import, call edges, inherits edges (#98)
- Fix: Semantic extraction chunks now group files by directory — reduces missed cross-chunk relationships (#65)
- Fix: `tree-sitter>=0.21` now pinned — prevents silent empty AST output on older tree-sitter versions (#52)
- Add: Progress output every 100 files during AST extraction on large projects (#52)
Fixed ModuleNotFoundError that prevented pipx users from running follow-up commands.
- XSS in HTML legend (community labels now HTML-escaped)
- Shebang allowlist validation prevents metacharacter injection
- Trae and Trae CN platform support
- Japanese README documentation
Fix HTML entity double-encoding in interactive graphs and missing --wiki flag.
Full changelog
0.3.12
- Fix:
sanitize_labelwas double-encoding HTML entities in the interactive graph (&lt;instead of<) — removedhtml.escape()fromsanitize_label; callers that inject directly into HTML now callhtml.escape()themselves (#66) - Fix:
--wikiflag missing fromskill.mdusage table (#55)
Fixes indefinite hang in Louvain fallback for large sparse graphs without graspologic.
- Skill staleness warning with version stamp tracking
Full changelog
What's new
Fix: Windows Unicode crash (#47)
- Replaced arrow character with
->in all print statements — fixesUnicodeEncodeErroron cp1252/Windows consoles
Add: Skill staleness warning (#46)
graphify installnow writes a version stamp alongside the skill file- Every
graphifycommand checks all platform skill locations and warns if the installed skill is from an older version - Works across Claude Code, Windows, Codex, OpenCode, OpenClaw, Factory Droid
- Symlink traversal with follow_symlinks parameter
- Circular symlink cycle detection
- watch.py refactored to use collect_files()
Full changelog
What's new
Symlink support (#33)
detect()andcollect_files()now acceptfollow_symlinks=Trueto traverse symlinked files and directories- Circular symlink cycle detection prevents infinite recursion
watch.pynow usescollect_files()for consistency
Docs
- Codex skill trigger is
$graphify .not/graphify .(#36)
Tests
- 367 tests passing (up from 362)
- C# inheritance extraction
- graphify query CLI command for BFS/DFS search
Full changelog
What's new
C# inheritance extraction (#45)
DataProcessor : IProcessornow emitsinheritsedges- Handles both simple bases (
identifier) and generic bases (IList<T>→generic_name) - Zero false positives — tested on 6,100-file Unity/VaM codebase producing 3,957 edges
graphify query CLI command (#43)
- Query the knowledge graph without Claude Code:
graphify query "what connects attention to the optimizer?" graphify query "what is CfgNode?" --dfs graphify query "show auth flow" --budget 500 --graph path/to/graph.json - BFS by default,
--dfsfor path tracing,--budget Nto cap output tokens
Tests
- 362 tests passing (up from 360)
- Objective-C support (.m, .mm files via tree-sitter)
- --obsidian-dir flag for custom vault paths
- Elixir (.ex, .exs) AST extraction
Full changelog
What's new
- Elixir language support —
.exand.exsfiles now go through AST extraction. Extractsdefmodule,def/defp,alias/import/require/use, and the call graph between functions. Same EXTRACTED/INFERRED tagging as every other language.
- DOCX support via python-docx
- XLSX support via openpyxl
- Optional [office] dependency with graceful fallback
Full changelog
What's new
- .docx and .xlsx support — Office documents now work in graphify. Install the optional extra:
pip install graphifyy[office].docx: converted to markdown viapython-docx(headings, lists, tables preserved).xlsx: each sheet converted to a markdown table viaopenpyxl- Converted files are saved to
graphify-out/converted/as.mdsidecars — Claude reads them as normal documents - Graceful fallback if
[office]is not installed: file is skipped with an install hint
Fixes UnicodeDecodeError crashes on Windows systems with non-UTF-8 locales like GBK.
- Windows auto-detection and PowerShell-compatible skills
Full changelog
What's new
- Windows support —
graphify installnow auto-detects Windows and installs a PowerShell-compatible skill variant (skill-windows.md). All bash-specific commands replaced:which/head/tr→ Python detection,rm -f→Remove-Item,mkdir -p→New-Item,python3→python - Manual override:
graphify install --platform windowson any platform
- Zig language support
- PowerShell support
- Factory Droid platform
- Neo4j Cypher injection via backslash sequences in node labels
- HTML sanitization in visualization
- Tweet fetching SSRF protection bypass
- Multi-platform support (Claude Code, Codex, OpenCode, OpenClaw)
- Always-on project hooks for all platforms
- MIT license
- Obsidian vault generation changed from default to opt-in; use --obsidian flag to enable
- Docstrings and tagged comments become graph nodes
- Confidence scores on inferred edges
- Semantic similarity edges for cross-file concepts
Full changelog
What's new in v0.2.0
Mine the "why"
Code comments and docstrings are now first-class graph nodes. Module, class, and function docstrings are extracted automatically. Inline comments tagged # NOTE:, # IMPORTANT:, # HACK:, # WHY:, # RATIONALE:, # TODO:, # FIXME: become rationale_for nodes connected to the code entity they explain. Doc files now extract design rationale and architectural decisions too - not just structure, but why things were built that way.
Confidence scores on every edge
Every INFERRED edge now carries a confidence_score (0.0-1.0). EXTRACTED edges are always 1.0. INFERRED edges score 0.4-0.9 based on how certain the model was. AMBIGUOUS edges score 0.1-0.3. You know not just what was guessed but how confident.
Semantic similarity edges
Cross-file conceptual links with no structural connection. Two functions solving the same problem without calling each other, a class in code and a concept in a paper describing the same algorithm. Tagged semantically_similar_to with a confidence score.
Hyperedges
Group relationships connecting 3+ nodes that pairwise edges cannot express. All classes implementing a shared protocol, all functions in an auth flow, all concepts from a paper section forming one coherent idea. Stored in a top-level hyperedges array in graph.json.
Git hooks - post-checkout added
graphify hook install now installs both post-commit (existing) and post-checkout (new). The graph rebuilds automatically when you switch branches, not just when you commit.
Claude Code PreToolUse hook
graphify claude install now also writes a .claude/settings.json hook that fires before every Glob and Grep call. If a graphify knowledge graph exists, Claude is reminded to check it before searching raw files. Ensures the graph is actually used during research, not bypassed.
Obsidian output opt-in
Obsidian vault generation (--obsidian) is now opt-in. Default output is graph.html + graph.json + GRAPH_REPORT.md. Large repos were generating thousands of files by default.
Upgrade
pip install --upgrade graphifyy
graphify install
- Knowledge graph extraction with audit trail (EXTRACTED/INFERRED/AMBIGUOUS tagging)
- Leiden community detection with cohesion scores
- Obsidian/Wiki exports and GraphRAG-ready persistence
Full changelog
First stable release.
What's in v1
- Knowledge graph from any mix of code, papers, docs, and images
- Leiden community detection with cohesion scores
- God nodes and surprising connections ranked by composite score
- Honest audit trail: every edge tagged EXTRACTED, INFERRED, or AMBIGUOUS
- Interactive HTML visualization
- Obsidian vault export with graph.canvas
- Wiki export (--wiki): Wikipedia-style articles per community for agent navigation
- GraphRAG-ready graph.json persistent across sessions
- SHA256 cache: re-runs only process changed files
- --watch: auto-rebuilds graph on code changes without LLM
- git commit hook: graphify hook install for per-commit rebuilds
- MCP stdio server (--mcp)
- Neo4j export (--neo4j)
- SVG and GraphML export
Install
pip install graphifyy && graphify install
Then in Claude Code: /graphify .
Worked examples
Reproducible benchmarks with input files and real output in worked/:
- worked/httpx/ - 6-file Python library
- worked/mixed-corpus/ - code + paper
- worked/karpathy-repos/ - 52-file corpus, 71.5x token reduction
v2 plans
- Hypergraph support (hyper-edges connecting more than 2 nodes)
- Poincare ball embeddings for hierarchical corpora
- Deeper agentic workflow integration