Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
149 KiB
Changelog
Full release notes with details on each version: GitHub Releases
Unreleased
0.8.43 (2026-06-19)
- Feat: package manifests are now parsed deterministically into a dependency graph.
apm.yml,pyproject.toml,go.mod, andpom.xmleach yield ONE canonical package node per package (keyed by name) plusdepends_onedges, routed to the AST path so the LLM never sees them. Previouslyapm.ymlwas an LLM-handled document, so the same package got a different file-anchored id from its own manifest than from each dependent's dependency reference and split into duplicate nodes; a package referenced from N manifests is now a single hub node (#1377). - Feat: markdown links now become graph edges.
extract_markdownonly emitted heading nodes +containsedges and never parsed link syntax, so a doc full of[text](./other.md)links (e.g.index.md,table-of-contents.md) had no edges to what it links and never became a hub. Inline links, reference-style links, and[[wikilinks]]are resolved relative to the source file (external URLs / in-page anchors / images skipped) and emitted asreferencesedges, with targets resolved via the same node-id recipe so they merge onto the real doc node (#1376). - Security: bumped vulnerable dependencies to patched versions —
pypdf6.11.0→6.13.3 (CVE-2026-48155/48156),yt-dlp2026.3.17→2026.6.9,pyjwt2.12.1→2.13.0,cryptography48.0.0→49.0.0,python-multipart0.0.28→0.0.32 — with lower-bound floors for the direct deps (pypdf,yt-dlp) so installs get the patched versions (#1375; thanks @hypnwtykvmpr). - Fix: the semantic extract entry points (
extract_corpus_parallel,extract_files_direct) crashed withAttributeErrorwhen passedstrpaths instead ofpathlib.Path. Both now coercefiles = [Path(f) for f in files]at entry (#1386). - Fix: community labeling now recovers from a malformed-JSON batch by splitting it at the midpoint and retrying each half (mirroring the extract path), instead of logging-and-skipping it — which silently lost ~100 community names per failed batch on large graphs (#1280, #1278; thanks @CJdev232).
- Fix:
graphify hook installno longer creates a literal backslash-named junk directory and reports false success whencore.hooksPath(orgit rev-parse --git-path hooks) is a Windows-style path under WSL. Drive-letter / embedded-backslash hooks paths are now rejected with a clear error (#1385). - Refactor: node-ID normalization is unified into a single
graphify.idsmodule.extract._make_id,build._normalize_id,mcp_ingest._make_id, andsymbol_resolution._bash_make_idwere four hand-synced copies of the same NFKC/casefold recipe — the root of the recurring ghost-node bug class (#811/#550/#1033/#1104). All four now delegate to one implementation guarded by contract + hypothesis property tests (#1378; thanks @danielnguyenfinhub).
0.8.42 (2026-06-18)
- Fix: large text documents are no longer silently truncated during semantic extraction.
_read_filescapped every file at 20,000 characters, so a Markdown/text/rST document longer than that had everything past the cap dropped — the model never saw it, and the packer/adaptive-retry path couldn't recover ("packing can't shrink one big file"). Oversized splittable-text files are now sliced at heading/paragraph boundaries into units that each fit the cap and together cover the whole file; every slice reports its parent file assource_file, so the graph is not fragmented per-slice. A single slice that still overflows the model's output is bisected and retried. Code files and PDFs are never sliced (they keep whole-symbol / page handling). (#1369) - Fix:
/graphify --updateno longer deletes a changed file's freshly re-extracted nodes. The0.8.41root=fix (#1361) madebuild_merge's prune actually match relativesource_filevalues — which then matched the just-re-extracted nodes of changed files (still listed inprune_sources) and removed them, so an--updateon a changed file could wipe its nodes. The update runbook now prunes only genuinely deleted files; changed files are reconciled bybuild_merge's replace-on-re-extract (#1344). The full build also now passesroot=tobuild_from_json, and the extraction-specsource_fileis pinned to the verbatim path, so the full build and incremental updates never drift on node-key base. (#1366; thanks @RelywOo) - Fix: Java
recorddeclarations are now modeled as first-class type nodes (they shareclass_declaration's name/body/interfaces fields), andnew Foo(...)constructor calls now produce acallsedge to the constructed type. Previously a record appeared only as its file node (degree 0) with no incoming edges, and body-levelnewusages were dropped becauseobject_creation_expressionwasn't a recognized call type and its callee lives in thetypefield rather thanname. (#1373) - Security fix:
.graphifyignoreand.gitignoreare now merged per directory instead of.graphifyignoresilently replacing that directory's.gitignore. Previously, adding a.graphifyignore(e.g. to exclude media) disabled the dir's.gitignoreentirely, so a file excluded only by.gitignore— including neutrally-named secrets likeprod-dump.sqlorcustomer-data.jsonthat the sensitive-file heuristic doesn't catch — got indexed into the graph, whose artifacts embed file contents and are routinely committed..gitignoreis read first and.graphifyignorelast, so.graphifyignorepatterns (including!negations) still win on conflict; adding one can only ever exclude more, never re-include a.gitignore-excluded file. (#1363)
0.8.41 (2026-06-17)
- Fix: OpenAI-compatible backends (
ollama,openai,deepseek,kimi) now honour their configured16384output-token cap instead of silently falling back to8192. The dispatch read amax_completion_tokensconfig key that onlygeminidefines; the others setmax_tokens, so their advertised cap was dead and deep-mode JSON truncated mid-string (recovered by the adaptive bisect, but noisy and slower). The dispatch now reads either key, and theopenaiconfig gained an explicit cap.GRAPHIFY_MAX_OUTPUT_TOKENSstill overrides. (#1365) - Fix: fuzzy dedup no longer over-merges distinct nodes in three cases. (1) Numbered/versioned siblings whose embedded digit runs differ as zero-padding-insensitive multisets (
ADR 0011vsADR 0013,3.1 Product Goalsvs1.1 Product Goals,40%+ …vs<20% …) never merge. (2)rationale/documentnodes are file-anchored like code (#1205's reasoning): near-identical docstring/heading boilerplate in parallel files no longer collapses across files, while same-file duplicates still merge. (3) Cross-file labels that share a long prefix but diverge in a distinguishing token (testing-library jest-nativevsreact-native) are scored on plain Jaro instead of Jaro-Winkler, so the leading-prefix bonus can no longer fabricate a merge; genuine cross-file duplicates still clear the bar on Jaro alone, and same-file near-duplicates keep Jaro-Winkler. Guards are mirrored into the--dedup-llmambiguous-pair collection. (#1284 thanks @van4oza, #1243) - Fix: Swift cross-file class relationships expressed through member calls and constructors now resolve to the receiver's real definition. A per-file type table (built from property/parameter declarations and constructor inference) types the receiver of
recv.method()/Type.staticMethod()/Singleton.shared.method()/self.prop.method(), and property/field initializers (let vm = VM()) are now walked for constructor calls. Edges are emitted only when the receiver's type resolves to exactly one definition (preserving the #543/#1219 god-node guards) and are taggedINFERRED; the blanket member-call skip in the shared call pass is untouched (#1356). - Fix:
/graphify <path> --updatenow prunes stale nodes correctly. The update runbook calledbuild_merge(prune_sources=...)withoutroot=, so the absolute prune paths were never relativized to match the graph's relativesource_filevalues — nothing was pruned and changed/deleted files left ghost nodes that compounded on every incremental run. The shared skill fragment now passesroot(the nativegraphify updateCLI was already correct) (#1361). - Fix:
export obsidianno longer writes an empty 32-bytegraph.canvason a populated graph.to_canvasbuilt cards solely by iterating communities, so a graph with no community data (--no-clusterbuilds, or a missing analysis sidecar) produced the empty{"nodes": [], "edges": []}shell while the markdown notes rendered fine. It now falls back to one synthetic community covering every node (#1324). - Fix: edges missing a
source_filefield (occasionally emitted by the semantic/LLM extractor, whichbuildonly normalized when the field was already present) are now backfilled from the edge's endpoint nodes inbuild_from_jsonand the--no-clusterraw-write path, so they no longer reachgraph.jsonwithout a file reference or trip validation (#1279). - Fix: every platform's query skill now ships both the vocab/IDF query-expansion step and the inline NetworkX fallback. Previously the two capabilities were split across
cli.md/cli-inline.mdso no platform got both — Claude had the superior expansion but no CLI-down fallback, while all other platforms had the fallback but the weaker raw-question matcher. The two fragments are merged into one unifiedqueryreference (and stub) shipped to all hosts; thequery_variantenum and its coverage-audit exemption are removed (#1325; thanks @LeanderBlume). - Fix: cross-file Java
implements/inherits/importsedges no longer orphan onto bare "shadow" nodes when two packages define a same-named type. The referencing file'simportstatement now disambiguates by exact package (FQN) and re-points the edge to the real definition, dropping the orphan stub. Previously_rewire_unique_stub_nodescould only repair the globally-unique case, so same-named interfaces (common in large Java codebases —Handler,Service, interface+impl pairs) left the real definition isolated in its own community (#1318). - Fix: Swift imports of the same module from multiple files now collapse to a single shared
type=modulenode instead of N path-qualified duplicates. The import target is taggedtype=moduleand exempted from id-disambiguation, so reverse traversal ("what imports CoreKit?") works; the--no-clusterwriter also now dedupes nodes by id (and edges) to match the clusteredbuild_from_jsonpath. Builds on the v0.8.40 Swift-import fix (#1327, #1330; thanks @duncan-daydream).
0.8.40 (2026-06-16)
-
Feat: custom OpenAI- and Anthropic-compatible endpoints via
OPENAI_BASE_URL/OPENAI_MODELandANTHROPIC_BASE_URL/ANTHROPIC_MODEL. Point either backend at a self-hosted or proxy server (vLLM, llama.cpp, LM Studio, LiteLLM, gateways); defaults still resolve toapi.openai.com/api.anthropic.com, andGRAPHIFY_OPENAI_MODELkeeps precedence overOPENAI_MODEL. Wired through both the extraction path (_call_claude) and community labeling (#1273). -
Feat: PowerShell
.psm1modules are now indexed..psm1was absent fromCODE_EXTENSIONSand the extractor dispatch table, so modules — and their dependents — were silently missing from the graph; they parse cleanly with the existing PowerShell grammar (#1315). (.psd1manifests andImport-Module/ dot-source import edges remain a follow-up.) -
Fix: Swift
importedges are no longer silently dropped._import_swiftemitted an edge to a bare module id with no backing node, sobuild.pypruned 100% of Swift imports. The target module node is now synthesized (new opt-inLanguageConfig.synthesize_import_module_nodes) so the edge survives the build (#1327). -
Fix:
--no-clusterand incrementalgraphify updateno longer accumulate duplicate edges. These paths bypass the NetworkXDiGraphthat collapses parallel edges, so repeatedupdategrew the edge count every run and counts diverged across build modes. Edges are now deduped by(source, target, relation)before writing — deterministic and idempotent; the no-cluster rebuild log now reports the written (deduped) edge count instead of the raw pre-merge count (#1317). -
Perf:
save_manifestfile hashing parallelized with aThreadPoolExecutor(#1295). -
Perf:
_walk_js_treeconverted from a recursive generator to an iterative walk, reducing overhead on large JS/TS trees (#1294). -
Feat: JS/TS AST now extracts function symbols defined via
this.X = () => {}/this.X = function(){}(constructor-assigned methods),exports.X = fn/module.exports.X = fn,Foo.prototype.X = fn, class arrow/function fields (class C { onClick = (e) => {} }), andconst f = function(){}function expressions. Previously only top-levelfunctiondeclarations, top-levelconst x = () =>arrows, classes, and method shorthand were captured, so the majority of callable symbols in constructor-style and CommonJS codebases (DAOs, route handlers, services) never became nodes and could not be call-edge endpoints. Arbitraryobj.x = fnis deliberately not captured, preserving the #1077 phantom-god-node guard (#1322). -
Fix:
graphify query,graphify explain, and MCPquery_graph/get_nodenow show the human-readable community name (e.g. "FlashAttention Paper") instead of a blank or numeric ID after runningcluster-only.to_jsonnow acceptscommunity_labelsand embedscommunity_nameon each node; read paths fall back to the numericcommunityfield for backward compatibility with old graphs (#1305). -
Fix:
graphify-mcpandpython -m graphify.servenow accept--graph <path>as an alias for the positional argument, consistent with every other graphify subcommand. Previously--graphraised "unrecognized arguments" (#1304). -
CI: bandit (MEDIUM+ severity) and pip-audit security scans added as a non-blocking
security-scanjob. Both run withcontinue-on-error: trueso they never break CI — advisory signal only, with the intent to remove the gate once pre-existing findings are triaged. -
Docs: RFC for file-level node summaries added (
docs/node-summaries-rfc.md). Proposes inlinegraph.jsonattribute vs sidecar storage options with pros/cons, phased implementation plan, and open questions for maintainer decision. -
Fix: AST extraction no longer crashes on Windows machines with >61 logical cores.
ProcessPoolExecutoron Windows is hard-capped at 61 workers viaWaitForMultipleObjects; the clamp now applies to all three input paths (auto-compute,GRAPHIFY_MAX_WORKERS,--max-workers) (#1298). -
Fix: ghost-merge skips ambiguous
(basename, label)collisions where two AST nodes share the same key. When same-named symbols appear in same-named files across different directories (e.g. tworender()in twoindex.ts), the previous last-writer-wins produced an arbitrary canonical node and mis-pointed all edges. Ambiguous keys are now tracked and skipped (#1257). -
Fix: startup no longer crashes on unreadable
.graphify_versionfiles. On restricted-permission installs or network mounts,.exists()/.read_text()raisedPermissionErrorand crashed everygraphify query/explain/pathcall. All three FS probes now wrapped intry/except OSError: return(#1299). -
Fix:
prs.pyclaude-cli backend resolvesclaude.cmdon Windows. The_call_llmand_call_claude_cliextraction paths were already fixed;prs.pyhad the same bare["claude", ...]subprocess call that fails on Windows npm installs with WinError 2 (#1288).
0.8.39 (2026-06-12)
-
Perf: O(n²)→O(n) LSH neighbor lookup in
deduplicate_entities. The inner scannext(n for n in candidates if n["id"]==neighbor_id)was O(n) per neighbor; replaced with acandidates_by_iddict built once per pass. Also adds anorm_cacheto avoid re-normalising labels on every comparison. -
Fix:
graphify merge-chunkssummary now prints the node count instead of the raw list object.global_graph.pyprintedmerged['nodes'](the list) instead oflen(merged['nodes']). -
Fix: manifest data-loss on corrupt
~/.graphify/manifest.json. A parse error previously triggeredexcept Exception: pass, silently returning an empty manifest and overwriting the file — wiping all tracked repos. The corrupt file is now renamed to a timestamped.corrupt.<ts>backup with a stderr warning before starting fresh. -
Fix: tree-sitter grammar packages now have pinned upper-bound version ranges in
pyproject.toml. Grammar packages routinely break node-type and field APIs across minor bumps; ceilings prevent silent breakage on future upgrades. -
Feat: FalkorDB export backend.
graphify export falkordb --push redis://localhost:6379pushes the graph to a FalkorDB instance. Optional dep (uv tool install "graphifyy[falkordb]"); lazy import; idempotent (MERGE semantics); Cypher injection guarded. -
Fix:
affectedandgraphify querynow handle graph files that use"edges"as the top-level key instead of"links". Graphs produced by nativegraphify extracton some corpus layouts used"edges"; loading them inaffected.pyraisedKeyError: 'links'. Normalised using the same established pattern already in__main__.pyandserve.py. -
Fix: a single
!negation rule in.graphifyignoreno longer disables all directory pruning. Previously any negation pattern causedcollect_filesto descend every ignored directory to look for re-included files. Since gitignore semantics cannot rescue files beneath an excluded parent, this descent was always wasted — the per-file filter still excluded them. Pruning now proceeds unconditionally; only the final per-file_is_ignoredcheck is consulted for negation. -
Feat:
--modelflag added tographify label-communitiesandgraphify cluster-only. Routes throughgenerate_community_labels→label_communities→_call_llm; defaults toNone(keeps existing backend default). Also fixes a latent arg-parsing bug where--backend gemini(space-separated) was mis-parsed as the positional path argument. -
Docs: Persian (فارسی) README translation added (
docs/translations/README.fa-IR.md).
0.8.38 (2026-06-11)
- Fix: LLM-generated
callsedges now have correct direction. The extraction prompt previously never stated thatsource= caller andtarget= callee; the LLM systematically emitted callee→caller edges. An explicit direction rule was added to the prompt. Separately, ghost-node merge was extended to collapse LLM duplicate nodes (bare-stem IDs) onto AST canonical nodes (parent-qualified IDs) even when the LLM node carries asource_location— the old check only caughtsource_location=Noneghosts. Post-fix annotation:callsprecision 100% (n=6), overall INFERRED precision 94% (n=16). - Fix: default imports/exports now produce symbol-level edges. JS/TS symbol resolution only handled named imports, so a
export default class Fooimported asimport Foo from './foo'got just a file→fileimports_fromedge — the class node received no incoming symbol edge. On codebases that default-export most classes (NestJS services/helpers/models, etc.) this left those symbols looking like isolated leaf nodes and madegraphify affected "<Class>"/explainreport no callers. Default imports are now recorded withimported_name="default",export default <class|function|identifier>registers a"default"export, and the existing resolver wires theimportsedge (and resolves calls through the local binding, even when renamed). Anonymous defaults (export default class {}) remain file-level only. - Fix: tsconfig
pathsaliases now resolved relative tobaseUrl. Previously all@/*→src/*aliases were resolved from the config file's directory regardless ofbaseUrl, breaking path alias import resolution for NestJS, monorepo, and similar layouts that setbaseUrl: "./src". - Fix: ghost-merge skips ambiguous
(basename, label)keys where multiple AST nodes share the same pair. Previously the last-writer-wins pass silently mis-merged one of two same-named symbols in different files (e.g. tworenderfunctions across separate modules), re-pointing edges to the wrong canonical node. - Fix:
resolve_seednow matches bare query terms against callable-decorated node labels. A query for"render"failed to seed nodes whose label was stored as".render()"because the string comparison was exact. Bare names are now tried against stripped labels as a fallback after exact and prefix matches. - Fix: AST cache is now namespaced by graphify version. Stale AST cache entries from a previous release no longer silently produce wrong extraction output after an upgrade — each version writes to its own subdirectory under
graphify-out/cache/ast/<version>/. Semantic cache is deliberately unversioned (LLM calls are expensive to re-run). - Fix: global-graph edges are now rewired to deduplicated external nodes. When two repos shared an external dependency node (e.g. both reference
requests), one copy was pruned but edges still pointed to the removed node ID, creating dangling references. Edges are now remapped through the dedup remap table before insertion. - Fix: dedup pass 2 now picks the winner only from the verified
(node, neighbor)pair. The previous code unioned both normalised-label groups before calling_pick_winner, allowing an unrelated same-named node from a different file to be dragged into the merge and supplant the correct winner. - Fix: extraction cache is anchored at the
--outdirectory root instead of leaking agraphify-out/into the scanned project. Usinggraphify extract ./src --out /tmp/outpreviously wrote cache files into./src/graphify-out/cache/alongside source files. Cache now writes exclusively under the--outpath. - Fix:
collect_filesrewritten as a single prunedos.walkinstead of onerglobper extension. On large repos this eliminated ~85 redundant filesystem traversals; noise directories (node_modules,.git,__pycache__, etc.) are now pruned before descent, preventing those subtrees from being scanned at all. - Fix: frontmatter delimiter detection now requires a whole
---line (regex^---[ \t]*\r?$). Thematic break lines (----) and YAML documents that open with--- title: foowere incorrectly parsed as frontmatter delimiters, causing cache hash instability on Markdown files with those constructs. - Fix:
claude-clibackend now spawnsclaude.cmdon Windows headless installs.npm-installed Claude Code ships a.cmdshim on Windows;CreateProcesscannot run it without the explicit extension.shutil.which("claude.cmd")is now tried first on win32, mirroring the fix already applied to the extraction path.CREATE_NO_WINDOWflag added to both subprocess spawn sites to prevent console windows flashing during headless runs. - Fix:
claude-clibackend handles JSON-array envelope from Claude Code CLI ≥ 2.1. Older CLI versions returned a single JSON object; 2.1+ wraps the response in a streaming array of events. The envelope parser now accepts both shapes, preferring the last{"type":"result"}event from an array. - Feat: Cargo workspace dependency extraction.
graphify extract ./my-workspace --cargointrospectsCargo.tomlfiles across a Rust workspace and emitscrate:<name>nodes withcrate_depends_onedges for workspace-internal dependencies. Registry dependencies are excluded. Handles virtual workspaces, root-package workspaces, glob members, and{workspace = true}inherited deps. - Fix: SystemVerilog class-level extraction improved. Classes, interfaces, enums, parameters, and their inheritance/implementation relationships are now extracted correctly from
.sv/.svhfiles. Dartwith MyMixinclauses now emitmixes_inedges (was incorrectlyimplements), consistent with PHP and Scala. - Docs: README grammar count updated from 28 to 36, reflecting all currently supported tree-sitter language grammars.
0.8.37 (2026-06-10)
- Security: SSRF guard rewritten to eliminate thread-safety race. The global
socket.getaddrinfomonkey-patch is replaced with per-connection_SSRFGuardedHTTPConnection/_SSRFGuardedHTTPSConnectionsubclasses that resolve DNS once, validate the IP, and connect to that exact address — closing both the concurrent-thread race window and the underlying TOCTOU gap. No global state is mutated, so sibling threads (MCP server, PR triage pool) are unaffected. - Security: Prompt injection mitigation for LLM semantic extraction. Untrusted source file content is now wrapped in
<untrusted_source path="..." sha256="...">XML delimiters; jailbreak sentinel tokens (<|im_start|>,[INST],<<SYS>>, forged closing tags) are neutralised with a zero-width space; the extraction system prompt includes an explicit SECURITY block stating that content inside the wrapper is inert data. - Fix:
export obsidianandexport canvasno longer crash withKeyErrorwhen a community contains a node ID absent from the graph (stale community index, merge artifacts). Dangling members are silently skipped. - Fix:
--updateon macOS no longer re-extracts all Office files on every run.convert_office_file()now NFC-normalises the source path before hashing the sidecar filename, so NFD paths returned byos.walk(HFS+/APFS) produce the same sidecar as NFC-constructed paths. An early-return when the sidecar exists prevents mtime bumps causing spurious re-detection. - Fix: Data
.jsonfiles no longer explode into hundreds of orphan key-nodes. The JSON extractor now only processes config/manifest JSON (detected by filename —package.json,tsconfig.json,.eslintrc.json,deno.json, etc. — or by top-level keys such asdependencies,extends,$ref,compilerOptions). Data JSON (top-level arrays, generic key/value files) is skipped by the AST pass and left for the LLM semantic pass. - Fix: OpenAI-compatible backends no longer send
temperature=0to reasoning models._resolve_temperature()auto-detects o1/o3/o4 and gpt-5 series and omits temperature from the request. Override withGRAPHIFY_LLM_TEMPERATURE=<value>(ornoneto omit explicitly for any model). - Fix: EDR / corporate Windows hang eliminated.
datasketch(which transitively importsscipy→numpy.testing→platform.machine()subprocess at import time) is replaced by a self-contained pure-numpy MinHash/MinHashLSH implementation with byte-identical hash math. Removesdatasketchandscipyfrom the dependency tree. - Perf:
detect()ignore-pattern checks memoized per scan. Each ancestor directory is now evaluated once across all sibling files, eliminating ~42M redundantfnmatchcalls on large repos (~34% whole-run speedup on 2k-file corpora). - Fix:
dedup.pylabel-based merge passes now skip code nodes entirely. Distinct same-named symbols in different files (e.g. twoConfigclasses) were being merged by the exact-label and MinHash/LSH passes. Code nodes are now deduplicated by ID only, which is correct. - Feat:
GRAPHIFY_MAX_GRAPH_BYTESenv var to override the 512 MiBgraph.jsonsize cap. Accepts plain bytes,<N>MB, or<N>GB. The cap error message now cites this env var.graphify export htmlauto-falls back to the community-aggregation view when over cap instead of hard-failing. - Feat:
CLAUDE.mdtemplate now uses mandatory language for the graphify-first rule — "MANDATORY: Before using Read/Grep/Glob/Bash to explore the codebase, you MUST run graphify first" — and explicitly requires forwarding the rule to subagent prompts. PreToolUse hook message hardened to match. - CI: Release workflow added. Every GitHub release now ships
graphify-self-graph.tar.gzas a downloadable asset —graph.json+graph.html+GRAPH_REPORT.mdfrom running Graphify on its own source. Opengraph.htmllocally with no install required to see what Graphify produces.
0.8.36 (2026-06-08)
- Feat:
extra_bodyfield inproviders.jsonforwarded to OpenAI-compat calls at extraction and labeling. Lets vLLM/Qwen3/Llama endpoints pass model-specific request shapes (e.g.{"chat_template_kwargs": {"enable_thinking": false}}). Explicitextra_bodyalso bypasses Ollamanum_ctxauto-derive. Thanks to @EirikWolf (#1197). - Feat:
label_communitiesmulti-batch for 16k-context models. Chunks of 100 communities per call (configurablebatch_size=);max_communitiesdefaults toNone(label all); partial batch failures no longer drop the whole pass. Thanks to @EirikWolf (#1197). - Feat:
.slnxVisual Studio solution file support. Extractscontains(project references) andimports(build dependencies) edges from the modern XML solution format (VS 2022 17.13+). Thanks to @bakgaard (#1189). - Feat:
graphify-mcpconsole script. MCP stdio server now directly invocable asgraphify-mcpfromuv tool install/pipx. Thanks to @jr2804 (#1190). - Fix:
label_communitiestoken budget raised andGRAPHIFY_MAX_OUTPUT_TOKENSnow honoured. Hardcodedmin(40+16n, 4096)undershooted (~16 tok/community); raised tomin(64+24n, 8192)and wrapped in_resolve_max_tokens()(#1200). - Fix:
find_import_cyclesno longer hangs on large graphs.nx.simple_cycles()now receiveslength_bound=max_cycle_length, pruning during enumeration rather than post-filtering — drops from never-returns to ~0.1s on dense graphs (#1196). - Fix: fuzzy dedup no longer merges prefix-extension symbol pairs.
getActiveSession/getActiveSessions,parseConfig/parseConfigFileetc. scored ~98-99 JW and were auto-merged. A prefix-extension guard now prevents merge when one normalised label is a strict prefix of the other, in both Pass 2 and the LLM tiebreaker (#1201). - Fix:
_norm,_norm_label,_strip_diacriticsguard againstNonenode labels, preventingTypeErrorcrash on corpora with explicitnulllabel fields (#1194). Thanks to @freiit (#1195). - Fix: skill frontmatter
trigger:field removed from all 14 skill variants — not part of Agent Skills spec, flagged byagentskills validateCI (#1180).
0.8.35 (2026-06-07)
- Feat: CodeBuddy platform support.
graphify codebuddy installinstalls the graphify skill to~/.codebuddy/skills/graphify/SKILL.md, writes aCODEBUDDY.mdalways-on section, and registers Bash + Read|Glob PreToolUse hooks in.codebuddy/settings.jsonthat nudge the agent towardgraphify queryinstead of grepping raw files when a graph exists.graphify install --platform codebuddyandgraphify codebuddy uninstallalso supported. Thanks to @studyzy (#1136). - Fix:
graphify --updateno longer destructively collapses distinct same-named symbols across files. The skill's--updatemerge now passes re-extracted (changed) files toprune_sourcesalongside deleted files, so old nodes for changed files are pruned before fresh AST is inserted — no fuzzy reconciliation needed. Separately,dedup.pyPass 1 now skips nodes with an emptysource_fileso label-only merging across no-source-file nodes is prevented. The anti-shrink guard message now names fuzzy dedup as a possible cause rather than only blaming missing chunk files (#1178).
0.8.34 (2026-06-07)
- Feat: Streamable HTTP transport for the MCP server.
python -m graphify.serve graph.json --transport http --port 8080 --api-key $SECRETserves the graph over the MCP Streamable HTTP transport (spec 2025-03-26) so a single shared process can serve the whole team. Flags:--host,--port,--api-key(envGRAPHIFY_API_KEY),--path,--json-response,--stateless,--session-timeout. Docker image included. stdio remains the default (#1143). - Feat: Salesforce Apex extractor.
.clsand.triggerfiles are now AST-extracted via regex (no tree-sitter grammar exists for Apex). Extracts classes, interfaces, enums, methods, triggers, and SOQL/DML edges (#1159). - Feat: Azure OpenAI Service backend.
--backend azurereadsAZURE_OPENAI_API_KEY+AZURE_OPENAI_ENDPOINTand auto-detects both. Uses the existingopenaipackage — no new dependency (#1107). - Feat: live PostgreSQL introspection.
graphify extract --postgres "postgresql://..."connects directly to a running database and maps tables, views, routines, and FK relations viainformation_schemain aSERIALIZABLE READ ONLYtransaction. Newgraphify[postgres]extra (psycopg3). Credentials are sanitized from error messages (#1103). - Feat: vision and PDF support in headless extract. Images now route through per-backend vision payloads (base64/data-URI for claude/openai, file path for claude-cli, bytes for bedrock) instead of producing garbage binary data. Non-vision backends get a text reference via
_strip_pixels. PDFs reuse pypdf. 5MB cap, 20-image chunk limit (#1110). - Fix:
graphify updatenow prunes symbols removed from files that still exist on disk. Previously, deleting a function left a ghost node in the graph until the source file itself was deleted. Every AST node is now stamped with_origin="ast"; on a full rebuild any stamped node absent from the fresh output is dropped (#1118). - Fix:
graphify pathandshortest_pathnow fire the exact-match bonus for multi-word queries. The per-token comparison never equalled a full multi-word label, so the exact bonus was silently skipped for queries like"AuthService"when the label contained punctuation or spaces. The full normalized query is now compared alongside each token (#1165). - Fix:
_is_sensitiveno longer flags topic-mentioning filenames as secrets.token-economics-of-recall.mdandpassword-policy-discussion.mdwere silently dropped. Generic keywords (token/secret/password) now only fire when the keyword ends the filename stem or the stem is ≤2 words; specific patterns (.env,.pem,id_rsa, etc.) remain unconditional (#1169). - Fix: git hooks no longer use
nohupto background the rebuild. Git for Windows' MSYS shell has nonohup, causing the post-commit/post-checkout hook to fail silently and the graph to go stale. Replaced with a cross-platform Python launcher usingDETACHED_PROCESS | CREATE_NEW_PROCESS_GROUPon Windows andstart_new_session=Trueon POSIX (#1161 / #1170). - Fix: post-commit and post-checkout hooks now respect an existing
.graphify_root. A scoped build (graphify src/) was silently expanded to the full repo on the next commit because the hook hardcodedPath('.'). The hook body now readsgraphify-out/.graphify_rootfirst (#1173). - Fix:
graphify affectednow forces a directed graph on load, matching the identical fix already applied inserve.pyand__main__.py. On undirected graphs ("directed": falsein graph.json) the traversal was direction-blind — missing true callers and reporting callees as affected (#1174). - Fix: Step 9 skill cleanup no longer aborts under fish/zsh on pure-code corpora. The
rm -f ... .graphify_chunk_*.jsonglob errored with "no matches found" when no chunk files existed, leaving other temp files on disk. Split intorm -ffor fixed filenames andfind -maxdepth 1 -deletefor the chunk glob (#1172). - Fix:
detect_incrementalno longer crashes on schema-drifted manifest files. A dict-valuedmtimeentry (from an older richer schema) is now coerced toNoneand the file is treated as new rather than raising a comparison error (#1163). - Fix: numpy pinned to
>=2.0only on Python 3.13+ in thesvgandallextras. numpy 1.26.4 ships nocp313wheel souv syncfell back to a source build requiring a C compiler (#1153 / #1154). - Fix: Codex platform skill now installs to
.codex/skills/graphify/(was.agents/skills/graphify/), aligning with where the hook already lives (#1160).
0.8.33 (2026-06-06)
- Feat: FalkorDB export backend — sibling to Neo4j, selected via
graphify export falkordb [--push falkordb://localhost:6379]. FalkorDB is OpenCypher-compatible, so the MERGE/SET upsert queries match the Neo4j path; auth is optional and the target graph defaults tographify. Install withuv tool install "graphifyy[falkordb]"(#1175). - Feat: install banner —
graphify installnow prints an amber knowledge-graph brain in the terminal (TTY-only, silent in CI/pipes, never raises). - Fix: Python
from pkg import submodpackage-form imports now resolve to a file-levelimports_fromedge to the submodule file when it exists on disk. Previously these imports produced zero edges, leaving test files as disconnected islands in the graph (up to 66% of test nodes in some corpora). The fix lives in the symbol-resolution post-pass which has filesystem access (#1146). - Fix: builtin type-annotation nodes (
str,int,bool,float,bytes,MagicMock,Mock,AsyncMock, etc.) no longer appear as graph nodes or accumulate edges. They were being created via the annotation walker whenever used as parameter or return types, inflating degree counts ~25% and displacing real abstractions from god-node rankings. A new_PYTHON_ANNOTATION_NOISEfilter suppresses them at extraction time;god_nodesalso filters them as a defense for pre-existing graphs (#1147). - Fix: AST/semantic ghost-duplicate nodes are now auto-merged at build time. When AST and semantic extraction produce different IDs for the same symbol (one with
source_location=L<n>, one without),build_from_jsondetects the pair by(source_file basename, label)and collapses the semantic ghost into the AST node, re-pointing all edges. Graphs built before this release can be cleaned up withgraphify extract . --force(#1145).
0.8.32 (2026-06-05)
- Feat: Terraform/HCL support.
.tf,.tfvars, and.hclfiles are now AST-extracted viatree-sitter-hclinto a structured infrastructure dependency graph. Nodes: resources, data sources, modules, variables, outputs, providers, and locals. Edges:contains,references(interpolation), anddepends_on. Node IDs are directory-scoped for cross-file resolution. Requiresuv tool install "graphifyy[terraform]"(#1129). - Fix:
graphify extractno longer requires an LLM API key for code-only corpora. Backend resolution is now deferred until after file detection — a corpus with only code files (pure tree-sitter AST, zero LLM calls) runs fully offline. The key is only enforced when docs, PDFs, or images are present, or when--dedup-llmis passed (#1122). - Fix:
graphify kiro installnow correctly installs thereferences/sidecar and.graphify_versionstamp. The install was using a barewrite_textthat bypassed the shared helper, shippingSKILL.mdwith 8 deadreferences/*.mdpointers. Re-rungraphify kiro installto pick up the fix (#1142). - Fix:
GRAPHIFY_API_TIMEOUTnow applies toclaude-clisubprocess and Anthropic SDK backend, not just the HTTP client. Both subprocess paths previously hardcodedtimeout=600and ignored the env var and--api-timeoutflag (#1112). - Build: version floors added for
networkx>=3.4,datasketch>=1.6, andrapidfuzz>=3.0to prevent silent breakage from old installs resolving incompatible versions.
0.8.31 (2026-06-03)
- Fix:
graphify hook installnow embeds the current interpreter (sys.executable) directly into the generated hook scripts. Previously, uv tool and pipx installs silently no-oped on git commit in GUI clients and CI runners where~/.local/binis not on PATH — the hook could not find the graphify launcher, fell through all detection probes, and exited 0 without rebuilding. The embedded path is sanitized through a filesystem-safe allowlist before substitution. If you already have hooks installed, re-rungraphify hook installto pick up the fix (#1127). - Fix: hook scripts now also probe
graphify-out/.graphify_pythonas a fallback interpreter source, covering Windows/Git Bash installs where the launcher is a binary with no parseable shebang, and the case where the pinned path goes stale after a reinstall. - Security: hook script hardening — the
_PINNED=assignment uses single quotes to prevent shell injection from a path containing metacharacters;nohup "$GRAPHIFY_PYTHON" -cis properly quoted to handle spaces; the fallback emits a loud stderr diagnostic instead of a bare silentexit 0. - Feat: query logging. Every
graphify query,graphify path,graphify explain, and MCPquery_graphcall is now appended to~/.cache/graphify-queries.login JSON Lines format (timestamp, kind, question, corpus path, nodes returned, result size, duration). Full subgraph responses are not stored by default. Control withGRAPHIFY_QUERY_LOG(path override),GRAPHIFY_QUERY_LOG_DISABLE=1(opt out),GRAPHIFY_QUERY_LOG_RESPONSES=1(store full response text) (#1128).
0.8.30 (2026-06-03)
- Fix:
graphify install --project --platform antigravitynow writes Antigravity's always-on layer (.agents/rules/graphify.md+.agents/workflows/graphify.md), not just the skill. The project-scoped path went through the skill-only branch and skipped them, even though the project uninstall removes them. - Feat: close the Read-tool graph bypass. The
PreToolUsenudge previously only fired on Bash search (grep/rg/find); an agent answering a question by reading many source files through the nativeReadtool (orGlob) slipped past it. A newRead|Globhook nudges towardgraphify querywhengraphify-out/graph.jsonexists, only for a source/doc file outsidegraphify-out/, and never blocks (#1114). - Feat: add an
anthropicoptional extra (and include it in[all]) so theclaudebackend is installable like every other one:uv tool install "graphifyy[anthropic]". Previously it was the only backend with no extra, so a user withANTHROPIC_API_KEYset could not satisfy it without--with anthropic. The backend package-missing errors now point atuv tool install "graphifyy[<extra>]"(the isolated-venv path) rather than onlypip install.
0.8.29 (2026-06-02)
- Feat: progressive-disclosure skill files. The per-host
SKILL.mdis now a lean core (~615 lines, down from the ~1156-line monolith, about 47% less always-loaded context) that carries the full default code-build pipeline inline and links to an on-demandreferences/sidecar (extraction-spec, query, update, exports, transcribe, github-and-merge, add-watch, hooks); an agent reads a reference only when that path is actually taken, so a normal build needs none. 18 hosts go progressive (claude, codex, opencode, kilo, copilot, claw, droid, trae, trae-cn, hermes, kiro, pi, antigravity, antigravity-windows, windows, kimi, amp, gemini); aider and devin stay monolithic by design. All 15 skill bodies + sidecars are generated from one source undertools/skillgen/, with CI guards (--check,--audit-coverage,--monolith-roundtrip,--always-on-roundtrip) proving the references are byte-identical slices of the old monolith so nothing is lost (#1121). - Fix:
graphify install --platform geminishipped aSKILL.mdwith 8 deadreferences/pointers. gemini installs claude's lean progressive core but the installer never copied claude's references sidecar; it now does, so every on-demand reference resolves (regression from the progressive-disclosure split). - Security (F1): a project-local
./.graphify/providers.json(which travels with a cloned or shared repo) is no longer loaded automatically, since a custom provider'sbase_urlis where your corpus and API key are sent. SetGRAPHIFY_ALLOW_LOCAL_PROVIDERS=1to opt in; the user's own~/.graphify/providers.jsonis still trusted. Non-http(s)base_urls are rejected on load and onprovider add, and plaintext-http egress warns. Behavior change: if you relied on an auto-loaded project-local providers file, set the opt-in env var. - Security (F2): untrusted office/PDF files are screened before parsing (on-disk size cap, plus a bounded streaming-decompression ceiling for
.docx/.xlsxzip containers) so a zip-bomb in a scanned corpus can no longer exhaust memory. - Security (F3):
OLLAMA_BASE_URLpointing at a link-local or cloud-metadata address (169.254.x,metadata.google.*, or any host that resolves to one) now fails closed with a clean error instead of sending the corpus there. Trusted LAN hosts still warn-and-allow. - Security (F5): the Fortran C-preprocessor step passes an absolute path so an attacker-named corpus file cannot be interpreted as a
cppoption.
0.8.28 (2026-06-01)
- Feat: Kilo Code support —
graphify install --platform kiloinstalls a native skill (~/.config/kilo/skills/graphify/SKILL.md) and/graphifycommand, plus a.kilotool.execute.beforeplugin (mirroring the OpenCode integration). Existing.kilo/kilo.jsoncconfig is read but never rewritten — plugin registration goes tokilo.jsonso user comments are preserved (#512) - Feat: modernized Dart extractor — comment stripping,
part ofredirection, nested-generic-awareextends/with/implementsparsing, generic type-argument mapping, and generic call detection (#1098) - Fix:
uv tool install graphifyy/pip install graphifyyno longer fails to build on Linux/macOS —tree-sitter-dm(BYOND DreamMaker) ships only a Windows wheel, so on other platforms it compiled from source and aborted the entire install when a C toolchain orpython3-devheaders were missing. It is now an optional extra (graphifyy[dm], also in[all]) instead of a core dependency, so the default install needs no compiler (#1104).- Upgrade note: DreamMaker
.dm/.dmeusers must reinstall withgraphifyy[dm](or[all]) to keep AST extraction — onuv tool upgradethe now-optional grammar is removed..dmi/.dmm/.dmfparsing is unaffected (no tree-sitter dependency).
- Upgrade note: DreamMaker
- Fix: community IDs are now assigned by a total order (
(-size, sorted node IDs)) so an identical grouping always gets identical IDs across runs — previously the equal-sized small communities that dominate a sparse graph were numbered by the partitioner's (not seed-stable) enumeration order, making a per-node community diff report large spurious "churn" even though the actual grouping was reproducible (#1090 follow-up) - Fix:
graphify amp installnow writes the skill where Amp actually looks for it. It was landing in.amp/skills/graphify(project) and~/.amp/skills/graphify(user), neither of which Amp searches, so the skill never loaded. User-scope installs now go to~/.config/agents/skills/graphifyand project installs to.agents/skills/graphify, and a stale~/.amp/skills/graphifyfrom an older install is cleaned up on the next run.
0.8.27 (2026-05-31)
- Feat: standalone CLI now auto-names communities with the configured backend instead of leaving
Community Nplaceholders — community labeling was previously an agent-only step (skill.md Step 5), so bare-CLI runs never got semantic names;cluster-onlynow auto-labels when no.graphify_labels.jsonexists, newgraphify label <path>subcommand (re)generates names on demand,--no-labelopts out,--backend=<name>overrides auto-detection; one batched LLM call with per-community placeholder fallback and graceful degradation on missing backend/API error; works with all built-in and custom OpenAI-compatible backends (#1097) - Fix: AST file-level node IDs now match the skill.md
{parent_dir}_{stem}spec — they were derived from the full relative path plus extension (match_script_pipeline_step_py) while semantic subagents usescript_pipeline_step, splitting every file into two disconnected ghost nodes; fixed at the single relative-path remap chokepoint so file nodes and all import/dependency edge endpoints (Python, TS, Lua, C, bash) convert together (#1033) - Fix: symbol-level node IDs for root-level files now match the spec too — the #1033 remap relativized file nodes but symbols still embedded the absolute parent-dir name (
<rootdir>_main_runvs specmain_run), splitting every top-level file's symbols into AST/semantic ghost pairs; the remap now canonicalizes symbol stems andraw_callscaller IDs, gated bysource_file(#1096) - Fix: TypeScript
interface A extends Band same-fileclass X extends Ynow produceinherits/implementsedges — the walker only inspectedclass_heritage(missing the interfaceextends_type_clausenode) and the resolver only consulted the import table (missing same-file bases); both gaps closed (#1095) - Fix:
graphify export obsidianno longer crashes withOSError ENAMETOOLONGon long node labels —to_obsidian/to_canvasnow cap filenames on UTF-8 bytes (not chars, so multibyte/CJK labels are handled) with an 8-char hash suffix on truncation to keep distinct long-prefix labels from colliding; also fixes the previously-uncapped_COMMUNITY_notes (#1094) - Fix:
graph.jsonis now deterministic across runs —detect()sorts file traversal lexicographically (os.walkorder is filesystem-dependent), which had made first-writer-wins node-ID decisions and Leiden community counts vary between identical runs (#1090) - Fix: Windows consoles no longer crash with
UnicodeEncodeErroron non-UTF-8 code pages —main()reconfigures stdout/stderr to UTF-8 at startup and→/—in print statements replaced with ASCII (#992)
0.8.26 (2026-05-30)
- Feat:
find_import_cycles(G)inanalyze.pydetects file-level circular import dependencies — collapses symbol graph to file-level directed import graph, finds simple cycles via Johnson's algorithm, deduplicates rotations, renders## Import Cyclessection inGRAPH_REPORT.md(#961) - Feat: custom LLM provider registry —
graphify provider add/list/show/removeregisters any OpenAI-compatible endpoint (NVIDIA NIM, vLLM, OpenRouter, Together, LiteLLM) via~/.graphify/providers.json; custom providers auto-detected after built-ins indetect_backend()priority (#1084) - Fix:
extract_files_direct()no longer silently defaults to kimi (Moonshot AI) —backend=Nonenow callsdetect_backend()and raises a clearValueErrorif no key is configured, matching CLI behavior; README Privacy section updated with data-residency notes (#1086) - Fix:
pnpm-workspace.yamlwithpackages: - '.'no longer crashes withIndexError: tuple index out of rangeon Python 3.10 —Path.glob('.')replaced with[root]guard in_load_workspace_packages;GRAPHIFY_DEBUG=1env var added to_safe_extractfor full traceback on extraction errors (#1083) - Fix: anchored
.graphifyignorepatterns (leading/) no longer match the same directory name anywhere in the tree —_matches()in both_is_ignoredand_is_includednow gates basename/segment shortcuts onnot anchored; anchored patterns do exact anchor-relative path match only (#1087) - Docs: Filipino (fil-PH) README translation added (#1080)
0.8.25 (2026-05-29)
- Fix: JS/TS
const/letinside arrow-function callbacks no longer emit phantom god-nodes — scope guard restricts_js_extra_walknode emission to program-level declarations only; applies uniformly to JS, TS, and TSX (#1077) - Fix: fenced code blocks in Markdown no longer emit orphan
codeblock_Nnodes — they had onlycontainsedges and no semantic meaning; fence-toggle still prevents inner content from being mis-parsed as headings (#1077) - Fix: Lua
require("pkg.sub")now resolves to the correct file node ID — dots converted to path separators, probes filesystem for.lua/.luau/init.luavariants up the directory tree (#1075) - Fix: Windows
claude-clibackend no longer raisesWinError 2— prefersclaude.cmdover bareclaudeto avoid PATHEXT.ps1resolution failure (#1072) - Fix: post-commit hook no longer silently drops
changed_pathswhen another rebuild holds the lock — lock-losers queue paths to a pending file; the lock-holder drains and merges on acquire (#1059) - Fix:
graphify install antigravityglobal install now writes to~/.gemini/config/skills/(per Antigravity docs) instead of the wrong~/.agents/; uninstall, version-stamp refresh, and project-scope install all updated to match (#1079) - Docs: README warns against
pip installon Mac/Windows due to Python env mismatch causingModuleNotFoundError;uv tool installrecommended as primary method (#1074)
0.8.24 (2026-05-29)
- Feat: type-reference edges for ObjC, Julia, C, C++, Scala, Fortran, and PowerShell — extends cross-language semantic context work from #1015 to a second wave of languages; CI matrix now covers Python 3.10 with
faster-whisperversion guard (#1071) - Fix: claude-cli backend no longer loops on hollow streamed responses — handles all four documented failure modes (empty stream, no JSON, missing
result, emptyresult) with tests (#1063) - Fix:
callsedges no longer flip caller/callee when the same node pair appears in both directions in an undirected build — first-seen direction preserved on bidirectional collision (#1061) - Fix:
graphify-out/.graphify_pythonpath prefix was missing in 8 skill files (256 instances) causingcat: .graphify_python: No such file or directoryon every non-Claude-Code platform - Chore: all skill files now use uv-aware interpreter detection —
uv tool run graphifyy pythonpreferred over shebang parsing when uv is available
0.8.23 (2026-05-28)
- Feat: type-reference edges for Swift, Kotlin, PHP, Rust, and Go —
referencesedges withparameter_type,return_type,generic_arg,field, andattributecontexts; inheritance split intoinherits(superclass) vsimplements(protocol/interface/trait) for all five languages (#1015) - Chore: CI switched from pip to uv (
astral-sh/setup-uv,uv sync,uv run pytest);uv.lockcommitted for reproducible installs; dev setup docs updated (#885)
0.8.22 (2026-05-28)
- Feat: BYOND DreamMaker support —
.dm/.dmefiles extracted via tree-sitter-dm (type definitions, proc declarations,#includeedges, in-file call resolution,new /type()instantiation edges);.dmiPNG icon files parsed for icon-state nodes;.dmmmap files parsed for type-pathusesedges from the tile dictionary section;.dmfinterface files parsed for window/elem/control-type hierarchy (#884) - Feat:
graphify extract --mode deepflag enables richer semantic extraction using an extended system prompt; flag propagated through all four LLM backends (#1030)
0.8.21 (2026-05-27)
- Fix:
graphify update(no--changedflag) no longer leaves ghost nodes from files deleted between runs — full re-extraction path now reconciles the existing graph against current disk state and evicts any node whosesource_fileno longer exists;_norm_source_fileused on both sides to guarantee path format consistency (#1007) - Fix:
graphify install --platform opencode --projectnow writesSKILL.mdto.opencode/skills/graphify/SKILL.md(discoverable by OpenCode) instead of the incorrect.config/opencode/skills/path; git-add hint updated accordingly (#1040) - Fix: post-commit hook no longer triggers rebuild when only
graphify-out/files were committed (avoids infinite dirty-tree loop when graph outputs are tracked in git);GRAPHIFY_SKIP_HOOK=1env var added for one-off skip; hook rebuild log now appends (>>) instead of overwriting (>) (#1018, #1037) - Fix: graph output is now byte-for-byte deterministic across runs — edges sorted by
(source, target, relation)inbuild_from_json;PYTHONHASHSEED=0exported in hook scripts to stabilize Louvain community ordering (#1010) - Feat: Amp (ampcode.com) platform support —
graphify amp install/uninstallinstalls the skill into.amp/skills/graphify/SKILL.md(#948) - Fix: query punctuation no longer breaks node matching —
"what calls extract?"correctly finds theextractnode;_search_tokenshelper strips punctuation from search terms in_query_terms,_score_nodes, and_find_node(#994, #978) - Fix: language built-in globals (
String,Number,Boolean,Object,Array, etc.) no longer accumulate spurious call edges — filtered at same-file and cross-file resolution in the AST extractor, eliminating god-node pollution from constructor-style calls (#916, #726) - Feat: SystemVerilog header files (
.svh) now extracted using the Verilog parser alongside.vand.sv(#1042) - Fix:
@property,@staticmethod,@classmethodmethods no longer produce orphaned nodes without a class-qualified ID —decorated_definitionis now treated as a transparent wrapper in the Python AST walker, preservingparent_class_nidthrough the decorator layer (#1050) - Fix: Pass 2 dedup no longer merges nodes with identical labels that live in different files — same-file partition enforced for the identical-label subcase so
foo()ina.pyandfoo()inb.pyare not collapsed into one node (#1046) - Fix:
graphify-out/memory/files are no longer silently excluded by.gitignorepattern matching — memory dir files now bypass the gitignore filter indetect.py, ensuring knowledge accumulated viagraphify rememberis always scanned (#1047)
0.8.20 (2026-05-26)
- Fix: stale nodes persist after
graphify updatewhen files are deleted on Windows —deleted_pathsandevict_sourcesin_rebuild_codenow use.as_posix()for consistent forward-slash paths;_relativize_source_filescalled on the existing graph before eviction (not after);_relativize_source_filesitself now produces forward slashes (#1007) - Fix:
graphify extractstale-node pruning now also handles symlinked scan roots —prune_setexpansion usesPath(root).resolve()beforerelative_to()so symlinked roots produce correct relative paths (#1007) - Feat: MCP config extractor —
.mcp.json,mcp.json,mcp_servers.json,claude_desktop_config.jsonnow extracted into the knowledge graph; captures server nodes, npm/pip package refs, env var requirements; env values discarded to prevent secret leakage (#1034) - Fix:
cluster-onlyno longer drops community label alignment after re-clustering —remap_communities_to_previousnow applied in thecluster-onlypath, matching the behaviour ofgraphify update(#1028) - Fix: Dart child node IDs no longer embed absolute paths — switched from
_make_id(str(path), name)to_make_id(_file_stem(path), name), consistent with all other extractors; existing Dart graphs should be rebuilt with--force(#999) - Security: XML parsing in
extract_csprojandextract_lazarus_packagenow pre-screens for<!DOCTYPE/<!ENTITYdeclarations before callingET.fromstring, blocking billion-laughs DoS on malicious project files;extract_lpkalso gains the missing 2 MiB size cap
0.8.19 (2026-05-26)
- Feat: .NET project file support —
.sln,.csproj,.fsproj,.vbproj,.razor,.cshtmlnow extracted; captures NuGet package refs, project-to-project dependencies, target frameworks, SDK attributes, Blazor/Razor directives (@using,@inject,@inherits,@model,@page), component refs, and@codeblock methods (#1025) - Feat: Chinese query segmentation — compound Chinese tokens (e.g.
页面路由) are split into meaningful words using jieba when installed, with character bigram fallback; original compound preserved alongside segments for exact-match; newpip install "graphifyy[chinese]"extra (#1026) - Fix: Wiki TypeError when
source_fileisNone—G.nodes[n].get("source_file") or ""replaces.get("source_file", ""), which did not handle explicitNonevalues (#1016) - Fix: Nested
.claude/worktrees/no longer indexed —_is_noise_dirnow accepts an optionalparentparam and skipsworktrees/directories nested inside dotted dirs like.claude/(#1023) - Fix:
backup_if_protectedno longer accumulates one folder per run — uses content-hash comparison to skip identical backups and overwrite in-place when content changes; one folder per day maximum - Feat: Devin CLI support —
graphify devin install/uninstallinstalls the skill into Devin's.devin/rules/directory (#1020) - Fix: TypeScript 5.0 array-form
extendsintsconfig.jsonnow handled —_read_tsconfig_aliasesnormalizesextendsto a list before iteration (#1017)
0.8.18 (2026-05-24)
- Fix: post-commit hook now updates graph after delete-only commits — shrink-guard is bypassed when
changed_pathscontains explicit deletions, preventing stale nodes from accumulating indefinitely (#1000) - Fix:
graphify export(html/obsidian/wiki/svg/graphml/neo4j) no longer collapses to "Single community" when.graphify_analysis.jsonis absent — falls back to per-nodecommunityattribute already present ingraph.json(#1001) - Fix: Ukrainian README translation updated to v8 — all new sections, correct badges, 31 languages (#995)
- Feat: semantic context tags on
referencesedges for Python/JS/TS/C#/Java —parameter_type,return_type,generic_arg,attribute,field; C#/Java splitinherits/implements; dedup key now includes context (#996)- Breaking: Java
extendsedges are now emitted asinherits— queries filtering onrelation="extends"for Java nodes must be updated torelation="inherits"
- Breaking: Java
- Feat: constrained query expansion in skill — Step 0 extracts actual graph vocab and forces LLM to pick expansion tokens only from that set, preventing hallucinated expansions; Unicode regex fix captures Cyrillic/CJK labels (#998)
- Docs: Ukrainian README updated to v8 with all new sections, correct badges, YC badge, 31 language count (#995)
0.8.17 (2026-05-23)
- Fix: Case-sensitive call resolution for Go, Rust, and Elixir — resolvers previously lowercased both the label index and the callee name, causing
Authorizeto matchauthorizeand produce phantom edges; Ruby/C#/Java/Kotlin/Scala/PHP use the same generic resolver which now splits into case-sensitive (all languages) and case-insensitive (PHP only, where function/class names are genuinely case-insensitive) dicts (#993) - Fix: Cross-language phantom
callsedges from semantic extraction dropped at graph-build time — INFERREDcallsedges whose source and target nodes belong to different language families (py/js/go/rs/jvm/c/cpp/rb/php/cs/swift/lua) are now discarded; skill.md prompt updated with an explicit anti-rule (#991)
0.8.16 (2026-05-22)
- Fix: CJK/Unicode labels no longer silently stripped during dedup —
_norm()and_norm_label()now use Unicode-aware[\W_]+regex withcasefold()and NFKC normalization; previously道具処理クラスand any non-ASCII label collapsed to empty string and got falsely merged (#937) - Fix:
.ets(ArkTS/HarmonyOS) files now recognized as code and extracted via the TypeScript parser (#926) - Fix:
graphifynow exits non-zero when all semantic-extraction chunks fail — previously a silent empty graph was written with exit code 0, masking backend failures (#889) - Feat:
graphify install --projectinstalls the skill into the current repository (.claude/skills/,.agents/skills/, etc.) instead of the user home directory; per-platform subcommands support the same flag (#931) - Docs: Uzbek (uz-UZ) README translation (#982)
0.8.15 (2026-05-22)
- Fix:
cluster-onlysubcommand crashed withFileNotFoundErrorwhengraphify-out/did not yet exist — output directory is now created before any write (#934) - Fix:
GRAPHIFY_MAX_OUTPUT_TOKENSenv var now respected for all OpenAI-compatible backends — previously the token limit was hardcoded, causing truncated responses on high-context queries (#973) - Fix: Swift extension nodes no longer duplicated across files —
_merge_swift_extensionsdeduplicates by canonical name before graph insertion (#969) - Fix: Non-Latin query terms (CJK, Arabic, Cyrillic, etc.) now preserved through query preprocessing — previous normalization stripped non-ASCII chars, making multi-lingual codebases unsearchable (#964)
- Feat: Multigraph runtime compatibility probe — emits a warning if a
MultiDiGraphis passed where aGraphis expected by any downstream consumer (analyze, cluster, wiki, export, report) (#956) - Feat: JS/TS barrel re-exports tracked as explicit
re_exportsgraph edges —export { X } from './mod'emits typed edges withcontext="re-export"andconfidence=EXTRACTED; file-levelimports_fromedges also emitted (#960) - Feat:
--affectedand--import-resolutionflags for thev8subcommand — impact analysis and cross-file import resolution exposed as first-class CLI options
0.8.14 (2026-05-20)
- Fix:
--wikicrash when community node IDs are stale after dedup or re-extract — stale IDs are now silently dropped with a stderr warning; raises a clear error only if every ID is stale (#936) - Fix:
.gitignorepatterns now respected when no.graphifyignoreexists — previous behaviour silently ignored the project's gitignore, causing expected exclusions to be skipped (#945) - Feat:
--exclude <pattern>CLI flag to pass extra gitignore-style exclusion patterns at runtime without modifying.graphifyignore(#947) - Fix:
.worktrees/directory now skipped during scan — git worktree sibling checkouts inside.worktrees/were previously indexed as duplicate source (#947) - Security: NAT64 IPv6 addresses (
64:ff9b::/96) no longer false-positive as blocked reserved IPs — affects hosts likearxiv.orgon IPv6-only networks where the ISP uses RFC 6052 NAT64
0.8.13 (2026-05-18)
- Fix: node ID collisions across same-named files in different directories — SQL extractor and Python import resolver now use directory-qualified stems (
dir_file_entity) instead of bare filename stems, preventing silent node merging on repos with duplicate filenames (#1A, #1B) - Perf: stat-based mtime fastpath for
file_hash— skips full SHA256 read when file size+mtime_ns unchanged, same trade-off as make; index flushed atomically via atexit - Fix: absolute
source_filepaths from semantic subagents no longer stored in graph —build_from_json,build, andbuild_mergeaccept arootparam and relativize paths at build time (#932) - Fix: failed semantic chunks no longer permanently freeze their files in the manifest — only files that appear in extraction output get
semantic_hashstamped; failed-chunk files keep emptysemantic_hashand are re-queued on next run (#933) - Feat:
graphify cache-check,graphify merge-chunks,graphify merge-semanticCLI subcommands expose cache and merge logic as library-callable commands for skill pipelines
0.8.12 (2026-05-18)
- Security:
_is_sensitivenow correctly flags underscore-prefixed secret filenames (api_token.txt,oauth_token.json) —\bword boundary was treating_as a word char, so names likeapi_tokennever matched (#920) - Security:
_is_sensitivenow checks parent directories against a_SENSITIVE_DIRSblocklist (.ssh,.aws,.gcloud,secrets, etc.) so any file inside those dirs is skipped regardless of name; root-level files namedcredentialsorsecretsare no longer falsely flagged (#920) - Fix:
--wikiRelationships section was always empty —_cross_community_linksreadcommunityfrom node attributes (always None) instead of thecommunitiesdict;_god_node_articlehad the same bug and never linked to the owning community (#925) - Fix:
--watchnow respects.graphifyignore— the event handler was checking extensions before the ignore filter, so paths insidenode_modules/,.venv/, etc. triggered rebuilds (#928) - Fix:
graphify <path>now correctly dispatches tographify extract <path>— previously a bare path argument returned "unknown command" instead of starting extraction - Fix: skill fast path — if
graphify-out/graph.jsonalready exists and the request is a natural-language question, extraction steps are skipped entirely andgraphify queryruns immediately; previously the skill re-ran detect and hit the corpus-size gate on every question - Fix: large-corpus gate raised from 200 to 500 files;
detect()now returnsscan_rootso the skill correctly computes relative subdirectory breakdowns instead of showing absolute paths; flat repos with no subdirectories no longer ask the user to pick a subfolder that doesn't exist - Docs: clarify that code-only corpora skip the LLM semantic extraction pass entirely — AST handles code, Pass 3 is reserved for docs, papers, images, and transcripts (#836)
0.8.11 (2026-05-18)
- Fix: LLM empty choices / None message guard — Gemini and other providers return
choices=[]on content-filtered HTTP 200 responses; now raises a clean error instead of crashing with IndexError (#924) - Fix: OpenCode skill removed invalid
general-purposeagent reference and headless-incompatible interactive halt (#911, closes #825) - Fix: Codex skill now uses graphify query/explain/path even when graph artifacts are dirty in worktree (#913, closes #860)
- Perf: precompute degrees once in surprise scoring — ~11x speedup per lookup on large graphs (#914)
0.8.10 (2026-05-17)
- Fix: git hooks phantom directory on git < 2.31 — drop
--path-format=absolute, validate path contains no newlines, anchor relative paths on repo root (#907) - Fix:
save_manifestincremental data loss — seed from existing manifest before loop so untouched files aren't erased on partial runs (#917) - Fix: C++ class/struct inheritance edges missing — extract
base_class_clauseforclass_specifierandstruct_specifier(#915) - Fix: cohesion split threshold unreachable due to rounding —
cohesion_scorenow returns raw float, display rounds to 2dp (#919) - Fix: Rust cross-crate spurious INFERRED edges — skip
Type::method()scoped calls and common trait-method names from cross-file resolver (#908) - Feat:
--resolution Nforextractandcluster-only— control Leiden/Louvain community granularity (>1 = more smaller, <1 = fewer larger) (#919) - Feat:
--exclude-hubs Pforextractandcluster-only— exclude degree-percentile super-hubs from partitioning, reattach by majority-vote neighbour community (#919)
0.8.9 (2026-05-17)
- Feat: DeepSeek backend support — set
DEEPSEEK_API_KEYand use--backend deepseek; default modeldeepseek-v4-flash
0.8.8 (2026-05-16)
- Feat:
graphify prs— graph-aware PR dashboard: CI state, review decision, worktree mapping, and graph blast radius per PR;--triageranks your queue via any configured LLM backend (claude, kimi, openai, gemini, claude-cli, ollama — auto-detected);--conflictsshows PRs sharing graph communities with node labels;--worktreesmaps worktree paths to branches to open PRs; MCP toolslist_prs,get_pr_impact,triage_prsfor agent access
0.8.7 (2026-05-16)
- Fix: query seed selection now uses IDF weighting — common terms like
errororhandlethat match dozens of nodes are down-weighted so a rare identifier likeFooBarServiceranks first and BFS expands from the right node (#897) - Fix: seed count is now dynamic — a dominant match (score gap >80% vs next candidate) gets one seed rather than always picking three, preventing noise nodes from consuming BFS slots alongside the target (#897)
- Fix: truncation message in
query_graphnow tells Claude what to do (callget_nodeor add acontext_filter) rather than just saying "truncated" (#897) - Fix: C++ class data members (
int x;,static const int MAX = 100;) now extracted as nodes withdefinesedges from the parent class — previously the field_declaration branch was a no-op due to a wrong child type guard (#898) - Fix: dedup Pass 1 now partitions same-label groups by source_file before merging — nodes with generic labels (
handle,init,run) from different files no longer collapse into artificial god nodes; cross-file matches are routed to Pass 2 fuzzy (#895) - Fix: C/C++
#include "path/to/file.h"edges now resolve the include path relative to the including file and use the full resolved path as the target node ID, matching what extraction creates for the included file — previously all include edges dangled with a basename-only ID (#899) - Fix:
exact_mergescounter in dedup now reports only merges actually performed rather than counting all same-label nodes across files (#895)
0.8.6 (2026-05-16)
- Fix: cross-language INFERRED
calls/usesedges (e.g. Python → TypeScript) are suppressed in Surprising Connections — label-matching across language boundaries in monorepos is resolver pollution, not structural insight; all structural bonuses zeroed for these edges - Fix: code-to-doc INFERRED
calls/usesedges suppressed in Surprising Connections — the LLM seeing a symbol name in a README and emitting acallsedge is documentation cross-reference noise, not a real architectural connection (#890) - Fix: generic JSON key nodes (
name,id,type,start,end,key,value,data,items,title,description,version,properties) filtered from god_nodes — their degree is positional (every sibling record in the same JSON file references them), not architectural (#890) - Fix: Alembic migrations, Django migrations, and protobuf-generated files now have their module-level docstrings suppressed from rationale extraction — these are boilerplate headers, not design intent; function docstrings inside migration files are still captured
- Feat:
--follow-symlinksis now auto-detected — if symlinked children are present in the target directory, follow-symlinks is enabled automatically without requiring an explicit flag (#887) - Fix: install guidance now directs users to run
/graphify queryinteractively rather than readingGRAPH_REPORT.mdfirst; the report is a summary, not a starting point (#891)
0.8.5 (2026-05-15)
- Fix:
.graphifyignoreparent-exclusion rule now correctly blocks files under an excluded directory even when a!negation exists elsewhere in the file — previously any negation pattern disabled directory pruning entirely (#882) - Fix: dedup no longer false-merges chip/model SKU variants like
ASR1603/ASR1605orM1/M1 Pro— Jaro-Winkler prefix bonus is now gated by_is_variant_pairand_short_label_blockedguards; real typos on short labels still merge (#878) - Docs: added
worked/rsl-siege-manager/— case study on a real-world Python + TypeScript monorepo (FastAPI backend, React/Vite frontend, Discord bot); covers god node behaviour with tests included, cross-language INFERRED edges, community cohesion, and Alembic migration noise (#881)
0.8.4 (2026-05-15)
- Feat: Firebird SQL — trigger and stored procedure extraction via
CREATE TRIGGERand regex fallback; FK detection via global regex coveringREFERENCESandFOREIGN KEYclauses (#875) - Fix: SQL extraction regex fallback now decodes source as UTF-8 instead of latin-1, preventing non-ASCII identifier hash mismatches (#875)
- Fix:
--updatedeletion pruning now matches on full source file paths instead of basenames, preventing false node removal when different directories contain files with the same name (#876) - Fix:
--updatenow also prunes edges whosesource_fileattr points to deleted files, not just nodes (#876) - Fix: community label keys from
graph.json(stored as strings) are now coerced to int before lookup, fixing blank community names in GRAPH_REPORT.md and graph.html (#877)
0.8.3 (2026-05-15)
- Fix: Windows skill temp files (chunk JSONs,
.graphify_python,.graphify_root) no longer pollute the project root — all written undergraphify-out/(#831) - Fix:
--updatewith deletions-only no longer errors when.graphify_extract.jsondoes not yet exist — creates an empty extraction file before merging (#876)
0.8.2 (2026-05-15)
- Fix: Python interpreter detection for
uv toolandpipxinstalls on Windows —graphify installand all skill steps now find the correct executable (#831) - Fix: antigravity Windows skill path resolution (#831)
- Fix: dot directories (e.g.
.github/,.vscode/) are now indexed when explicitly included via.graphifyignore(#873) - Fix: MCP server hot-reloads the graph when
graph.jsonchanges on disk (#874)
0.8.1 (2026-05-15)
- Feat: Bash extractor —
.shand.bashfiles now indexed via tree-sitter; extracts functions, cross-function calls,source/.imports resolved to real file paths, andexport/declarevariable declarations (#866) - Feat: JSON extractor —
.jsonfiles now indexed via tree-sitter; extracts key/valuecontainstree,dependencies/devDependenciesblocks asimportsedges,extendsedges (tsconfig, eslintrc), and$refreferences (#866) - Feat:
.sh,.bash,.jsonadded toCODE_EXTENSIONSindetect.pyso files are picked up during corpus scan (#866) - Feat: Mermaid callflow HTML auto-regenerates on every graph rebuild when
*-callflow.htmlexists ingraphify-out/— works with--watchandgraphify hook install - Fix:
coverage/,lcov-report/,visual-tests/,visual-test/,__snapshots__/,snapshots/,storybook-static/,dist-protected/added to_SKIP_DIRS— generated artefact dirs no longer appear in the corpus (#869, #870) - Fix:
graphify hook installnow works in git linked worktrees — usesgit rev-parse --git-path hooksinstead of constructing.git/hooks/directly (#865) - Fix: office sidecar files in
graphify-out/converted/are now checked against.graphifyignorebefore being added to the file list (#861) - Fix:
save_manifest()accepts akindparameter (ast,semantic,both) — incremental AST-onlygraphify updateno longer overwritessemantic_hashentries, preventing spurious full re-extracts on the next run (#857) - Fix: five paths in
skill-windows.mdStep B3 were missing thegraphify-out/prefix, causing chunk files to be written to the wrong directory (#862)
0.7.19 (2026-05-14)
- Feat:
.astrofiles now extracted as code — frontmatter static imports, dynamic imports, and<script>block imports all produce edges; tsconfig path aliases resolved (#850, PR #852) - Fix:
.rebuild.lockno longer accumulates PIDs across rebuilds — now contains a single owning PID while running and is unlinked on release so downstream tooling polling for its absence unblocks promptly (#858, PR #859) - Docs: skill.md now clarifies that graphify does not read
ANTHROPIC_API_KEYor other provider keys during/graphifyskill runs — the host IDE session provides the LLM (PR #864)
0.7.18 (2026-05-14)
- Fix:
graphify updateis now idempotent — graph.json and GRAPH_REPORT.md are only rewritten when content actually changes; topology comparison short-circuits clustering entirely on unchanged graphs, eliminating residual community-count drift (#824) - Fix: community IDs are now stable across rebuilds — Leiden/Louvain receive deterministically sorted input and a fixed random seed; greedy overlap remapper preserves existing IDs so hand-edited
.graphify_labels.jsonlabels don't drift onto wrong communities (#824) - Fix:
--no-clusterflag added tographify update— writes raw AST graph without clustering, consistent withgraphify extract --no-cluster(#824) - Fix:
graphify update --no-clusternow writes"links"key matching the schema of the full clustered path; previously wrote"edges", causing schema toggle on every mode switch - Fix:
.graphify_labels.jsonwas rewritten on every rebuild even when nothing changed; now only written when outputs actually change - Fix: shrink-check (refuse overwrite when new graph has fewer nodes) was duplicated across two code paths; unified into a single
_check_shrink()helper - Fix: node ID format in skill.md corrected to
{parent_dir}_{filename_stem}_{entity}— the old filename-only format caused ghost-duplicate nodes when AST and semantic extractors disagreed on the stem; top-level files use just the filename stem; existing graphs with ghost duplicates can be cleaned up withgraphify extract --force - Fix: safer JSON serialization in clustering sort keys (
default=str) prevents crashes when edge attributes contain non-serializable values - Docs: added Prerequisites, optional extras table, environment variables reference, troubleshooting, and dev setup to README (#833)
0.7.17 (2026-05-13)
- Fix:
graphify pathandgraphify explainnow render arrow direction correctly —-->for caller→callee,<--for callee←caller; previously the graph was loaded undirected so every hop printed-->regardless of stored direction (#849, #853) - Fix: MCP
shortest_pathandget_neighborstools had the same reversed-arrow bug; now fixed inserve.pyalongside the CLI commands (#849, #853) - Fix:
graphify extract --backend bedrockwas rejected by the CLI guard even whenAWS_PROFILE/AWS_REGION/AWS_DEFAULT_REGION/AWS_ACCESS_KEY_IDwere set — boto3 session auth was never reached (#846) - Fix: BFS/DFS query traversal now skips expanding high-degree hub nodes (threshold:
max(50, p99_degree)) as transit — hubs can still be destinations but no longer produce semantically meaningless 2-hop paths likeClassA → View → ClassBin Android/Spring corpora (#830) - Fix:
--updatemanifest shrink — after an incremental run,manifest.jsonwas overwritten with only the changed-file subset, causing the next--updateto re-flag the entire unchanged corpus as new; Step 9 now persists the full corpus viaall_filesfallback (#837) - Fix:
file_typeenum aligned acrossskill.mdandllm.py(both now enumerate all six values:code,document,paper,image,rationale,concept); synonym mapper inbuild.pysilently coerces known LLM-emitted synonyms (pattern→concept,markdown→document,tool→code, etc.) before validation (#840) - Fix: Fortran test fixture renamed
sample.F90→sample_preprocessed.F90to avoid case-collision withsample.f90on macOS case-insensitive filesystems (credit: @FatahChan, #823)
0.7.16 (2026-05-12)
- Fix: all
read_text()/write_text()calls inskill.mdandskill-windows.mdnow specifyencoding="utf-8"— bare calls defaulted to the system codepage on Chinese-locale Windows, silently mojibaking node labels and Markdown content on--update(#832) - Fix:
json.dumpsin skill pipeline now usesensure_ascii=Falseso Chinese/CJK characters are stored as-is rather than\uXXXXescaped (#832) - Fix: Step 1 install fallback in skill now prefers
uv tool install --upgrade graphifyyoverpipwhen uv is on PATH — pip was installing to the wrong environment when graphify was originally installed viauv tool(#831) - Fix:
_score_nodesinserve.pynow uses three-tier precedence (exact 1000 / prefix 100 / substring 1) instead of flat substring scoring —graphify path "Foo" "FooBar"no longer returns 0 hops when both labels substring-match the same node (#828) - Fix:
graphify pathand MCP_tool_shortest_pathnow emit a clear error when source and target resolve to the same node, instead of silently returning 0 hops (#828) - Fix:
file_hashincache.pynow normalises path keys via.as_posix().lower()— Windows junction/case variants of the same file now hash identically, fixingsave_semantic_cachealways reporting "Cached 0 files" on subsequent--updateruns (#826) - Fix:
check_semantic_cachenow applies the same absolute-path normalization assave_semantic_cacheso relativesource_filepaths resolve consistently on both sides (#826) - Fix:
_AGENTS_MD_SECTIONnow includes the/graphifyskill trigger instruction — all 7 AGENTS.md platforms (OpenCode, Codex, Aider, Trae, Hermes, OpenClaw, Factory Droid) now correctly invoke the skill tool when the user types/graphify(#827)
0.7.15 (2026-05-11)
- Fix:
-h/--help/-?in any position now stops execution — previouslygraphify cursor install --helpsilently installed into Cursor;graphify benchmark --helpcrashed with FileNotFoundError (#821) - Fix:
--version,-v, andgraphify versionnow print the installed version and exit (#818) - Fix:
GRAPHIFY_OLLAMA_NUM_CTX=<invalid>no longer falls back to hardcoded 131072 (which exhausted VRAM) — it now falls through to the auto-derived value and prints a warning (#820) - Fix: when
GRAPHIFY_OLLAMA_NUM_CTXis set smaller than the estimated chunk size, graphify now warns explicitly that Ollama will silently truncate the prompt and suggests a corrected--token-budget(#820)
0.7.14 (2026-05-11)
- Fix:
_make_idand_normalize_idnow apply NFKC Unicode normalization before ID generation -- composed/decomposed forms of the same character (e.g.étyped vs pasted from a PDF) now produce the same node ID; switched from.lower()to.casefold()for correct Turkish/German/Greek case folding; both functions are now byte-for-byte equivalent (#811) - Fix: non-ASCII identifiers (CJK, Cyrillic, Arabic, accented Latin) are no longer collapsed to a bare file stem --
[^\w]+withre.UNICODEreplaces the old[^a-zA-Z0-9]+so Unicode word chars are preserved as part of the ID (#811) - Fix: dedup edge remap uses explicit key-presence check instead of
orso empty-stringsourceis not silently swapped forfrom; stalefrom/tokeys are now popped before the edge is emitted so they can't leak intograph.jsonedge attributes (#803) - Fix:
--updatemerge now 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(merged) rather than just the new extraction (#801) - Fix: subagent chunk files are now written to an absolute path (
CHUNK_PATHinjected at dispatch time fromgraphify-out/.graphify_root) so the Write tool doesn't lose chunks to an undefined working directory (#808) - Fix: skill version mismatch warning is now suppressed during
hook-check(runs on every editor tool use and must be silent) and routed to stderr for all other commands
0.7.13 (2026-05-09)
- Fix: Ollama
num_ctxnow derived from actual chunk size instead of hardcoded 131072 -- over-allocating 128k KV-cache slots for small chunks exhausted VRAM by chunk 4 on large models; formula ismin(input_tokens + output_cap + 2000, 131072)so--token-budget 8192gets ~26k instead of 131072 (#798) - Fix: hollow-response warning now mentions VRAM pressure and
GRAPHIFY_OLLAMA_NUM_CTX/GRAPHIFY_OLLAMA_KEEP_ALIVEenv vars as tuning knobs (#798) - Feat:
graphify export callflow-html-- generates a self-contained Mermaid architecture/call-flow HTML page fromgraphify-out/graph.json, grouped by community with interactive zoom/pan diagrams, call detail tables, and graph report highlights (#797) - Feat: callflow HTML auto-regenerates on every
--watchrebuild and post-commit hook if the file already exists -- opt-in by existence, zero config (#800)
0.7.12 (2026-05-09)
- Fix:
graphify explainandgraphify pathno longer crash onMultiGraphinputs -- newedge_data()/edge_datas()helpers inbuild.pyhandle both simple and multi-graphs; all 8 production call sites and 30 skill-file inline heredocs updated (#796) - Fix: hollow Ollama responses (0 tokens / empty string) now trigger adaptive retry bisection instead of silently dropping the chunk --
_response_is_hollow()detects empty/null/whitespace content and parsed results with no nodes/edges, then rewritesfinish_reason="length"to route into the existing bisection path (#792) - Fix: post-commit hook no longer spawns unbounded parallel rebuilds -- per-repo
fcntl.flocknon-blocking lock in_rebuild_code;changed_pathswired from hook through to AST extractor; stale nodes evicted on deletion;GRAPHIFY_REBUILD_TIMEOUTwatchdog; Darwin-aware memory cap (#791) - Fix: Antigravity install now writes to
.agents/(plural) -- corrected in platform config, paths, workflow body, and help text (#453) - Fix: Antigravity rules file now includes
trigger: always_onYAML frontmatter so Antigravity recognises it (#785) - Feat:
graphify extractgains--max-workers,--token-budget,--max-concurrency,--api-timeoutflags; hard 8-worker AST cap removed; explicit HTTP timeout on OpenAI client (default 600s,GRAPHIFY_API_TIMEOUT); ollama API key gate skipped for loopback URLs (#792) - Feat: Pascal/Delphi extraction now works without
tree-sitter-pascal-- regex fallback covers unit/program/library headers, uses clauses, class/interface inheritance, method declarations, and intra-file calls (#781) - Feat:
/graphify --helpnow prints the Usage block and stops without running pipeline steps (all 12 skill files) (#795)
0.7.11 (2026-05-09)
- Fix: context-window-exceeded API errors now trigger automatic retry with bisected file chunks -- exponential bisection up to 6 levels deep; covers
"context_length_exceeded","maximum context length", and"too_large"across OpenAI-compat backends (#789) - Fix: Windows pipeline unblocked --
print_benchmark()falls back to ASCII box-drawing on cp1252 consoles;ProcessPoolExecutorBrokenProcessPoolcaught and falls back to sequential extraction when caller lacksif __name__ == "__main__":guard; Windows skill file (skill-windows.md) rewrites allpython -c "..."blocks as PowerShell heredocs to fix quote-escaping failures (#788) - Fix: reversed
callsedges after--update--build_merge()now reads the saved JSON directly instead of round-tripping through NetworkXnode_link_graph(), which was silently reversing edge direction on reload (#760) - Fix: atomic SKILL.md install -- temp-file +
os.replace()pattern prevents half-installed empty skill directories that looked valid but contained no file; version-stamp guard and warning added for missing installs (#725) - Feat:
graphify uninstalltop-level command -- removes graphify skill files from all platforms in one shot;--purgeflag also deletesgraphify-out/ - Feat: SQL
ALTER TABLEFK extraction --ADD CONSTRAINT ... FOREIGN KEYandADD FOREIGN KEYDDL statements now emitreferencesedges; schema-qualified table names (schema.table) correctly resolved (#779)
0.7.10 (2026-05-07)
- Fix:
.tsxfiles now uselanguage_tsxgrammar for JSX-aware parsing -- previouslylanguage_typescriptwas used, silently dropping all JSX-specific nodes (#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 (#774)
- Refactor: generated
CLAUDE.md/AGENTS.md/GEMINI.mdtemplates strengthened withALWAYS/NEVER/IF ... EXISTSgraph-first directives (#775)
0.7.9 (2026-05-07)
- 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; Quarto executable code blocks (```{python}) extracted as code nodes (#761) - Feat: optional Google Workspace shortcut export for headless extraction --
graphify extract ./docs --google-workspaceconverts.gdoc,.gsheet, and.gslidesfiles into Markdown sidecars with thegwsCLI before semantic extraction; account email pseudonymized via SHA256 hash;[google]extra adds Sheets table rendering support (#752) - Fix: Google Workspace exports now run
gwsfrom the sidecar output directory with a relative-opath, matchinggwspath validation and avoiding failures when extracting a corpus outside the current working directory. - 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)
0.7.8 (2026-05-06)
- Fix: CommonJS
require()imports now extracted from JS/TS --const { foo } = require('./mod'),const m = require('./mod'), andconst x = require('./mod').yall emit EXTRACTEDimports_from(and per-symbolimports) edges. Previously CJS-only Node.js codebases produced AST graphs missing every import edge, which downgraded all cross-file calls to INFERRED. - Fix: cross-file
callsedges are now promoted from INFERRED to EXTRACTED when the caller's file has an explicitimportsorimports_fromedge to the callee. Previously every cross-file call was unconditionally INFERRED, even when a top-of-fileimport/requireproved the binding. On a 92-file CJS Node.js corpus this promoted 88% of cross-file calls (104 of 118) to EXTRACTED. - Feat: Gemini and OpenAI backends --
graphify extract ./docs --backend gemini(GEMINI_API_KEY / GOOGLE_API_KEY) or--backend openai(OPENAI_API_KEY);[gemini]and[openai]extras added (#735) - Feat: Groovy and Spock support --
.groovyand.gradleextracted via tree-sitter-groovy; Spock spec files (def "feature"()syntax) handled via regex fallback (#732) - Feat: Luau support --
.luau(Roblox Luau) added to code extraction using the Lua tree-sitter parser (#745) - Feat: Markdown structural extraction -- headings, fenced code blocks, and nesting hierarchy extracted as graph nodes from
.mdand.mdxfiles with zero new dependencies (#711) - Fix:
collect_files()extension set now auto-syncs with_DISPATCH-- previously 18 extensions (.sql,.vue,.svelte,.jsx,.ex,.jl, etc.) were silently skipped in skill-mode extraction (#711) - Fix:
detect_incrementalnow forwardsfollow_symlinkstodetect()-- symlinked subtrees no longer vanish on--updateruns (#736) - Fix: TS bare-path /
.svelte.ts/.svelte.js/index.tsdirectory / multi-dot imports now resolve correctly -- previously these produced phantom edges dropped at merge time (#717, #716) - Fix:
cluster-onlynow loads and saves.graphify_labels.json-- human-readable community labels survive re-clustering instead of resetting to "Community N" (#744) - Fix:
graphify export wikinow fails fast with exit 1 if.graphify_analysis.jsonis missing -- prevents silent deletion of existing wiki articles (#746) - Fix:
to_wiki()now raises before the cleanup loop whencommunitiesis empty -- second safety layer against wiki data loss (#746) - Fix: Ollama import error message now says "Ollama" not "Kimi" and points to
pip install openai;[ollama]extras group added (#750) - Security: hooks.py path execution now validates scripts are within the repo root -- closes supply-chain attack vector where a malicious commit could redirect hook execution (#747)
0.7.7 (2026-05-05)
- Feat: Ollama backend for headless extraction --
graphify extract ./docs --backend ollama; auto-detected whenOLLAMA_BASE_URLis set; defaults toqwen2.5-coder:7b; zero cost ($0.00); sentinel API key handles OpenAI client auth requirement (#729) - Feat: Cross-project global graph at
~/.graphify/global.json--graphify global add/remove/list/pathto register multiple project graphs with<repo>::<id>prefixed node IDs, preventing silent collisions; hash-based skip avoids re-ingesting unchanged graphs (#729) - Feat:
graphify extract --global --as <tag>flag -- after building a project graph, auto-registers it into the global graph in one step (#729) - Feat:
merge-graphsnow prefix-relabels each input graph before composing, preventing silent node ID collisions when two projects share entity names (#729) - Fix:
deduplicate_entitiesraisesValueErrorif called with nodes spanning multiple repos (cross-project dedup disabled by design -- per-project graphs are deduplicated in isolation) (#729) - Fix:
detect_incremental()now accepts and forwardsfollow_symlinkstodetect(). Without this,--updateruns silently miss any files reached through a symlinked sub-tree (e.g.state_of_truth/symlinking to a directory outside the corpus root), even when the original full run had detected them. Previously the flag was ondetect()andcollect_files()only. (#736)
0.7.6 (2026-05-05)
- Fix:
cluster-onlynow accepts--graph <path>to specify a non-default graph.json location; positional path and flags can appear in any order (#724) - Fix:
_is_sensitive()no longer drops legitimate source files — word boundaries on the keyword pattern prevent false positives liketokenizer.py,password_verification.py,SecretManager.java(#718) - Fix:
graphify extract --backend claude/kimiraises defaultmax_tokensfrom 8192 → 16384, eliminating the truncation-then-recursive-split cascade on dense doc corpora; respectsGRAPHIFY_MAX_OUTPUT_TOKENSenv var (#730) - Fix:
--updateprune message now clearly distinguishes "N nodes pruned from M deleted files" from "M deletions detected but graph already clean — no drift" (#539) - Fix:
extract_svelte()stub nodes now carry the resolved import path assource_fileinstead of the importer's path, preventing metadata corruption after merge (#712) - Fix:
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 in.sveltefiles (#713) - Fix:
graphify extract(full rebuild path) now savesmanifest.jsonon every successful run, not only on--update; prevents stale-manifest drift on subsequent incremental runs (#538) - Fix:
graphify antigravity installnow writes to.agent/(no trailing s) matching Antigravity's actual config paths (#704) - Fix: Pi skill YAML frontmatter description simplified to avoid "nested mappings" parse error on Pi startup (#737)
- Fix:
--dedup-llmflag now correctly threads LLM backend through todeduplicate_entitiesin both fresh and incremental extract paths; fresh extract path now also runs dedup (previously calledbuild_from_jsondirectly, bypassing dedup entirely)
0.7.5 (2026-05-04)
- 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
0.7.4 (2026-05-04)
- Fix:
_read_tsconfig_aliases()now parses JSONC — handles//line comments,/* */block comments, and trailing commas that every TypeScript framework starter generates; warns to stderr on parse failure instead of silently returning{}(#700) - Fix:
extract_svelte()regex fallback now captures aliased dynamic imports ($lib/...,$partials/...,@/...) and uses correct_make_id(str(path))scheme so edges survive intograph.jsoninstead of being dropped as phantom nodes (#701)
0.7.3 (2026-05-04)
- Feat:
graphify extract <path>— headless full-pipeline extraction for CI; runs AST extraction on code files and semantic LLM extraction on docs/papers/images without Claude Code in the loop; supports--backend kimi|claude,--out DIR,--no-cluster; auto-detects backend fromMOONSHOT_API_KEY/ANTHROPIC_API_KEY; docs-only corpora (issue #698) work cleanly - Fix: export/query/path/explain CLI subcommands added in 0.7.2 now ship with integration tests
- Fix: skill.md reduced from 63KB to 47KB by replacing Python heredocs with CLI calls (#696)
0.7.2 (2026-05-04)
- Feat: Fortran support - extracts modules, subroutines, functions, programs,
useimports, andcalledges from.f,.F,.f90,.F90,.f95,.F95,.f03,.F03,.f08,.F08files; names are lowercased for case-insensitive matching (#694)
0.7.1 (2026-05-04)
- Fix: Obsidian export - community labels with
.,&,(,)now produce valid Obsidian tags; only[a-zA-Z0-9_\-/]characters survive, preventing broken Dataview queries (#690) - Fix:
_load_tsconfig_aliases()now follows tsconfigextendschains - SvelteKit, Nuxt, and NestJS path aliases defined in extended configs are no longer silently dropped (#691) - Fix:
.sveltefiles now get a regex pass over the template layer after JS AST extraction -{#await import('./X.svelte')}markup-level dynamic imports are captured as edges (#692) - Fix: recursion limit raised to 10,000 at extract entry points (main process + each worker) with a
_safe_extractwrapper that skips pathological files with a clear warning instead of crashing the whole run (#695)
0.7.0 (2026-05-03)
Multi-dev busy-repo support: four gaps that caused merge conflicts, stale graphs, and silent cache misses in team workflows.
- Feat:
graphify hook installnow also configures a git merge driver forgraphify-out/graph.json— union-merges two graph.json files so git never produces conflict markers in the knowledge graph; writes.gitattributesand registersgraphify merge-driverin.git/config - Feat:
graphify merge-driver <base> <current> <other>subcommand — takes two graph.json variants and writes their node/edge union back to<current>; always exits 0 so merge never blocks - Feat: Leiden community detection now seeded (
seed=42when supported) for deterministic community IDs across parallel rebuilds — reduces JSON diff churn in multi-dev repos - Feat:
graph.jsonnow embedsbuilt_at_commit(git HEAD) at write time;GRAPH_REPORT.mdsurfaces the commit hash and a freshness check hint - Fix:
file_hashis now content-only (path removed from hash) — renamed files reuse their cache entry instead of re-extracting; cachedsource_filefields are updated to the new path on load - Fix: watch mode mixed-batch handling — commits with both code and non-code files now rebuild code immediately AND write
needs_updateflag; previously code changes were silently dropped in mixed batches
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
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)
0.6.7 (2026-05-02)
- Feat:
graphify tree— self-contained D3 v7 collapsible-tree HTML view ofgraph.json; expand/collapse controls, depth-based colours, hover inspector; XSS-safe (#557) - Feat: token-aware chunking with split-and-retry on truncation (#625)
- Feat: cross-language edge context filters in MCP
query_graphtool (#573) - Feat: dynamic
import()extraction for JS/TS (#579) - Fix:
save_semantic_cachecrashed withIsADirectoryErrorwhen a node'ssource_filewas a directory path —p.exists()→p.is_file()(#655) - Fix:
sanitize_label(None)raisedTypeErrorcrashingto_htmlon graphs with nullsource_filerationale nodes — return""early (#656) - Fix: chunk-extraction prompt omitted
rationalefrom validfile_typevalues — model hallucinatedconcepton every doc/paper run; explicit merge step added to all skill variants (#657) - Fix:
cost.jsonalways reported 0 tokens — chunk JSONs have placeholder zeros; orchestrator now globs and sums real token counts before merging (#658)
0.6.6 (2026-05-02)
- Fix:
skill-windows.mdrewritten from PowerShell to bash — Claude Code on Windows uses git-bash so PowerShell syntax ($null,$LASTEXITCODE,Select-Object,& (Get-Content ...),Remove-Item) caused exit code 49 failures; now mirrorsskill.mdstructure withpythonadded as fallback afterpython3for Windows Conda (#39) - Fix: wiki
to_wiki()now clears stale articles before regenerating, preventing orphan .md accumulation (#558) - Fix:
_safe_filename()in wiki.py now strips Windows-reserved characters (< > : " / \ | ? *) and caps length at 200 chars (#594) - Fix: rationale-node leakage in cross-file INFERRED call resolution — rationale nodes now excluded from name lookup; edge direction (
calls,rationale_for) preserved correctly at JSON export (#576) - Feat:
.graphifyincludehidden path allowlist — opt specific hidden dirs into traversal (e.g..hermes/plans/**/*.md) (#583) - Feat:
--no-vizflag wired incluster-only;GRAPHIFY_VIZ_NODE_LIMITenv var overrides 5000-node HTML threshold (#565) - Fix: stray colon SyntaxError in
skill-trae.md--cluster-onlyblock (#603) - Docs: skill INFERRED confidence score guidance changed to discrete rubric (0.55/0.65/0.75/0.85/0.95) backed by calibration data (#546)
- Docs: skill
--updateprune output clarified — splits no-drift vs drift cases (#544) - Docs: skill
--updatemerge step now callssave_manifestto prevent deleted files reappearing (#545) - Feat:
graphify tree— self-contained D3 v7 collapsible-tree HTML view ofgraph.json; expand/collapse controls, depth-based colours, hover inspector; XSS-safe viahtml.escape()and_js_safe()(#557)
0.6.5 (2026-05-02)
- Fix: Kotlin call-walker now accepts both
simple_identifierandidentifiernode types — PyPI'stree_sitter_kotlingrammar usesidentifierwhile older forks usesimple_identifier, causing zerocallsedges to be emitted (#659) - Feat: community sidebar now uses checkbox-based multi-select instead of show/hide buttons — supports indeterminate "select all" state (#647)
- Feat:
graphify update --forceandGRAPHIFY_FORCE=1env var — bypass the node-count safety check after refactors that legitimately shrink the graph (#639) - Fix: Codex PreToolUse hook on Windows — replaced
python3 -c "..."inline command (fails on Conda where onlypythonexists, and breaks PowerShell JSON parsing) withgraphify hook-check, a new shell-agnostic subcommand. Re-rungraphify codex installto regenerate the hook (#651, #522)
0.6.4 (2026-05-02)
- Fix: Codex PreToolUse hook failed on Windows —
[ -f ]is bash-only and crashes oncmd.exe; replaced with a cross-platform Python one-liner (pathlib.Path.exists()) (#651)
0.6.3 (2026-05-02)
- Fix: incremental rebuild (
graphify update, post-commit hook) dropped INFERRED/AMBIGUOUS semantic nodes extracted from code files — node preservation now filters by ID membership in the new AST output instead offile_type, so LLM-extracted call/data-flow edges survive code-only rebuilds (#653) - Fix: post-commit and post-checkout hooks blocked
git commitfor the full rebuild duration (hours on large repos) — rebuilds now detach vianohup & disown, git returns in ~100ms, log written to~/.cache/graphify-rebuild.log(#650) - Fix: cross-file INFERRED
callsresolution used a last-write-wins name map, causing common short names (log,execute,find) to accumulate hundreds of spurious edges and dominate god_nodes ranking — resolution now skips any callee name that matches 2+ candidates (ambiguous, no import evidence to pick the right target) (#543) - Fix:
cluster-onlycommand crashed on graphs with >5000 nodes due to unguardedto_htmlcall — now wrapped in try/except ValueError matching the watch/hook path (#541)
0.6.2 (2026-05-01)
- Fix: Kimi K2.6 reasoning mode consumed entire token budget leaving
contentempty — thinking now disabled on Moonshot calls so graphs actually populate (#623) - Fix:
graphify update/graphify watchnever persisted the manifest, so every subsequent--updatere-extracted all files — manifest now saved after each rebuild (#621) - Fix: inline comments in
.graphifyignore(e.g.vendor/ # legacy) now stripped correctly — whitespace +#suffix is treated as a comment,path#hash.pypreserved (#605) - Fix:
graphify query "FunctionName"now returns the exact matching node first instead of high-degree hub modules hijacking the output — 100-point exact-match bonus + seeds render before BFS expansion (#638) - Fix: concurrent AST extractors raced on a shared
.tmpcache file — each writer now gets a unique tempfile viamkstemp, eliminating cache corruption under parallel extraction (#589) - Fix:
_clone_repobranch names starting with-could be interpreted as git flags — validation added,--separator inserted before positional args (#589) - Fix: replaced
html2text(GPL-3.0) withmarkdownify(MIT) — removes the only copyleft dependency from a MIT project (#586) - Fix:
--updatere-extracted files whose mtime was bumped by sync tools (Obsidian, Nextcloud) without content changes — manifest now stores content hash alongside mtime; mtime bump triggers an MD5 check before re-extraction (#593) - Feat: R language support —
.rfiles classified as code and processed via LLM semantic extraction (#617) - Feat: extensionless shell scripts now detected via shebang (
#!/bin/bash,#!/usr/bin/env python3, etc.) and included as code (#619) - Fix: cross-language INFERRED
callsedges (e.g. Python→TypeScript name collision) no longer appear as top surprising connections in GRAPH_REPORT.md (#630) - Fix:
cluster-onlyCLI silently flipped directed graphs to undirected —directedflag now read from graph.json and preserved through re-clustering (#590) - Fix: Windows UNC / extended-length paths (
\\?\C:\...) now normalize to consistent cache keys (#629) - Fix:
.graphifyignorenegation patterns (!src/lib/secrets.ts) now work — full last-match-wins evaluation with!un-ignore support (#628)
0.6.1 (2026-05-01)
- Fix:
.graphifyignorediscovery now uses correct gitignore semantics — outer rules are loaded first so inner (closer) rules always win via last-match-wins, matching standard gitignore behavior (#643) - Fix: without a VCS root,
.graphifyignorediscovery is now hermetic to the scan folder — no leakage across sibling projects in a shared workspace (#643) - Fix: anchored patterns (leading
/) in a parent.graphifyignorenow correctly apply only relative to their own directory, not the scan root (#643) - Fix: trailing spaces in patterns are now handled per gitignore spec — unescaped trailing spaces are stripped,
vendor\(escaped) is preserved (#643)
0.6.0 (2026-05-01)
- Feat: SQL AST extractor —
.sqlfiles now processed deterministically via tree-sitter. Extracts tables, views, functions/procedures, foreign key references, and FROM/JOIN reads_from edges. No LLM needed. Requirespip install 'graphifyy[sql]'(#349) - Feat:
xlsx_extract_structure()utility — extracts sheet names, named tables, and column headers from .xlsx files as structural nodes
0.5.7 (2026-04-30)
- Feat: YAML/YML files now indexed for semantic extraction — Kubernetes, Kustomize, Helm, and any YAML corpus now picked up automatically (#633)
0.5.6 (2026-04-30)
- Fix:
NameError: name '_os' is not definedcrash aftergraphify update— this was fixed in v5 branch but not released to PyPI (#618, #612)
0.5.5 (2026-04-29)
- Feat: Kimi K2.6 backend —
pip install 'graphifyy[kimi]'+MOONSHOT_API_KEYroutes semantic extraction through Kimi K2.6. 3-6x richer relation extraction at ~3x lower cost. Claude remains default; Kimi is opt-in. - Fix: phantom god nodes (#598) — member-call callees (
this.logger.log()→log) no longer cross-file resolved. Go package-qualified calls (pkg.Func()) correctly preserved. Affects JS/TS, Go, Rust, Swift, Kotlin, Scala, PHP, C++, C#, Zig, Elixir. - Fix:
conceptfile_type no longer triggers validation warnings (#601) - Fix:
graphify updateremembers scan root viagraphify-out/.graphify_root— no path argument needed on subsequent runs - Fix: Kimi K2.6 temperature 400 error — temperature param is now skipped for Kimi backends (model enforces its own fixed value) (#610)
- Fix: community labels deleted in Step 9 cleanup —
.graphify_labels.jsonis now preserved so wiki/obsidian/HTML retain human-readable names after re-cluster (#608) - Fix:
NameError: name '_os' is not definedingraphify updateKimi tip (#612) - Fix:
SyntaxWarningin__main__.pyfor shell glob pattern with backslash escapes - Fix: Python upper bound removed —
requires-python = ">=3.10"now supports Python 3.14+ (#607)
0.5.4 (2026-04-28)
- Fix: SSRF DNS rebinding —
safe_fetchnow patchessocket.getaddrinfofor the full request duration (#591) - Fix: yt-dlp SSRF bypass —
download_audionow callsvalidate_urlbefore handing URL to yt-dlp (#592)
0.5.3 (2026-04-27)
- Fix: cache namespace — AST and semantic entries now live in
cache/ast/andcache/semantic/subdirectories; flat entries read as migration fallback
0.5.2 (2026-04-26)
- Fix: PreToolUse hook now matches on
Bashinstead ofGlob|Grepfor Claude Code v2.1.117+
0.5.1 (2026-04-25)
- Fix: node ID collision for same-named files in different directories
- Fix:
source_filepaths relativized before return sograph.jsonis portable - Fix: desync guard —
to_json()returns bool; report only written on successful JSON write - Feat: TypeScript
@/path aliases resolved viatsconfig.json - Feat: Show All / Hide All buttons in HTML community panel
0.5.0 (2026-04-24)
- Feat:
graphify clone <github-url>— clone and graph any public repo - Feat:
graphify merge-graphs— combine multiplegraph.jsonoutputs into one cross-repo graph - Feat:
CLAUDE_CONFIG_DIRsupport ingraphify install - Feat: shrink guard —
to_json()refuses to overwrite with a smaller graph - Feat:
build_merge()for safe incremental updates - Feat: duplicate node deduplication via
deduplicate_by_label() - Fix:
graphify-out/excluded from source scanning
0.4.23 (2026-04-18)
- Fix: stale skill version warning persists after running
graphify installwhen multiple platforms were previously installed —graphify installnow refreshes.graphify_versionin all other known skill directories so the warning clears across the board (#178) - Fix:
.htmlfiles silently skipped during detection — added.htmltoDOC_EXTENSIONS; HTML pages, docs, and web project content now indexed correctly (#260) - Fix:
_rebuild_code(watch/update/hook) fails entirely on graphs > 5000 nodes becauseto_htmlraisesValueError— wrapped in its own try/except sograph.jsonandGRAPH_REPORT.mdalways land; stalegraph.htmlfrom a previous smaller run is removed (#432) - Fix: Go stdlib imports (e.g.
"context") producedimports_fromedges pointing at local files of the same basename — Go import node IDs now prefixedgo_pkg_using the full import path, eliminating false cycle-dependency pairs (#431)
0.4.22 (2026-04-18)
- Fix: AST cache written to
src/graphify-out/cache/instead of project root when all code files share a common prefix likesrc/—extract()now called with explicitcache_root=watch_pathin_rebuild_codeandcache_root=Path('.')in the Codex skill AST step (#429) - Fix:
.mdxfiles silently skipped during detection — added.mdxtoDOC_EXTENSIONSindetect.py; MDX-based corpora (Next.js, Docusaurus, Astro) now indexed correctly (#428)
0.4.21 (2026-04-17)
- Fix:
graphify cluster-onlycrashed withKeyError: 'total_files'inreport.py— cluster-only skips detection so the stats dict was empty; now passes awarningkey so the report skips the file-stats section (#422) - Fix:
/graphify --updatedropped all existing graph nodes — the merge block built a correct in-memoryG_existingbut 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 (#423)
0.4.20 (2026-04-17)
- Fix: JS/MJS
imports_fromedges were silently dropped for files that use../subdir/file.mjsstyle imports —Path.parent / rawleft..segments unnormalized, so the generated target ID didn't match the actual file node ID. Fixed withos.path.normpath(#414) - Fix:
graphify update .andgraphify cluster-onlynow generategraph.htmlalongsidegraph.jsonandGRAPH_REPORT.md— previously only the skill generated the interactive HTML (#418)
0.4.19 (2026-04-17)
- Fix: AST and semantic extraction no longer produce mismatched node IDs —
build_from_jsonnow normalises IDs before dropping edges, so edges survive when the LLM generates slightly different casing or punctuation than the AST extractor (#390) - Fix: cross-file call resolution extended to Go, Rust, Zig, PowerShell, and Elixir — unresolved callees are now saved as
raw_callsand resolved globally in a post-pass, matching existing behaviour for Python, Swift, Java, C#, Kotlin, Scala, Ruby, and PHP (#298) - Fix: Windows
graphify-out/graphify-outnesting bug —cache_dirand_rebuild_codein watch.py now call.resolve()on the root path, preventing a nested output directory when graphify is run from a subdirectory (#410) - Fix:
graphify hook installnow respectscore.hooksPathgit config (used by Husky and similar tools) — hooks are written to the configured path instead of always.git/hooks(#401) - Fix: Kiro skill YAML frontmatter —
descriptionvalue is now quoted and colons replaced with dashes, preventing a parse error in Kiro's YAML loader (#385) - Docs: added Windows PATH tip (
%APPDATA%\Python\PythonXY\Scripts) and macOS pipx tip (pipx ensurepath) to the install section (#413) - Docs: added team workflow section — committing
graphify-out/,.graphifyignoreusage, and recommended.gitignoreadditions (#369)
0.4.16 (2026-04-16)
- Fix: graphify watch crashed on all platforms with NameError because import sys was missing from watch.py (#386, #394)
- Fix: .mjs files were detected but produced 0 nodes — added .mjs to the AST extractor dispatch table (#387)
- Fix: llm.py excluded from the published wheel (local benchmarking file, not part of the public API) (#391)
0.4.15 (2026-04-15)
- Feat: VS Code Copilot Chat support —
graphify vscode installinstalls 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 entries in
opencode.json— now uses forward slashes via.as_posix()(#378) - Fix: Gemini CLI on Windows now installs skill to
~/.agents/skills/(higher priority) instead of~/.gemini/skills/(#368) - Fix:
.mjsand.ejsfiles now recognised by the AST extractor as JavaScript (#365, #372) - Fix:
god_nodes()field renamed fromedgestodegreefor clarity — updated in report, wiki, serve, and all tests (#375) - Fix: macOS
graphify watchnow usesPollingObserverby default to avoid missed events with FSEvents (#373)
0.4.14 (2026-04-15)
- Fix: cross-file call edges now emitted for all languages (Swift, Go, Rust, Java, C#, Kotlin, Scala, Ruby, PHP, and others) — previously only Python had cross-file resolution; unresolved call sites are now saved per file and resolved against a global label map in a post-pass (#348)
- Fix: PHP extractor now handles
scoped_call_expression(static method calls likeHelper::format()) andclass_constant_access_expression(enum/constant references likeStatus::ACTIVE) — both were silently dropped before (#230, #232) - Fix:
--wikiflag now runsto_wiki()as Step 6b in the skill pipeline before the cleanup step — community labels are available and the wiki is written tographify-out/wiki/(#229, #354) - Fix:
graphify install --platform opencodenow also installs the.opencode/plugins/graphify.jsplugin, matching whatgraphify opencode installdoes (#356) - Fix:
extract()accepts explicitcache_rootparameter so subdirectory runs no longer write cache to<subdir>/graphify-out/cache/(#350) - Fix:
os.replacein cache writer falls back toshutil.copy2onPermissionError(Windows WinError 5) (#287) - Fix:
graphify updateexits with code 1 on rebuild failure instead of silently returning (#287) - Fix:
CLAUDE.md, Cursor, and Antigravity templates now usegraphify update .instead of hardcodedpython3 -cinvocation (#287) - Fix:
skill-kiro.mdadded topyproject.tomlpackage-data —graphify kiro installwas failing on fresh pip installs (#352) - Fix:
betweenness_centralityinsuggest_questionsusesk=100approximate sampling for graphs over 1000 nodes;edge_betweenness_centralityreturns early for graphs over 5000 nodes (#341)
0.4.13 (2026-04-14)
- Add: Verilog/SystemVerilog support —
.vand.svfiles extracted via tree-sitter-verilog (modules, functions, tasks, package imports, module instantiations withinstantiatesedges) (#325) - Fix: hyperedge polygons render correctly on HiDPI/Retina displays —
afterDrawingcallback ctx is now used directly (already in network coordinate space), removing the double-applied transform and incorrectcanvas.width/2DPR anchor (#334) - Fix: AGENTS.md and GEMINI.md rebuild rule now uses
graphify update .instead of hardcodedpython3 -c "..."— correct Python is resolved through the graphify binary, no more interpreter mismatches in Nix/pipx/uv environments (#324) - Fix:
graphify queryandgraphify explainno longer crash withAttributeErrorwhen a node haslabel: null— all.get("label", "")calls guarded withor ""to handle explicit null values (#323)
0.4.12 (2026-04-13)
- Add: Kiro IDE/CLI support —
graphify kiro installwrites.kiro/skills/graphify/SKILL.md(invoked via/graphify) and.kiro/steering/graphify.md(inclusion: always— always-on context before every conversation) (#319, #321) - Fix: cache
file_hash()now uses the path relative to project root instead of the resolved absolute path — cache entries are now portable across machines, CI runners, and different checkout directories (#311)
0.4.11 (2026-04-13)
- Fix:
graphify queryno longer crashes withValueErroron MultiGraph graphs —G.edges[u, v]replaced withG[u][v]+ MultiGraph guard (#305) - Fix:
graphify queryno longer crashes withAttributeError: 'NoneType' has no attribute 'lower'when a node has a nullsource_file(#307) - Fix: MCP server launched from a different directory now correctly derives the
graphify-outbase from the absolute path provided, instead of CWD (#309) - Fix:
.graphifyignorepatterns from a parent directory now fire correctly when graphify is run on a subfolder — patterns are matched against paths relative to both the scan root and the.graphifyignore's anchor directory (#303)
0.4.10 (2026-04-13)
- Fix:
graphify install --platform cursorno longer crashes — passesPath(".")to_cursor_install(#281) - Fix:
_agents_uninstallnow only removes the OpenCode plugin when uninstalling theopencodeplatform — other platforms were incorrectly having their OpenCode plugin stripped (#276) - Fix: misleading comment in query
--graphpath handler removed (#278) - Fix:
skill-codex.md—wait→wait_agent(correct Codex tool name) (#273) - Add:
svg = ["matplotlib"]optional extra in pyproject.toml;matplotlibadded to[all]extra (#288) - Fix:
graspologicdependency now haspython_version < '3.13'env marker inleidenandallextras — prevents install failures on Python 3.13+ (#290) - Add: Dart/Flutter support —
.dartfiles extracted via regex (classes, mixins, functions, imports); added toCODE_EXTENSIONS(#292) - Add:
norm_labelfield written at build time into_json()for diacritic-insensitive search;_score_nodesand_find_nodeinserve.pyusenorm_labelwith Unicode NFKD normalization fallback (#293) - Add: Hermes Agent platform support —
graphify hermes installwrites skill to~/.hermes/skills/graphify/SKILL.mdand AGENTS.md (#251) - Add: PHP extractor now captures static property access (
Foo::$bar) asuses_static_propedges (#234) - Add: PHP extractor now captures
config()helper calls asuses_configedges pointing to the first config key segment (#236) - Add: PHP extractor now captures service container bindings (
bind,singleton,scoped,instance) asbound_toedges (#238) - Add: PHP extractor now captures
$listen/$subscribeevent listener arrays aslistened_byedges (#240) - Add:
prune_dangling_edges()utility inexport.py— removes edges whose source/target is not in the node set (#294) - Fix: Antigravity install injects YAML frontmatter into skill file for native tool discovery; rules now include MCP navigation hint; prints MCP config snippet (#268)
- Fix: Windows hook tests now use platform-aware assertions instead of POSIX executable bit checks (#279)
- Add: CLI commands
path,explain,add,watch,update,cluster-onlynow work as bare terminal commands (not just AI skill invocations) — documented in--helpoutput (#277)
0.4.8 (2026-04-12)
- Fix: platform skill files (aider, codex, opencode, claw, droid, copilot, windows) no longer contain Claude-specific language — references to "Claude" as the AI model replaced with platform-agnostic wording (#272)
0.4.7 (2026-04-12)
- Fix:
watchsemantic edge preservation was always empty —graph.jsonuseslinkskey but code readedges(#269) - Fix:
graphify claw installnow writes to.openclaw/(correct OpenClaw directory) instead of.claw/(#208) - Add: Blade template support —
@include,<livewire:>components, andwire:clickbindings extracted from.blade.phpfiles (#242) - Docs: WSL/Linux MCP setup note — package name is
graphifyy, use.venv/bin/python3in.mcp.json(#250)
0.4.6 (2026-04-12)
- Add: Google Antigravity support —
graphify antigravity installwrites.agent/rules/graphify.md(always-on rules) and.agent/workflows/graphify.md(/graphifyslash command) (#203, #199, #53)
0.4.5 (2026-04-12)
- Fix: MCP server no longer crashes with
ValidationErroron blank lines sent between JSON messages by some clients (#201)
0.4.4 (2026-04-12)
- Fix:
watchnow preserves INFERRED/AMBIGUOUS edges (code↔doc rationale links) across rebuilds — previously all cross-type edges were dropped (#261) - Fix: Codex hook no longer emits
permissionDecision:allowwhich codex-cli 0.120.0 rejects (#249) - Fix: Common lockfiles (
package-lock.json,yarn.lock,Cargo.lock, etc.) are now skipped during detection, preventing token drain on large JS/Rust/Python projects (#266)
0.4.3 (2026-04-12)
- Fix: JS/TS relative imports now resolve to full-path node IDs — previously all
imports_fromedges were silently dropped on large TypeScript codebases (#256) - Fix: Python relative imports (
from .foo import bar) now resolve correctly to full-path node IDs (#256) - Fix:
watch --rebuild_codenow merges fresh AST with existing semantic nodes from docs/papers instead of overwriting them (#253) - Fix: Windows hooks now fall back to
pythonifpython3is not found; exits cleanly if neither has graphify installed (#244) - Fix:
surprising_connections/suggest_questionsno longer crash withKeyErroron stale_src/_tgtedge hints after node merges (#226) - Add:
.vueand.sveltefiles now recognized as code and included in extraction (#254)
0.4.2 (2026-04-11)
- Fix: same-basename files in different directories produced colliding node IDs — now uses full path (#211)
- Fix: edges using
from/tokeys instead ofsource/targetwere silently dropped (#216) - Fix: empty graphs (no edges) crashed
to_htmlwithZeroDivisionError(#217) - Fix: post-commit hook skipped
.tsx,.jsx, and other valid code extensions due to stale allowlist (#222) - Fix: NetworkX ≤3.1 serialises edges as
links— now accepted alongsideedges(#212) - Fix: version warning fired during
install/uninstalland duplicated on shared paths (#220) - Fix: all file IO now uses
encoding="utf-8"— prevents crashes on Windows with CJK or emoji labels; hook writes usenewline="\n"to prevent CRLF shebang breakage (#204) - Fix: Obsidian export — node labels ending in
.mdproduced.md.mdfilenames;GRAPH_REPORT.mdnow links to community hub files so vault stays in one connected component (#221)
0.4.1 (2026-04-10)
- Fix:
collect_files()inextract.pynow respects.graphifyignore— previously ignored patterns, causing thousands of unwanted files (e.g.node_modules/) to be scanned (#188) - Fix: skill.md Step B2 now explicitly requires
subagent_type="general-purpose"— usingExploretype silently dropped extraction results since it is read-only and cannot write chunk files (#195) - Fix: Step B3 now warns when chunk files are missing from disk instead of silently skipping them
0.4.0 (2026-04-10)
- Branch: v4 — video and audio corpus support
- Add: drop
.mp4,.mp3,.wav,.mov,.webm,.m4a,.ogg,.mkv,.avi,.m4vfiles into any corpus and graphify transcribes them locally with faster-whisper before extraction - Add: YouTube and URL download via yt-dlp —
/graphify add https://youtube.com/...downloads audio-only and feeds it through the same Whisper pipeline - Add: domain-aware Whisper prompts — the coding agent reads god nodes from the corpus and writes a one-sentence domain hint for Whisper itself, no separate API call
- Add:
graphify-out/transcripts/cache — transcripts cached by filename; YouTube URLs cached by hash so re-runs skip already-transcribed files - Requires:
pip install 'graphifyy[video]'for faster-whisper and yt-dlp
0.3.29 (2026-04-10)
- Add: video and audio corpus support — drop
.mp4,.mp3,.wav,.mov,.webm,.m4a,.ogg,.mkv,.avi,.m4vfiles into any corpus and graphify transcribes them with faster-whisper before extraction - Add: YouTube and URL video download — pass a YouTube link (or any video URL) to
/graphify add <url>and yt-dlp downloads audio-only, which is then transcribed and added to the corpus automatically - Add: domain-aware Whisper prompts — god nodes from non-video files are used to build a one-sentence domain hint for Whisper via a cheap Haiku call, improving transcript accuracy on technical content
- Add:
graphify-out/transcripts/cache — transcripts are cached by filename so re-runs skip already-transcribed files; URLs cached by hash - Requires:
pip install 'graphifyy[video]'for faster-whisper + yt-dlp
0.3.28 (2026-04-10)
- Fix: hook installers (Claude Code, Codex, Gemini CLI) now always remove and reinstall the hook on re-run — users upgrading from old versions no longer get stuck with a broken hook format (#182)
- Fix: rationale node labels no longer contain bare
\rcharacters on Windows/WSL CRLF files — breaks Obsidian export was silently producing invalid filenames (#176) - Fix:
skill-windows.mdnow includes--wiki,--obsidian-dir, and--directedwhich were missing vs the main skill (#177)
0.3.27 (2026-04-10)
- Fix: graphify install --platform gemini now also copies the skill file to ~/.gemini/skills/graphify/SKILL.md so the /graphify trigger works in Gemini CLI (#174)
0.3.26 (2026-04-10)
- Fix: MCP server no longer uses a circular path validation when loading a graph outside cwd — now validates the path exists and ends in
.jsoninstead of checking containment within its own parent directory (security fix)
0.3.25 (2026-04-09)
- Fix:
graphify install --platform gemininow routes togemini_install()instead of erroring —geminiwas missing from_PLATFORM_CONFIG(#171) - Fix:
graphify install --platform cursornow routes to_cursor_install()the same way (#171) - Fix:
serve.pyvalidate_graph_pathnow passesbase=Path(graph_path).resolve().parentso MCP server works when graph is outside cwd (#170) - Fix: MCP
call_tool()handler now wraps dispatch in try/except — exceptions in tool handlers return graceful error strings instead of crashing the stdio loop (#163) - Fix:
_load_graphifyignorenow walks parent directories up to the.gitboundary, matching.gitignorediscovery behavior — subdirectory scans now inherit root ignore patterns (#168) - Add: Aider platform support —
graphify install --platform aidercopies skill to~/.aider/graphify/SKILL.md;graphify aider install/uninstallwrites AGENTS.md rules (#74) - Add: GitHub Copilot CLI platform support —
graphify install --platform copilotcopies skill to~/.copilot/skills/graphify/SKILL.md;graphify copilot install/uninstallfor skill management (#134) - Add:
--directedflag —build_from_json()andbuild()now acceptdirected=Trueto produce aDiGraphpreserving edge direction (source→target);cluster()converts to undirected internally for Leiden;graph_diffedge key handles directed graphs correctly (#125) - Add: Frontmatter-aware cache for Markdown files —
.mdfiles hash only the body below YAML frontmatter, so metadata-only changes (reviewed, status, tags) no longer invalidate the cache (#131)
0.3.24 (2026-04-09)
- Fix:
graphify codex install(and opencode) no longer exits early whenAGENTS.mdalready has the graphify section — partial installs with a missing.codex/hooks.jsoncan now recover on re-run (#153)
0.3.23 (2026-04-09)
- 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
0.3.22 (2026-04-09)
- Add: Cursor support —
graphify cursor installwrites.cursor/rules/graphify.mdcwithalwaysApply: trueso the graph context is always included;graphify cursor uninstallremoves it (#137) - Fix:
_rebuild_code()KeyError —detected[FileType.CODE]corrected todetected['files']['code']matchingdetect()'s actual return shape; was silently breaking git hooks on every commit (#148) - Fix:
to_json()crash on NetworkX 3.2.x —node_link_data(G, edges="links")now falls back tonode_link_data(G)on older NetworkX, same shim already used fornode_link_graph(#149) - Fix: README clarifies
graphifyyis the only official PyPI package — othergraphify*packages are not affiliated (#129)
0.3.21 (2026-04-09)
- Fix: Codex PreToolUse hook now places
systemMessageat the top level of the output JSON instead of insidehookSpecificOutput— matches the strict schema enforced by codex-cli 0.118.0+ which usesadditionalProperties: false(#138) - Fix: git hooks now use
#!/bin/shinstead of#!/bin/bash— Git for Windows shipssh.exenotbash, so hooks were silently skipped on Windows (#140)
0.3.20 (2026-04-09)
- Fix: XSS in interactive HTML graph — node labels, file types, community names, source files, and edge relations now HTML-escaped before
innerHTMLinjection; neighbor linkonclickusesJSON.stringifyinstead of raw string interpolation - Add: OpenCode
tool.execute.beforeplugin —graphify opencode installnow writes.opencode/plugins/graphify.jsand registers it inopencode.json, firing the graph reminder before bash calls (equivalent to Claude Code's PreToolUse hook) (#71) - Fix: AST-resolved call edges now carry
confidence=EXTRACTED, weight=1.0instead of INFERRED/0.8 — tree-sitter call resolution is deterministic, not probabilistic (#127) - Fix:
tree-sitter>=0.23.0now pinned in dependencies and_check_tree_sitter_version()guard added — stale environments now get a clearRuntimeErrorwith upgrade instructions instead of a crypticTypeErrordeep in the AST pipeline (#89)
0.3.19 (2026-04-09)
- Fix: install step now tries plain
pip installbefore falling back to--break-system-packages— Homebrew and PEP 668 managed environments no longer risk environment corruption (#126)
0.3.18 (2026-04-09)
- Fix:
--watchmode now respects.graphifyignore—_rebuild_codewas callingcollect_files()directly instead ofdetect(), bypassing ignore patterns (#120) - Fix: Codex PreToolUse hook now uses
systemMessageinstead ofadditionalContext— Codex does not supportadditionalContextand was returning an error (#121) - Fix: Trae link corrected from
trae.comtotrae.aiin README, README.zh-CN.md, README.ja-JP.md, README.ko-KR.md (#122) - Docs: Korean README added (README.ko-KR.md) (#112)
- Refactor:
save_query_resultinline Python blocks in all 6 skill files replaced withgraphify save-resultCLI command — shorter, maintainable, less tokens for LLM (#114) - Add:
graphify save-resultCLI subcommand — saves Q&A results to memory dir without inline Python - Fix: HTML graph click detection now uses hover-tracking (
hoveredNodeId) — more reliable than vis.js click params on small/dense nodes (#82) - Fix:
mkdir -p graphify-outnow runs before writing.graphify_pythoninskill.md— prevents write failure on first run;.graphify_pythonno longer deleted in Step 9 cleanup across all skill files so follow-up commands keep their interpreter (#93) - Fix:
skill-trae.mdadded topyproject.tomlpackage-data — Trae users no longer hitModuleNotFoundErrorafterpip install(#102) - Fix:
analyze.pyandwatch.pynow import extension sets fromdetect.pyinstead of local copies — Swift, Lua, Zig, PowerShell, Elixir, JSX, Julia, Objective-C files no longer misclassified as documents (#109) - Refactor: dead
build_graph()function removed fromcluster.py(#109)
0.3.17 (2026-04-08)
- Add: Julia (.jl) support — modules, structs, abstract types, functions, short functions, using/import, call edges, inherits edges via tree-sitter-julia (#98)
- Fix: Semantic extraction chunks now group files by directory so related artifacts land in the same chunk, reducing missed cross-chunk relationships (#65)
- Fix:
tree-sitter>=0.21now pinned in dependencies — prevents silent empty AST output when older tree-sitter is installed with newer language bindings (#52) - Add: Progress output every 100 files during AST extraction so large projects don't appear to hang (#52)
0.3.16 (2026-04-08)
- Fix:
graphify query,serve, andbenchmarknow work on NetworkX < 3.4 — version-safe shim fornode_link_graph()at all call sites (#95) - Fix:
.jsxfiles now detected and extracted via the JS extractor — added toCODE_EXTENSIONSand_DISPATCH(#94) - Fix:
.graphify_pythonno longer deleted in Step 9 cleanup across all 6 skill files — pipx users no longer hitModuleNotFoundErroron follow-up commands (#92)
0.3.15 (2026-04-08)
- Feat: Trae and Trae CN platform support (
graphify install --platform trae/trae-cn) - Fix:
skill-droid.mdwas missing from PyPI package data — Factory Droid users couldn't install the skill - Fix: XSS in HTML legend — community labels now HTML-escaped before
innerHTMLinjection - Fix: Shebang allowlist validation in
hooks.pyand all 6 skill files — prevents metacharacter injection from malicious binaries - Fix:
louvain_communities()kwargs now inspected at runtime for cross-version NetworkX compatibility - Fix: pipx installs now detected correctly in git hooks (reads shebang from graphify binary)
- Fix: graspologic ANSI escape codes no longer corrupt PowerShell 5.1 scroll buffer
- Docs: Japanese README added
- Docs:
graph.json+ LLM workflow example added to README - Docs: Codex PreToolUse hook now documented in platform table
0.3.14 (2026-04-08)
- Fix:
graphify codex installnow also writes a PreToolUse hook to.codex/hooks.jsonso the graph reminder fires before every Bash tool call (#86) - Fix:
--updatenow prunes ghost nodes from deleted files before merging new extraction (#51)
0.3.13 (2026-04-08)
- Fix: PreToolUse hook now outputs
additionalContextJSON so Claude actually sees the graph reminder before Glob/Grep calls (#83) - Fix: Go AST method receivers and type declarations now use package directory scope, eliminating disconnected duplicate type nodes across files in the same package (#85)
- Fix: PDFs inside Xcode asset catalogs (
.imageset,.xcassets) are no longer misclassified as academic papers (#52) - Fix:
_resolve_cross_file_importsis now guarded withif py_pathsand wrapped in try/except so a Python parser crash can't abort extraction for non-Python files (#52) - Fix: Skill intermediate files (
.graphify_*.json) now live ingraphify-out/instead of project root, preventing git pollution (#81)
0.3.12 (2026-04-07)
- 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)
0.3.11 (2026-04-07)
- Fix: Louvain fallback hangs indefinitely on large sparse graphs — added
max_level=10, threshold=1e-4to prevent infinite loops while preserving community quality (#48)
0.3.10 (2026-04-07)
- Fix: Windows UnicodeEncodeError during
graphify install— replaced arrow character with->in all print statements (#47) - Add: skill version staleness check — warns when installed skill is older than the current package, across all platforms (#46)
0.3.9 (2026-04-07)
- Add:
follow_symlinksparameter todetect()andcollect_files()— opt-in symlink following with circular symlink cycle detection (#33) - Fix:
watch.pynow usescollect_files()instead of manual rglob loop for consistency - Docs: Codex uses
$graphify .not/graphify .(#36) - Test: 5 new symlink tests (367 total)
0.3.8 (2026-04-07)
- Add: C# inheritance and interface implementation extraction —
base_listnow emitsinheritsedges for both simple (identifier) and generic (generic_name) base types (#45) - Add:
graphify query "<question>"CLI command — BFS/DFS traversal ofgraph.jsonwithout needing Claude Code skill (--dfs,--budget N,--graph <path>flags) - Test: 2 new C# inheritance tests (362 total)
0.3.7 (2026-04-07)
- Add: Objective-C support (
.m,.mm) —@interface,@implementation,@protocol, method declarations,#importdirectives, message-expression call edges - Add:
--obsidian-dir <path>flag — write Obsidian vault to a custom directory instead ofgraphify-out/obsidian - Fix: semantic cache was only saving 4/17 files — relative paths from subagents now resolved against corpus root before existence check
- Fix: 75 validation warnings per run for
file_type: "rationale"— added"rationale"toVALID_FILE_TYPES - Test: 6 Objective-C tests;
.m/.mmadded totest_collect_files_from_dirsupported set (360 total)
0.3.0 (2026-04-06)
- Add: multi-platform support — Codex (
skill-codex.md), OpenCode (skill-opencode.md), OpenClaw (skill-claw.md) - Add:
graphify install --platform <codex|opencode|claw>routes skill to correct config directory - Add:
graphify codex install/opencode install/claw install— writes AGENTS.md for always-on graph-first behaviour - Add:
graphify claude uninstall/codex uninstall/opencode uninstall/claw uninstall - Add: MIT license
- Fix:
build()was silently dropping hyperedges when merging multiple extractions - Refactor:
extract.py2527 → 1588 lines — replaced 12 copy-pasted language extractors withLanguageConfigdataclass +_extract_generic() - Docs: clustering is graph-topology-based (no embeddings) — explained in README
- Docs: all missing flags documented (
--cluster-only,--no-viz,--neo4j-push,query --dfs,query --budget,add --author,add --contributor)
0.2.2 (2026-04-06)
- Add:
graphify claude install— writes graphify section to local CLAUDE.md + PreToolUse hook in.claude/settings.json - Add:
graphify claude uninstall— removes section and hook - Add:
graphify hook install— installs post-commit and post-checkout git hooks (platform-agnostic) - Add:
graphify hook uninstall/hook status - Add:
graphify benchmarkCLI command - Fix: node deduplication documented at all three layers
0.1.8 (2026-04-05)
- Fix: follow-up questions now check for wiki first (graphify-out/wiki/index.md) before falling back to graph.json
- Fix: --update now auto-regenerates wiki if graphify-out/wiki/ exists
- Fix: community articles show truncation notice ("... and N more nodes") when > 25 nodes
- UX: pipeline completion message now lists all available flags and commands so users know what graphify can do
0.1.7 (2026-04-05)
- Add:
--wikiflag — generates Wikipedia-style agent-crawlable wiki from the graph (index.md + community articles + god node articles) - Add:
graphify/wiki.pymodule withto_wiki()— cross-community wikilinks, cohesion scores, audit trail, navigation footer - Add: 14 wiki tests (245 total)
- Fix: follow-up question example code now correctly splits node labels by
_to extract verb prefixes (previous version useddef/fnprefix matching which always returned zero results)
0.1.6 (2026-04-05)
- Fix: follow-up questions after pipeline now answered from graph.json, not by re-exploring the directory (was 25 tool calls / 1m30s; now instant)
- Skill: added "Answering Follow-up Questions" section with graph query patterns
0.1.5 (2026-04-05)
- Perf: semantic extraction chunks 12-15 → 20-25 files (fewer subagent round trips)
- Perf: code-only corpora skip semantic dispatch entirely (AST handles it)
- Perf: print timing estimate before extraction so the wait feels intentional
- Fix: 5 skill gaps - --graphml in Usage table, --update manifest timing, query/path/explain graph existence check, --no-viz clarity
- Refactor: dead imports removed (shutil, sys, inline os); _node_community_map() helper replaces 8 copy-pasted dict comprehensions; to_html() split into _html_styles() + _html_script(); serve.py call_tool() if/elif chain replaced with dispatch table
- Test: end-to-end pipeline integration test (detect → extract → build → cluster → analyze → report → export)
0.1.4 (2026-04-05)
- Replace pyvis with custom vis.js HTML renderer - node size by degree, click-to-inspect panel with clickable neighbors, search box, community filter, physics clustering
- HTML graph generated by default on every run (no flag needed)
- Token reduction benchmark auto-runs after every pipeline on corpora over 5,000 words
- Fix: 292 edge warnings per run eliminated - stdlib/external edges now silently skipped
- Fix:
build()cross-extraction edges were silently dropped - now merged before assembly - Fix:
pip install graphify→pip install graphifyyin skill Step 1 (critical install bug) - Add:
--graphmlflag implemented in skill pipeline (was documented but not wired up) - Remove: pyvis dependency, dead lib/ folder, misplaced eval reports from tests/
- Add: 5 HTML renderer tests (223 total)
0.1.3 (2026-04-04)
- Fix:
pyproject.tomlstructure -requires-pythonanddependencieswere incorrectly placed under[project.urls] - Add: GitHub repository and issues URLs to PyPI page
- Add:
keywordsfor PyPI search discoverability - Docs: README clarifies Claude Code requirement, temporary PyPI name, worked examples footnote
0.1.1 (2026-04-04)
- Add: CI badge to README (GitHub Actions, Python 3.10 + 3.12)
- Add: ARCHITECTURE.md - pipeline overview, module table, extraction schema, how to add a language
- Add: SECURITY.md - threat model, mitigations, vulnerability reporting
- Add:
worked/directory with eval reports (karpathy-repos 71.5x benchmark, httpx, mixed-corpus) - Fix: pytest not found in CI - added explicit
pip install pyteststep - Fix: README test count (163 → 212), language table, worked examples links
- Docs: README reframed as Claude Code skill; Karpathy problem → graphify answer framing
0.1.0 (2026-04-03)
Initial release.
- 13-language AST extraction via tree-sitter (Python, JS, TS, Go, Rust, Java, C, C++, Ruby, C#, Kotlin, Scala, PHP)
- Leiden community detection via graspologic with oversized community splitting
- SHA256 semantic cache - warm re-runs skip unchanged files
- MCP stdio server -
query_graph,get_node,get_neighbors,shortest_path,god_nodes - Memory feedback loop - Q&A results saved to
graphify-out/memory/, extracted on--update - Obsidian vault export with wikilinks, community tags, Canvas layout
- Security module - URL validation, safe fetch with size cap, path guards, label sanitisation
graphify installCLI - copies skill to~/.claude/skills/and registers inCLAUDE.md- Parallel subagent extraction for docs, papers, and images