Playtest loop
Play the game, inject input, read live state, capture frames, and poll runtime errors.
The runtime and input groups reach the running game, a separate process from the editor. The editor brokers that hop over file IPC, so you can drive and inspect a live playtest.
Play, drive, inspect, stop
swallowtail scene play --mode mainswallowtail runtime treeswallowtail input action --action ui_accept --pressed trueswallowtail runtime get --node-path Player --properties '["position", "velocity"]'swallowtail runtime screenshot --save-path user://shot.pngswallowtail scene stopruntime.screenshot works even under a headless editor, because the game is a separate windowed process.
Run a scenario
test run-scenario accepts input, wait, assert, and screenshot steps. For an
already-playing scene with a Score label:
swallowtail test run-scenario --steps '[{"type":"wait","node_path":"Score","timeout":5},{"type":"assert","node_path":"Score","property":"text","expected":"0"}]'Use --scene-path res://levels/arena.tscn to start a saved scene first. The whole
plan is checked before playback or input begins. An unknown field, missing
required value, wrong type, unsupported operator, or invalid numeric bound returns
-32602 with the zero-based step index. For example, partail in a text assertion
is rejected even if earlier steps are valid.
test run-scenario --help describes the fields. engine commands --group test
returns the seven step alternatives as nested JSON Schema, also exposed through
both MCP tool lists. Input steps choose either action or keycode; an action
press auto-releases unless auto_release is false. A hold needs a later release.
Inspect all_passed, assertions_failed, and errors in the result. A failed
assertion is a test result inside a successful transport response. Stdio clients
can request progress or cancellation.
Wait for a signal
runtime.await_signal blocks until a signal fires on a node in the running game and returns its serialized arguments:
swallowtail runtime await-signal --node-path Player --signal died --timeout 10A timeout returns fired: false as a success payload, so an agent can branch on it rather than treating it as an error.
Poll runtime errors
runtime.errors returns structured errors and warnings the running game captured through an OS.add_logger hook:
swallowtail runtime errors --clearEach entry is { kind, message, code, backtrace[] } with the real game-script frame in backtrace[0]. It is pull-based: the agent polls on demand, and runtime errors are unambiguously real.
Debug the running game
The debug group turns a playtest into a debugging session. Breakpoints are armed through the editor’s own script gutter, so they show in the gutter and the Breakpoints list, persist for later runs, and hit a game that is already running, with no restart:
swallowtail debug set-breakpoint --path res://player.gd --line 42swallowtail debug state # paused? reason, stack, variablesswallowtail debug frame --index 1 # another stack frame's variablesswallowtail debug step --mode over # also: into, outswallowtail debug resumeswallowtail debug pause # break into a game that is runningswallowtail debug clear-breakpointsThe guardrails do the thinking with you: a line that can never be hit (a blank, a comment, a declaration) is refused with the first executable line suggested instead, and arming a per-frame callback like _process comes with a warning, because every resume would re-break immediately.
Edited a script while the game is paused on a bug? Push the fix into the live process:
swallowtail debug resumeswallowtail debug reload-scripts # every .gd changed since the run startedEvery live instance starts running the new code and keeps the state it had. Any run started by scene play accepts reloads (it launches with the editor’s script-sync options armed); a run launched by hand needs both Synchronize options ticked in the editor’s Debug menu.
Direct-to-player channel
Everything above brokers through the open editor. You can also drive a standalone running game with no editor at all, which suits QA rigs and packaged dev builds. Enable Project → Project Settings → Swallowtail → Runtime → Direct Server, run a debug build of the game, then add the --game flag:
swallowtail --game runtime treeswallowtail --game runtime eval --code "emit(1 + 1)"swallowtail --game input action --action ui_accept --pressed trueThe game hosts its own 127.0.0.1-only WebSocket server (ports 9200-9215, SWALLOWTAIL_GAME_PORT pins one) and writes a discovery file in its user:// dir, so --game finds it automatically from inside the project. The runtime.* and input.* commands behave identically to the editor-brokered path.