Skip to content
Automation
Skill

/gdtoolkit

Lint and format GDScript files using gdtoolkit (gdlint + gdformat). Use after writing or modifying .gd files, when asked to check code style, fix lint errors, format code, or set up linting configuration. Also use when gdlint/gdformat errors appear in output and need diagnosis.

From plugin
godotmaker
51141 skills7 agents14 hooks
Install
$ npx -y skills add RandallLiuXin/GodotMaker --skill gdtoolkit --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/gdtoolkit

Context preview

The summary Claude sees to decide when to auto-load this skill.

Lint and format GDScript files using gdtoolkit (gdlint + gdformat). Use after writing or modifying .gd files, when asked to check code style, fix lint errors, format code, or set up linting configuration. Also use when gdlint/gdformat errors appear in output and need diagnosis.

SKILL.md

gdtoolkit.SKILL.md
name: gdtoolkit
description: |
  Lint and format GDScript files using gdtoolkit (gdlint + gdformat).
  Use after writing or modifying .gd files, when asked to check code style,
  fix lint errors, format code, or set up linting configuration.
  Also use when gdlint/gdformat errors appear in output and need diagnosis.
  Does NOT require Godot — runs as a standalone Python tool.

gdtoolkit — GDScript Lint & Format

> **Currently disabled (v0.3.4+).** `gm-verify` no longer invokes > `gdlint` / `gdformat`, and `gm-build` / `gm-fixgap` have removed this > skill from their Available Skills tables. Reason: repeated > `gdtoolkit/linter/class_checks.py:144 NotImplementedError` crashes on > common ECS-style GDScript class shapes, plus low signal-to-noise vs > the headless compile + reviewer pattern checks. Re-enabling tracked as > ROADMAP `R-112`. The reference content below is preserved for ad-hoc > use outside the pipeline and for the future re-enablement.

Wraps two CLI tools from the `gdtoolkit` Python package:

  • **gdlint** — static analysis and style checking
  • **gdformat** — deterministic auto-formatter

Prerequisites

pip install "gdtoolkit==4.*"    # Godot 4 projects
pip install "gdtoolkit==3.*"    # Godot 3 projects

Verify installation: `gdlint --version && gdformat --version`

If not installed, tell the user and offer to install. The version major must match the project's Godot major version (read from `project.godot` `config/features`).

Lint workflow

Run gdlint

gdlint path/to/file.gd          # single file
gdlint path/to/directory/       # all .gd files recursively

Interpret output

Each problem is one line on stderr:

path/to/file.gd:42: Error: Function name "MyFunc" is not valid (function-name)

Format: `{file}:{line}: Error: {message} ({rule-id})`

Exit codes:

  • **0** — no problems (stdout: `Success: no problems found`)
  • **1** — problems found (stderr: `Failure: N problem(s) found`)

Fix lint issues

For each reported issue, either: 1. **Fix the code** — rename to match convention, remove unused arg, reorder members 2. **Suppress inline** — when the violation is intentional:

   # gdlint:ignore = rule-id
   var _unusedButNeeded := 0   # this line + next line are suppressed

3. **Suppress region** — for larger blocks:

   # gdlint: disable=function-name
   func ALLCAPS_required_by_engine():
       pass
   # gdlint: enable=function-name

When suppressing, always add a brief comment explaining why.

Format workflow

Run gdformat

gdformat path/to/file.gd        # format in-place
gdformat path/to/directory/      # format all .gd files
gdformat --check path/           # check only, don't modify (exit 1 if changes needed)
gdformat --diff path/            # show unified diff on stderr, don't modify

Exit codes:

  • **0** — already formatted / formatting succeeded
  • **1** — check mode found differences / parse error / safety check failed

Safety checks

gdformat runs three safety checks by default (disable with `--fast`):

  • **TreeInvariantViolation** — parse tree changed after formatting
  • **FormattingStabilityViolation** — formatting isn't idempotent
  • **CommentPersistenceViolation** — comments were lost

If a safety check fails, report the error to the user — do NOT use `--fast` to bypass it. This likely indicates a gdtoolkit bug; the file should be formatted manually or the problematic section excluded.

Rule reference

Naming rules (regex-configurable)

| Rule ID | Default convention | Example | |---|---|---| | `function-name` | snake_case or `_on_PascalCase_signal` | `move_player`, `_on_Button_pressed` | | `class-name` | PascalCase | `PlayerController` | | `sub-class-name` | _PascalCase (leading underscore) | `_InternalHelper` | | `signal-name` | snake_case | `health_changed` | | `class-variable-name` | snake_case or _private | `speed`, `_cache` | | `function-variable-name` | snake_case | `local_var` | | `function-argument-name` | snake_case or _unused | `target_pos`, `_ignored` | | `loop-variable-name` | snake_case or _unused | `item`, `_i` | | `constant-name` | UPPER_SNAKE_CASE | `MAX_SPEED` | | `enum-name` | PascalCase | `Direction` | | `enum-element-name` | UPPER_SNAKE_CASE | `NORTH`, `SOUTH_EAST` |

Code quality rules

| Rule ID | Default | What it checks | |---|---|---| | `max-returns` | 6 | Too many return statements per function | | `max-public-methods` | 20 | Too many public methods per class | | `function-arguments-number` | 10 | Too many function arguments | | `max-file-lines` | 1000 | File too long | | `max-line-length` | 100 | Line too long |

Style rules

| Rule ID | What it checks | |---|---| | `unnecessary-pass` | `pass` in non-empty body | | `duplicated-load` | Same resource loaded twice | | `expression-not-assigned` | Standalone expression with no effect | | `unused-argument` | Argument never used (fix: prefix with `_`) | | `comparison-with-itself` | `x == x` | | `private-method-call` | Calling `_private_method()` from outside | | `class-definitions-order` | Members not in canonical order (see below) | | `trailing-whitespace` | Trailing spaces | | `mixed-tabs-and-spaces` | Mixed indentation | | `no-elif-return` | Unnecessary elif after return | | `no-else-return` | Unnecessary else after return |

Class member order (class-definitions-order)

gdlint expects this top-to-bottom order: 1. `@tool` 2. `class_name` 3. `extends` 4. Docstring 5. Signals 6. Enums 7. Constants 8. Static variables 9. `@export` variables 10. Public variables 11. Private variables (`_prefixed`) 12. `@onready` public variables 13. `@onready` private variables 14. Remaining declarations

Configuration

gdlintrc

Create `.gdlintrc` (or `gdlintrc`) in the project root. YAML format. gdlint searches upward from CWD, uses the first file found.

Generate defaults: `gdlint -d > .gdlintrc`

Example with customizations:

# Relax line length to match gdf
Read more
Ships withgodotmaker

Autonomous text-to-game pipeline for Godot, powered by Claude Code,Codex,Opencode

Get the whole plugin