gdscript-lsp
A Claude Code plugin that gives Claude real-time GDScript intelligence inside
your Godot project — completions, diagnostics, go-to-definition, hover docs,
references, and symbols — by bridging Claude Code's stdio LSP transport to the
TCP language server that ships inside the Godot editor.
When no Godot LSP is reachable, the plugin auto-launches Godot in headless
editor mode for your project. When you already have the editor open, it reuses
that instance.
Status
End-to-end verified against:
- Godot 4.6.3.stable.mono on macOS (Homebrew cask
godot-mono)
- Node 18+ runtime
- Claude Code 2.x with
/plugin install
A clean initialize round-trip from Claude Code through the bridge to a fresh
headless Godot returns the full ServerCapabilities (completion, definition,
hover, references, document/workspace symbols, signature help, semantic
tokens, code actions) in under 3 seconds once the headless editor has finished
its first-time project scan.
What you get
Once installed and inside a Godot project, you can ask Claude things like:
- "Where is
apply_damage defined?" — go-to-definition / find-references
- "What does
Node._physics_process(delta) return?" — hover docs from Godot's
built-in class database
- "List all functions in
player.gd" — document symbols
- "Find every place that emits
health_changed" — workspace symbol search
- "Why does this script not compile?" — live diagnostics from Godot's parser
All of this is served by Godot's own GDScript LSP, so the answers reflect your
actual project, your autoloads, and your installed plugins — not a generic
static parser.
Supported file types: .gd, .gdshader, .gdshaderinc.
Resource & scene validation (.tscn / .tres)
In addition to the GDScript language server, this plugin ships a second,
zero-dependency language server that statically validates Godot text scenes
(.tscn) and resources (.tres). It needs no running Godot instance.
It reports, with fix suggestions where possible:
| Check | Severity | Fix offered |
|---|
Referenced ext_resource file does not exist on disk | Error | "Did you mean res://…?" |
ExtResource("id") / SubResource("id") id not declared in the file | Error | Nearest declared id |
Missing required tag attributes (path/type/id, connection fields, …) | Error | — |
[resource] in a .tscn / [node] in a .tres | Error | — |
format newer than this Godot supports | Error | — |
Invalid uid://… | Warning | Remove the uid attribute |
Duplicate ext_resource / sub_resource id | Warning | Renumber |
load_steps does not match the resource count | Info | Correct the number |
Accuracy: the validator mirrors the structural rules of Godot's own text
parser (resource_format_text.cpp), so it does not produce false positives on
valid files. Property/type-level validation (which Godot only performs at scene
instantiation) is not done statically — that is planned as an optional
Godot-backed deep-check in a future version. Binary .scn/.res files are out
of scope. project.godot itself is not validated either — its presence is only
used to locate the project root (and to suppress missing-file checks when no
project root is found).
Optional deep-check (loads scenes through Godot)
When a Godot binary is found on your machine, saving a .tscn/.tres also
runs a project-wide deep-check: a bundled headless Godot pass that actually
loads every scene/resource and reports errors the static validator cannot see,
each mapped to res://file:line:
- a
sub_resource of an unknown/uninstantiable type,
- a missing dependency (with Godot's own fidelity),
- any resource that fails to load.
(GDScript parse errors are reported separately by the GDScript language server.)
Behavior:
- Runs automatically on save, but only when Godot is locatable (same
discovery as the GDScript bridge, including the Mono builds). It is
debounced and project-wide (one headless pass per save burst,
surfacing errors across all files, even ones you don't have open).
- It needs the project's
.godot/ import cache (open the project in Godot
once first).
- Disable it with
--no-deep-check in the godot-resource args.
- If you install Godot after starting Claude Code, restart the session so the
deep-check can pick it up.
Warning: ResourceLoader.load() executes any attached @tool script's
_init. If your project has tool scripts with side effects (file writes,
network calls), use --no-deep-check.
Scope: the deep-check is load-only. It does not validate property
types (Godot silently coerces those) and does not flag unknown node
type= classes (that requires instantiating scenes, which would run their
@tool scripts — unsafe as a default). Instantiation-level checks are a
possible future enhancement.