# Contributing to Godot AI AI assistants working in this repository should read the shared guide in [AGENTS.md](../AGENTS.md). Client-specific files should point there instead of duplicating general repo guidance. ## Development Setup **macOS / Linux:** ```bash git clone https://github.com/hi-godot/godot-ai.git cd godot-ai script/setup-dev # creates .venv, installs deps, builds plugin symlink, installs git hooks source .venv/bin/activate ``` **Windows (PowerShell):** ```powershell git clone https://github.com/hi-godot/godot-ai.git cd godot-ai .\script\setup-dev.ps1 # creates .venv, installs deps, builds plugin junction, installs git hooks .venv\Scripts\Activate.ps1 ``` > **Plugin link is built locally, not tracked in git.** `test_project/addons/godot_ai` > is a symlink (Unix) or directory junction (Windows) into `plugin/addons/godot_ai`, > created fresh by `setup-dev`. A clone without running `setup-dev` has no link and > Godot won't find the plugin. The Windows flavor uses `mklink /J`, which works > without admin rights and without Windows Developer Mode. > **One-time per clone:** `setup-dev` installs a `post-checkout` git hook > (from `script/githooks/`) into `.git/hooks/`. The hook auto-builds the plugin > link on every `git worktree add` and `git checkout `, so every > future worktree of this clone gets a working link automatically. You only > need to run `setup-dev` once per clone. ## Testing ### Python tests ```bash pytest -v # unit + integration tests ruff check src/ tests/ # lint ruff format src/ tests/ # format ``` ### Godot-side tests GDScript test suites run inside the connected editor via MCP: ``` test_run # run all suites test_run suite=scene # run one suite test_manage op=results_get # review last results ``` See [testing.md](testing.md) for how to write suites and the full `McpTestSuite` API reference. ### CI regression range helper When CI starts failing, identify the regression window (last green → first red): ```bash script/ci-find-regression-range hi-godot/godot-ai ci.yml main ``` If your local clone has a valid `origin` GitHub remote, you can omit `owner/repo`: ```bash script/ci-find-regression-range ``` ### Local self-update smoke For changes that touch self-update, plugin reload handoff, or install/extract logic, run the interactive local harness: ```bash script/local-self-update-smoke ``` It creates a disposable project with a physical `addons/godot_ai/` copy, stages a synthetic v(N+1) plugin ZIP, launches Godot, and prints the single manual action: click Update in the Godot AI dock. After you close Godot normally, the script verifies the fixture version advanced, the update temp dir was consumed, and no new macOS `Godot*.ips` crash report appeared. ### Self-update compatibility rules Self-update safety depends on the installed runner. Releases that include the fixed runner write one complete v(N+1) snapshot before Godot scans, so future upgrades from that release avoid mixed old/new script parsing. Users on older releases still take their next update through the old two-phase runner, so release shape still matters during that transition. - Do not delete a `class_name` declaration that has shipped in any release. If a published class needs to move or retire, leave the original file path and `class_name` in place as a compatibility shim. - Before cutting a release that may be installed by an old two-phase runner, avoid adding new files that reference constants, methods, or static/non-static shape changes added to existing load-surface scripts in the same release. This applies to `class_name` scripts and preload-only scripts. - Keep historical old-runner upgrade tests manual or explicitly marked. Default CI should gate the forward fixed-runner path, not permanently fail on old shipped runner behavior. ## Dev Server with Auto-Reload For Python-side changes without restarting Godot: ```bash python -m godot_ai --transport streamable-http --port 8000 --reload ``` The Godot AI dock also has a **Start/Stop Dev Server** button when running from a dev checkout. ## PR Workflow 1. Branch off `main` 2. Keep tests and lint clean 3. Add tests for new behavior — both Python and Godot-side when crossing the plugin boundary ```bash git checkout -b feature/my-feature pytest -v && ruff check src/ tests/ git push -u origin feature/my-feature gh pr create ```