Godot · GDScript
Dead code, found and gone.
gdlint reads every script in your Godot project — and every scene and autoload entry
that could be pointing at one — then tells you what nothing references. Leftover
prints, orphaned .gd.uid files and dynamic has_method()
calls too. Run it with -fix and it takes them out.
go install github.com/aviorstudio/gdlint@latest Go · one static binary · Linux, macOS and Windows
$ gdlint
=== ERRORS (will be removed with -fix) ===
Unused files: 3
• addon/autoload.gd
• addon/plugin.gd
• addon/src/core/router.gd
Print statements: 1
• addon/plugin.gd:59: print("GD Router: Created route map at %s." % RouteMapGenera...
Orphaned UID files: 2
• addon/src/route_transition_util.gd.uid
• addon/src/router_service.gd.uid
❌ has_method() calls (ALWAYS ERRORS): 2
• addon/src/core/router.gd:121: if not route.guard.has_method("can_enter"):
• addon/src/core/router.gd:131: if not host.has_method("mount_route"):
Explicit Variant usages (disallowed once enabled): 1
• addon/src/core/router.gd:99: func get_param(key: String, default: Variant = null) -> Vari...
=== SUMMARY ===
❌ 9 errors found
Run with -fix to remove all errors exit 1 errors block-warn adds the warnings-fix removes the errors
01 It knows what it is not
gdlint has no opinion on your directory names, your required sibling files, which
layer may import which, or who owns an autoload. Those rules are yours and they
change per project — a hygiene checker that guessed at them would be wrong in every
repo but the one it was written in.
02 Unused means nothing points at it
Before a script is called dead, gdlint follows preload, load
and file-path extends through every .gd, the
ext_resource and script paths inside every
.tscn, and the autoload list in project.godot. A scene
referencing a script counts, even when no code does.
03 Four rules on, the rest asked for
A project with no config gets prints, stray pass, orphaned
.gd.uid files and tab indentation. Everything else stays quiet until
gdlint.json switches it on, because the rest is house style and gdlint
does not know yours yet.
gdlint init
Every rule, and what it ships as.
gdlint init writes this list into gdlint.json with the defaults
below. Errors block and exit non-zero; warnings only appear under -warn.
Files can be excluded wholesale, or only from the unused-code rules, or only from the
Variant rule.
-fix acts on the errors — it deletes functions, signals, constants and whole
files that static analysis believes are unused. Reflection, a string-built
call() or a resource path assembled at runtime is invisible to it. Turn the
unused rules on, read what they report, and keep the change reviewable.
| Rule | Catches | Default |
print_statements | print() and debug output left behind | on |
pass_statements | pass in a body that already has statements | on |
orphaned_uids | a .gd.uid whose script is gone | on |
indentation | spaces where GDScript indents with tabs | on |
unused_functions | functions nothing calls | off |
unused_signals | signals nothing connects or emits | off |
unused_constants | constants nothing reads | off |
unused_enums | enums and enum values nothing reads | off |
unused_class_names | class_name nothing refers to | off |
unused_files | scripts no script, scene or autoload points at | off |
comments | comments outside the allowed prefixes | off |
has_method | dynamic dispatch instead of a typed call | off |
variant_usage | explicit Variant in a signature | off |
missing_return_types | public functions with no return annotation | off |
single_use_functions warning | functions with exactly one caller | off |
empty_functions warning | functions with nothing in them | off |
Ship what you use.
Not what you wrote.
PROJECT.GODOTEVERY .GD AND .TSCNWHAT NOTHING NEEDS