Skip to content

Verb reference

Chris Dowin edited this page Oct 15, 2026 · 5 revisions

Verb reference

Introspection (pure parse):

verb what it answers
scene <file> [--props] [--paths] a .tscn/.tres's node tree and resources; --props every [resource]/[sub_resource] property value, packed data elided, each id verbatim — the address the write verbs take
scene-diff <file> [--git <ref>] · scene-diff <old> <new> a structural diff — nodes, properties, resources, reparents — keyed the way the write verbs address them
refs <symbol> [--tests] every reference to a symbol, grouped by kind — including what Godot wires: a scene [connection] naming it as signal= or method= prints under scene connections, and an autoload name is indexed like a class_name (its project.godot entry the definition, Name. / Name) / Name, a typed ref); a bare handler in is_connected(…, h) / disconnect(…, h) is a call site; signal hits on a receiver the index cannot type (x.sig.connect(, emit_signal(&"sig", connect("sig", is_connected("sig", has_signal("sig", has_user_signal("sig", Signal(obj, "sig") print under dynamic (untyped receiver), and (no references found) prints only when that bucket is empty too
orphans [--tests] tracked files nothing references
autoloads the project.godot autoload census, grouped by suffix, layout flagged
stats [<dir>...] [--by dir] [--json] [--ratchet FILE] files, lines and code lines (non-blank, non-comment, docstrings are comment) per bucket: .gd by role (game, tests, tools, vendored, from [stats]), .gdshader, .tscn, .tres; one row per tests subdir with a func test_ count; --by dir splits game .gd by top-level dir; zero files scanned exits 1
tiles <file> [--layer NAME] [--cols] [--rows] [--at X,Y] [--region X0,Y0,X1,Y1] a TileMapLayer's grid: cell count, bounds, tile-kind histogram, per-column/row counts

Scene surgery (edits only the lines it was asked to, or refuses and says why):

verb what it does
scene set <file> <node-path> <prop> <value> replace or append one property on one node
scene set <file> --resource <prop> <value> · --sub-resource <id> <prop> <value> the same on a .tres's [resource] body or a [sub_resource] by the id scene --props prints
scene rename <file> <node-path> <new-name> rename a node and every NodePath, parent= and animation track that references it — never prose, never an export name
scene add <file> <parent-path> <name> <type> [--script res://x.gd] add a node; a --script ref is minted uid-in-refs from the sidecar, or refused
scene add <file> <parent-path> <name> --instance res://x.tscn add an instance node; its ref is minted from the scene's own uid, or refused
scene rm <file> <node-path> remove a node with its descendants, connections and editable markers; prunes an ext_resource nothing else uses
scene reparent <file> <node-path> <new-parent> move a subtree and fix its NodePaths
scene connect <file> <signal> <from> <to> <method> [--flags N] · scene disconnect … author or remove one [connection]; ambiguous matches are refused, --flags names one
scene canonicalize <file>... [--elide-defaults] [--respell] [--order] restore what PackedScene.pack() drops — uid-in-refs, the header uid, index= on instance children; --elide-defaults also removes assignments equal to the script's @export default; --respell re-spells floats in the saver's shortest form and wraps a bare list on an Array[T] export as Array[T]([...]); --order puts a scripted section's properties in declaration order — line edits only, anything unprovable named and left alone
refs --retarget <old-res-path> <new-res-path> [--dry-run] after a git mv: rewrite every ext_resource path and exact preload/load literal naming the old path; anything unprovable is SKIPPED with a reason, and skips exit 1
refs --rename <old> <new> [--dry-run] rename a class_name, method, signal or autoload across .gd, .tscn, .tres and project.godot as one plan — only the identifier token at each typed hit, a [connection]'s signal=/method= value, an autoload's key; all or nothing: an <old> or <new> the engine also names (a method or signal on any class — play, pressed, _ready), any dynamic hit, string or unproven occurrence, a defined <new> or an undefined <old> refuses the whole rename with every site named (exit 1), and a repeat prints already renamed; a res:// path that matches is never rewritten, only listed as a PATH line; tests/ is always in scope
autoloads add <Name> <res://path> [--dry-run] · autoloads rm <Name> declare or remove one project.godot autoload as an enabled singleton (Name="*res://path"); a missing file, a non-canonical path, a bad name (not an identifier, an engine class or a project class_name), a name already pointing elsewhere or declared disabled is refused, and a repeat is a no-op
tiles paint <file> --layer NAME --region X0,Y0,X1,Y1 --tile SRC/AX,AY[/ALT] · tiles erase … fill or clear a rectangle of one TileMapLayer; only that property's base64 is regenerated

Localization (pure parse; writes one file, or refuses):

verb what it does
pot [--dry-run | --check] write the POT that the editor's POT Generation writes, byte for byte (Godot 4.7), from project.godot's internationalization/locale/translations_pot_files to [pot] output; prints files scanned and msgids written; --check exits 1 on drift with a MISSING/EXTRA line per msgid, or one DRIFT line when only references, comments or order moved; a non-.gd entry, an empty manifest, a parse error or a constant only the editor can fold is refused with exit 2

The installer: install-runners [--force] [--diff] — see Runners and install-runners.

Agent UI skill: install-skills [--runtime codex|claude] [--dest ROOT] [--check] [--diff] [--force] (3.9.0). Installs bundled godot-ui below a skills root: .agents/skills for Codex or .claude/skills for Claude by default. --dest selects another root, including user scope. --check is read-only and returns 1 for missing/outdated files; --diff previews without writing. Differing regular files require --force. Symlinks below the selected root are refused; an explicitly selected root may itself be a symlink. The skill defines component contracts, native layout ownership and rendered-state proof; static tooling does not certify visual fit.

The gates: check <gate> for one, check all for the eight, check <gate> --help for that gate's contract, config and scope. check uid --fix applies the repairs the gate already computes.

See also: The eight gates, Configuration reference.

Comment and test-code budgets

godot-devkit stats [dir ...] [--by dir] [--json] [--ratchet FILE] reports physical/code/comment/doc/inline/docstring/test counts from git-known files. The shared GDScript tokenizer distinguishes real comments from hashes and escaped quotes in strings. comments includes own-line # comments and standalone docstrings; docs is the ## subset and is not added twice. Inline comment and docstring counts are separately limited so prose cannot move to evade a cap.

Capture a baseline once with godot-devkit stats --json > tools/ci/stats-baseline.json. Run the same scope and role roots with godot-devkit stats --ratchet tools/ci/stats-baseline.json. Comment/doc/inline/docstring limits and test-code/case limits must not grow. Production code counts are context rather than a dilution ratio. Existing baseline limits are checked against origin/main, or HEAD in a standalone repository; scope changes, deleted caps and cap increases fail. Malformed input exits 2 and a zero-file scan fails.

Introduced in 3.8.0. Table readers must accept the new columns; JSON fields are additive. No engine process or runtime dependency is introduced.

Clone this wiki locally