Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    Randroids-Dojo

    godot

    Randroids-Dojo/godot
    Coding
    7
    4 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Develop, test, build, and deploy Godot 4.x games. Includes GdUnit4 for GDScript unit tests and PlayGodot for game automation and E2E testing...

    SKILL.md

    Godot Skill

    Develop, test, build, and deploy Godot 4.x games.

    Quick Reference

    # GdUnit4 - Unit testing framework (GDScript, runs inside Godot)
    godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd --run-tests
    
    # PlayGodot - Game automation framework (Python, like Playwright for games)
    export GODOT_PATH=/path/to/godot-automation-fork
    pytest tests/ -v
    
    # Export web build
    godot --headless --export-release "Web" ./build/index.html
    
    # Deploy to Vercel
    vercel deploy ./build --prod
    

    Testing Overview

    GdUnit4 PlayGodot
    Type Unit testing Game automation
    Language GDScript Python
    Runs Inside Godot External (like Playwright)
    Requires Addon Custom Godot fork
    Best for Unit/component tests E2E/integration tests

    GdUnit4 (GDScript Tests)

    GdUnit4 runs tests written in GDScript directly inside Godot.

    Project Structure

    project/
    ├── addons/gdUnit4/          # GdUnit4 addon
    ├── test/                    # Test directory
    │   ├── game_test.gd
    │   └── player_test.gd
    └── scripts/
        └── game.gd
    

    Setup

    # Install GdUnit4
    git clone --depth 1 https://github.com/MikeSchulze/gdUnit4.git addons/gdUnit4
    
    # Enable plugin in Project Settings → Plugins
    

    Basic Unit Test

    # test/game_test.gd
    extends GdUnitTestSuite
    
    var game: Node
    
    func before_test() -> void:
        game = auto_free(load("res://scripts/game.gd").new())
    
    func test_initial_state() -> void:
        assert_that(game.is_game_active()).is_true()
        assert_that(game.get_current_player()).is_equal("X")
    
    func test_make_move() -> void:
        var success := game.make_move(4)
        assert_that(success).is_true()
        assert_that(game.get_board_state()[4]).is_equal("X")
    

    Scene Test with Input Simulation

    # test/game_scene_test.gd
    extends GdUnitTestSuite
    
    var runner: GdUnitSceneRunner
    
    func before_test() -> void:
        runner = scene_runner("res://scenes/main.tscn")
    
    func after_test() -> void:
        runner.free()
    
    func test_click_cell() -> void:
        await runner.await_idle_frame()
    
        var cell = runner.find_child("Cell4")
        runner.set_mouse_position(cell.global_position + cell.size / 2)
        runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT)
        await runner.await_input_processed()
    
        var game = runner.scene()
        assert_that(game.get_board_state()[4]).is_equal("X")
    
    func test_keyboard_restart() -> void:
        runner.simulate_key_pressed(KEY_R)
        await runner.await_input_processed()
        assert_that(runner.scene().is_game_active()).is_true()
    

    Running GdUnit4 Tests

    # All tests
    godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd --run-tests
    
    # Specific test file
    godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
      --run-tests --add res://test/my_test.gd
    
    # Generate reports for CI
    godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
      --run-tests --report-directory ./reports
    

    GdUnit4 Assertions

    # Values
    assert_that(value).is_equal(expected)
    assert_that(value).is_not_null()
    assert_that(condition).is_true()
    
    # Numbers
    assert_that(number).is_greater(5)
    assert_that(number).is_between(1, 100)
    
    # Strings
    assert_that(text).contains("expected")
    assert_that(text).starts_with("prefix")
    
    # Arrays
    assert_that(array).contains(element)
    assert_that(array).has_size(5)
    
    # Signals
    await assert_signal(node).is_emitted("signal_name")
    

    Scene Runner Input API

    # Mouse
    runner.set_mouse_position(Vector2(100, 100))
    runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT)
    runner.simulate_mouse_button_released(MOUSE_BUTTON_LEFT)
    
    # Keyboard
    runner.simulate_key_pressed(KEY_SPACE)
    runner.simulate_key_pressed(KEY_S, false, true)  # Ctrl+S
    
    # Input actions
    runner.simulate_action_pressed("jump")
    runner.simulate_action_released("jump")
    
    # Waiting
    await runner.await_input_processed()
    await runner.await_idle_frame()
    await runner.await_signal("game_over", [], 5000)
    

    PlayGodot (Game Automation)

    PlayGodot is a game automation framework for Godot - like Playwright, but for games. It enables E2E testing, automated gameplay, and external control of Godot games via the native RemoteDebugger protocol.

    Requirements:

    • Custom Godot fork: Randroids-Dojo/godot (automation branch)
    • PlayGodot Python library

    Setup

    # Install PlayGodot
    python -m venv .venv
    source .venv/bin/activate  # Windows: .venv\Scripts\activate
    pip install playgodot
    
    # Build custom Godot fork
    git clone https://github.com/Randroids-Dojo/godot.git
    cd godot && git checkout automation
    scons platform=macos arch=arm64 target=editor -j8  # macOS Apple Silicon
    # scons platform=macos arch=x86_64 target=editor -j8  # macOS Intel
    # scons platform=linuxbsd target=editor -j8  # Linux
    # scons platform=windows target=editor -j8  # Windows
    

    Test Configuration (conftest.py)

    import os
    import pytest_asyncio
    from pathlib import Path
    from playgodot import Godot
    
    GODOT_PROJECT = Path(__file__).parent.parent
    GODOT_PATH = os.environ.get("GODOT_PATH", "/path/to/godot-fork")
    
    @pytest_asyncio.fixture
    async def game():
        async with Godot.launch(
            str(GODOT_PROJECT),
            headless=True,
            timeout=15.0,
            godot_path=GODOT_PATH,
        ) as g:
            await g.wait_for_node("/root/Game")
            yield g
    

    Writing PlayGodot Tests

    import pytest
    
    GAME = "/root/Game"
    
    @pytest.mark.asyncio
    async def test_game_starts_empty(game):
        board = await game.call(GAME, "get_board_state")
        assert board == ["", "", "", "", "", "", "", "", ""]
    
    @pytest.mark.asyncio
    async def test_clicking_cell(game):
        await game.click("/root/Game/VBoxContainer/GameBoard/GridContainer/Cell4")
        board = await game.call(GAME, "get_board_state")
        assert board[4] == "X"
    
    @pytest.mark.asyncio
    async def test_game_win(game):
        for pos in [0, 3, 1, 4, 2]:  # X wins top row
            await game.call(GAME, "make_move", [pos])
    
        is_active = await game.call(GAME, "is_game_active")
        assert is_active is False
    

    Running PlayGodot Tests

    export GODOT_PATH=/path/to/godot-automation-fork
    pytest tests/ -v
    pytest tests/test_game.py::test_clicking_cell -v
    

    PlayGodot API

    # Node interaction
    node = await game.get_node("/root/Game")
    await game.wait_for_node("/root/Game", timeout=10.0)
    exists = await game.node_exists("/root/Game")
    result = await game.call("/root/Node", "method", [arg1, arg2])
    value = await game.get_property("/root/Node", "property")
    await game.set_property("/root/Node", "property", value)
    
    # Node queries
    paths = await game.query_nodes("*Button*")
    count = await game.count_nodes("*Label*")
    
    # Mouse input
    await game.click("/root/Button")
    await game.click(300, 200)
    await game.double_click("/root/Button")
    await game.right_click(100, 100)
    await game.drag("/root/Item", "/root/Slot")
    
    # Keyboard input
    await game.press_key("space")
    await game.press_key("ctrl+s")
    await game.type_text("hello")
    
    # Input actions
    await game.press_action("jump")
    await game.hold_action("sprint", 2.0)
    
    # Touch input
    await game.tap(300, 200)
    await game.swipe(100, 100, 400, 100)
    await game.pinch((200, 200), 0.5)
    
    # Screenshots
    png_bytes = await game.screenshot()
    await game.screenshot("/tmp/screenshot.png")
    similarity = await game.compare_screenshot("expected.png")
    await game.assert_screenshot("reference.png", threshold=0.99)
    
    # Scene management
    scene = await game.get_current_scene()
    await game.change_scene("res://scenes/level2.tscn")
    await game.reload_scene()
    
    # Game state
    await game.pause()
    await game.unpause()
    is_paused = await game.is_paused()
    await game.set_time_scale(0.5)
    scale = await game.get_time_scale()
    
    # Waiting
    await game.wait_for_node("/root/Game/SpawnedEnemy", timeout=5.0)
    await game.wait_for_visible("/root/Game/UI/GameOverPanel", timeout=10.0)
    await game.wait_for_signal("game_over")
    await game.wait_for_signal("health_changed", source="/root/Game/Player")
    

    Building & Deployment

    Web Export

    # Requires export_presets.cfg with Web preset
    godot --headless --export-release "Web" ./build/index.html
    

    Export Preset (export_presets.cfg)

    [preset.0]
    name="Web"
    platform="Web"
    runnable=true
    export_path="build/index.html"
    

    Deploy to Vercel

    npm i -g vercel
    vercel deploy ./build --prod
    

    CI/CD

    GitHub Actions Example

    - name: Setup Godot
      uses: chickensoft-games/setup-godot@v2
      with:
        version: 4.3.0
        include-templates: true
    
    - name: Run GdUnit4 Tests
      run: |
        godot --headless --path . \
          -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
          --run-tests --report-directory ./reports
    
    - name: Upload Results
      uses: actions/upload-artifact@v4
      if: always()
      with:
        name: test-results
        path: reports/
    

    References

    • references/gdunit4-quickstart.md - GdUnit4 setup
    • references/scene-runner.md - Input simulation API
    • references/assertions.md - Assertion methods
    • references/playgodot.md - PlayGodot guide
    • references/deployment.md - Deployment guide
    • references/ci-integration.md - CI/CD setup
    Repository
    randroids-dojo/godot-claude-skills
    Files