A fork of safishamsi/graphify that adds first-class Godot / GDScript support to the knowledge-graph pipeline.
Upstream graphify ingests code, docs, papers, and media into a clustered graph you can query from your AI assistant. It ships AST extractors for ~23 languages — Python, TypeScript, Go, Rust, Swift, etc. — but nothing for Godot, so any Godot project gets treated as docs-only.
This fork adds:
.gd— tree-sitter AST extraction (via thegdscriptgrammar bundled intree-sitter-language-pack).tscn— regex-based scene extraction (ext_resource paths, script attachment, node instancing, signal connections).tres— regex-based resource extraction (ext_resource paths, script class binding)
| Construct | Graph effect |
|---|---|
class_name X |
File gets an alias node X so external refs resolve by class name |
extends Y (top-level) |
file --inherits--> Y |
class Inner extends Base: |
file --contains--> Inner, Inner --inherits--> Base, methods hang off Inner |
func foo() |
Function node, file --contains--> foo() |
signal bar(...) |
Signal node, file --contains--> bar(signal) |
preload("res://x.gd") / load("res://x.gd") |
file --imports_from--> x.gd (res:// resolved via project.godot root) |
signal.emit(...) |
caller_fn --emits--> signal |
signal.connect(cb) |
signal --connected_to--> cb (when both are local) |
| Function body | caller_fn --calls--> callee (local + cross-file INFERRED) |
| Construct | Graph effect |
|---|---|
[ext_resource path="res://..."] |
scene --imports_from--> target |
[node ... instance=ExtResource("id")] |
scene --instances--> target_scene |
[connection signal=X to=Y method=M] |
Deferred call to method M — resolved to the method node in the script attached to the scene |
| Construct | Graph effect |
|---|---|
[ext_resource path="res://..."] |
resource --imports_from--> target |
Tested against a 1,000-file Godot 4.6 project (Meridian: Breach Zones —
~500 .gd, 50 .tscn, 660 .tres):
AST extraction: 1031 files in ~7s, 0 errors
Resulting graph: 6,872 nodes · 13,431 edges
calls: 6,274
contains: 5,316
imports_from: 856
inherits: 311
aliases: 216
emits: 103
instances: 8
connected_to: 4
Before this fork, graphify treated the same project as 0 code files / 54 docs.
Works on Windows, macOS, Linux. Requires Python 3.10–3.13.
# Clone
git clone https://github.com/hidalgob/graphify-godot.git
cd graphify-godot
# Install as editable replacement for upstream graphifyy
pip install -e .If upstream graphifyy was previously installed via pip, its package files
may sit in site-packages and shadow this fork. Either:
pip uninstall graphifyy # then re-run pip install -e .or drop a priority .pth file into your user site-packages:
python -c "import site, pathlib; p = pathlib.Path(site.getusersitepackages()) / '_graphify_godot_priority.pth'; p.write_text(f'import sys; sys.path.insert(0, r\"{pathlib.Path.cwd()}\")')"Verify:
python -c "import graphify; print(graphify.__file__)"
# → .../graphify-godot/graphify/__init__.pyUsage is identical to upstream:
python -m graphify update /path/to/your/godot/projectThe GDScript extractor walks up from each source file looking for
project.godot — that marks Godot's project root, and all res://foo/bar.gd
references resolve relative to it. The result is cached per parent directory
so it's cheap.
Godot projects typically want to exclude:
# Third-party / generated
addons/
.godot/
imported_models/
# Build outputs
bin/
/android/
*.apk
# Graph output (auto-skipped, but explicit is cleaner)
graphify-out/
# Tests (optional — they inflate communities around assert_*)
tests/
Put this in .graphifyignore at your project root.
- No
.gdshaderparsing. Shaders are ignored. - Cross-file
signal.connect(cb)is partial. When a file callsEventBus.enemy_killed.connect(_on_enemy_killed), the signal lives inevent_bus.gd(a different file) and the connect call sits in your file. Theconnected_toedge is emitted only when signal + callback are in the same file. Cross-file wiring shows up as a genericcallsedge on the callback instead. - No inner-class scope awareness. A method call inside
class InnerDatathat targets another inner method is resolved by global label lookup, which can collide with a top-level function of the same name. - Dynamic loads (
load(some_var), directory scans) are invisible. Godot projects that enumerateres://balance/achievements/at runtime will have those.tresfiles appear as orphan nodes. This is a limitation of static extraction — no way around it without running Godot itself.
This is a personal fork, not a merge candidate (yet). Upstream is moving fast (~1.5 releases/day as of April 2026) and has a low merge rate on community language PRs — nine competing language backends sit open unmerged. If you want GDScript support and don't want to track upstream churn, use this. If upstream adds official Godot support later, I'll deprecate this in favor of that.
Base version: upstream graphifyy==0.4.23. Periodically rebased.
MIT — same as upstream. Credit to Safi Shamsi for the graphify base.