Reading Godot scenes without opening the editor
by Fireal Software · ~8 min read
There’s a category of Godot work where booting the editor is overkill. You want to know what nodes are in a scene. What textures a scene depends on. What autoloads a project defines. Whether a scene has any Camera3D nodes. These are all questions you can answer by reading text files.
Godot Catalyst ships offline parsers for TSCN, TRES, and project.godot. They’re pure TypeScript, they run without Godot being installed, and they’re fast.
Why offline matters
The normal Godot Catalyst flow is: Claude talks to the TypeScript MCP server, which talks to a WebSocket server inside the Godot editor, which talks to GDScript handlers that read or mutate state. Every call is a round trip.
For read-only analysis this is a lot of overhead. If Claude wants to check what scripts are in your project, it doesn’t need the editor’s scene graph — a filesystem scan and some string parsing will do. If it wants to know what sub-resources a scene uses, a TSCN parse is enough.
There’s also the closed-project case. You want Claude to analyze a game repo you haven’t opened in weeks. Opening Godot takes 5–30 seconds, recompiles the .NET build if it’s a C# project, re-imports assets, scans the filesystem. For a five-minute analysis task, the startup cost dominates.
Offline parsers skip all of this. Claude reads the text files directly.
The tools
Ten offline tools live in src/tools/file-tools.ts, backed by parsers in src/parsers/:
godot_parse_tscn— a scene file to structured JSONgodot_generate_tscn— structured JSON to a scene filegodot_parse_tres— a resource file to structured JSONgodot_generate_tres— structured JSON to a resource filegodot_read_project_godot— parse project.godot INIgodot_modify_project_godot— merge settings into project.godotgodot_read_file— read any project filegodot_list_project_files— recursive file listing with globbinggodot_validate_tscn— check a TSCN for structural issuesgodot_create_gdscript— generate GDScript from templates (Node script, CharacterBody2D/3D, autoload, signal emitter, state machine)
All of these are tagged cli in the tool mode map, which means they’re available in every mode — including pure offline use with no Godot project even installed. You can set GODOT_TOOL_MODE=cli and get a 14-tool server that answers questions about .tscn files from anywhere.
What a parsed scene looks like
Ask godot_parse_tscn on a typical scene and you get back structured JSON:
{
"format": 3,
"uid": "uid://c8x2l3m4",
"loadSteps": 5,
"ext_resources": [
{"type": "Script", "path": "res://scripts/player.gd", "id": "1_abc"},
{"type": "Texture2D", "path": "res://art/player.png", "id": "2_def"}
],
"sub_resources": [
{"type": "RectangleShape2D", "id": "RectangleShape2D_xyz",
"properties": {"size": "Vector2(32, 48)"}}
],
"nodes": [
{"name": "Player", "type": "CharacterBody2D",
"properties": {"script": "ExtResource(\"1_abc\")"}},
{"name": "Sprite", "type": "Sprite2D", "parent": ".",
"properties": {"texture": "ExtResource(\"2_def\")"}},
{"name": "Collision", "type": "CollisionShape2D", "parent": ".",
"properties": {"shape": "SubResource(\"RectangleShape2D_xyz\")"}}
],
"connections": []
}
Claude can reason over this without the editor knowing the file exists. Questions it can answer from the JSON alone:
- What nodes are in the scene? (walk
nodes[]) - What assets does it depend on? (look at
ext_resources[]) - Is there a script attached to the root? (check
nodes[0].properties.script) - Are any signals wired? (check
connections[]) - What sub-resources are defined inline? (walk
sub_resources[])
For a “where is X used” query across the project, Claude can list all .tscn files via godot_list_project_files and parse each one in parallel.
When to prefer offline, when to prefer the editor
Use the offline parsers when:
- The project doesn’t need to be open in Godot (closed, unfamiliar, or remote)
- You’re doing read-only analysis (no mutation)
- You want to avoid editor startup time or refresh cycles
- You’re in CLI mode with no WebSocket connection
- You want to batch process many files (parse 50 scenes in parallel)
Use the editor-backed tools (godot_get_scene_tree, godot_set_node_properties, etc.) when:
- You’re mutating scene state and want undo/redo
- You need runtime info (current selection, open scene, dirty flags)
- You’re using the plugin’s helpers that wrap multiple operations
- You want the scene’s parsed node references, not raw property strings
The offline parsers return properties as their serialized string form ("Vector2(32, 48)"), because that’s what’s in the file. The editor-backed tools return typed JSON ({"x": 32, "y": 48}) because the editor has already deserialized the values. For most analysis work the string form is fine; when you need to do math on a vector, convert or go through the editor.
Offline mutation is supported too
godot_generate_tscn and godot_generate_tres write files. You pass structured JSON, you get a valid scene file. This is how Claude can scaffold a project without the editor running:
godot_read_project_godotto check the current project settingsgodot_modify_project_godotto add autoloadsgodot_create_gdscriptto generate the script templatesgodot_generate_tscnto build the scenes
Open Godot afterwards and everything is there. The scenes parse cleanly because the generators respect the TSCN format — external resource IDs, subresource IDs, property serialization, connection flags. godot_validate_tscn double-checks a generated file against the format invariants before you commit.
Example: finding unused scenes
1. godot_list_project_files({"pattern": "*.tscn"})
→ list of all .tscn paths
2. For each .tscn, godot_parse_tscn and collect all ext_resources
that reference other .tscn files (instance references)
3. Find .tscn files that appear in the filesystem but never as
ext_resources in any other scene
4. Report the orphans
This is ~20 lines of logic Claude can write on the fly. No editor. No import reconcile. No waiting for Godot to load.
Example: migrating a property name across scenes
You renamed target_speed to max_speed on a CharacterBody2D-derived script. A dozen scenes set the property directly in their TSCN. Find-and-replace in the files is fragile (might match unrelated strings). The offline parser lets Claude walk each scene, find nodes with a script property pointing to the renamed script, and change the property name specifically.
1. godot_list_project_files({"pattern": "*.tscn"})
2. For each, godot_parse_tscn
3. Find nodes whose script ext_resource points to the renamed file
4. Rewrite the node's properties: drop `target_speed`, add `max_speed`
5. godot_generate_tscn to save the updated file
Claude does this with precision because the parse result is structured. Find-and-replace would hit false positives.
The parsers are boring on purpose
src/parsers/tscn-parser.ts, tres-parser.ts, and project-godot-parser.ts are the whole implementation. TSCN and TRES are an INI-like format with a specific schema for sections ([gd_scene], [ext_resource], [sub_resource], [node], [connection]). The parser tokenizes line by line, collects sections, parses property lines into key/value pairs, and returns a typed object.
No tree-sitter, no grammar file, no Godot runtime dependency. Just careful regex and some state. This is deliberate — the format is stable enough that a hand-written parser is easier to maintain than a grammar, and it runs in under 10ms on a typical scene.
For pure CLI use with no editor:
GODOT_TOOL_MODE=cli npx godot-catalyst
Turn Claude into a Godot co-developer
Godot Catalyst is an MCP server with 240+ tools for Godot 4.x. GDScript LSP, DAP debugging, offline parsing, asset pipelines. 7-day free trial, $25 one-time.
Try Godot Catalyst