Skip to content

Installation ​

This guide covers everything you need to install Theatre and connect it to your Godot project.

Prerequisites ​

Rust toolchain ​

Theatre is built in Rust. You need a recent stable toolchain (1.94 or later).

bash
# Install rustup if you don't have it
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Verify
rustc --version   # should print 1.94.0 or later
cargo --version

Godot 4.7 or later ​

Theatre supports Godot 4.7 or later. Stage uses godot-rust 0.5.5 with api-4-7, experimental-godot-api, and compatibility_minimum = "4.7". Director also uses native editor APIs from this engine floor. The gdext dependency requires Rust 1.94 or later; current local engine verification used Rust 1.96.1.

Make sure the Godot binary is on your PATH, or pass it to initialization with --godot-bin, if you want Theatre to run the initial import and headless verification commands:

bash
godot --version   # e.g. 4.7.1.stable.official

An MCP-capable AI agent ​

Theatre exposes tools via Model Context Protocol. Supported agents include:

  • Claude Code (recommended) — built-in MCP support
  • Cursor — MCP support in recent versions
  • Windsurf — MCP support via settings
  • Any agent that supports stdio MCP servers

The fastest way to install Theatre — downloads a pre-built release for your platform:

bash
curl -LsSf https://github.com/nklisch/theatre/releases/latest/download/install.sh | sh

This detects your OS and architecture, downloads the correct release, verifies the SHA256 checksum, and installs to:

  • ~/.local/bin/ — theatre, stage, director binaries
  • ~/.local/share/theatre/ — addon templates, shared support payload, GDExtension binary, and optional client packages

Override install locations with --bin-dir and --share-dir flags. Use --no-modify-path to skip adding ~/.local/bin to your shell profile.

Supported platforms: Linux x86_64, macOS arm64, macOS x86_64 (Rosetta), Windows x86_64 (MINGW/MSYS).

Install a specific version ​

bash
curl -LsSf https://github.com/nklisch/theatre/releases/latest/download/install.sh | sh -s -- --version 0.6.2

Install from source ​

If you prefer to build from source, the theatre CLI handles the entire process:

bash
git clone https://github.com/nklisch/theatre
cd theatre
cargo run -p theatre-cli -- install

This builds all crates in release mode and installs to the same locations as the one-liner above.

If the configured binary directory is not in your PATH, the installer prints the appropriate command: PowerShell user-environment guidance on Windows or an export PATH=... command on Unix.

Platform notes ​

On Linux, the build works out of the box. On macOS, you may need the Xcode command-line tools (xcode-select --install). On Windows, use the MSVC toolchain (rustup default stable-x86_64-pc-windows-msvc).

The source install writes stage.exe, director.exe, and theatre.exe on Windows. Unix executable names remain extensionless.

Set up a Godot project ​

After installing, use theatre init to set up a Godot project interactively:

bash
theatre init ~/path/to/your-godot-project

PowerShell:

powershell
theatre init .\path\to\your-godot-project

This walks you through:

  1. Addon selection — choose Stage, Director, or both
  2. MCP configuration — generates portable .mcp.json commands resolved through PATH
  3. Plugin enabling — updates project.godot to enable plugins and autoloads
  4. Agent rules — optionally generates a rules file to guide native authoring of .tscn/.tres files

Ask the user before installing or enabling Theatre in a project. Machine installation, project wiring and per-run activation are separate decisions. After project-install approval, unattended setup requires both flags; existing addons and MCP config are preserved unless --overwrite-existing is also explicitly requested:

bash
theatre init path/to/your-godot-project --yes --accept-project-install

If Godot is not on PATH, provide it for the bounded initial import:

powershell
theatre init .\path\to\your-godot-project --yes --accept-project-install --godot-bin 'C:\path\to\Godot_console.exe'

This argument is used only for initialization. If Director also needs that location, set GODOT_BIN in the environment that launches your AI agent; do not add a machine-specific path to tracked .mcp.json.

What theatre init does ​

  • Copies selected addon files and addons/theatre_shared support into your project's addons/ directory
  • Copies the GDExtension binary (.so/.dylib/.dll) for Stage
  • Generates .mcp.json with the bare stage and director commands
  • Enables plugins in project.godot and adds the StageRuntime autoload
  • Optionally generates an agent rules file (.claude/rules/godot.md, CLAUDE.md, or AGENTS.md) to prevent hand-editing Godot files
  • Runs one bounded headless editor import when Godot can be resolved; otherwise prints the manual recovery command

Verify the deployment ​

Run Godot headless to confirm the extension loads without errors:

bash
godot --headless --quit --path ~/path/to/your-godot-project 2>&1

Expected output should not contain SCRIPT ERROR, [panic], or ERROR. You should see the Stage TCP server start and stop cleanly.

Rebuild and redeploy ​

After making code changes, use theatre deploy to rebuild and update projects:

bash
# Debug build → single project
theatre deploy ~/path/to/your-godot-project

# Release build → multiple projects
theatre deploy --release ~/godot/game1 ~/godot/game2

Deploy rebuilds the GDExtension and MCP servers, updates the share dir, and copies fresh files to all target projects.

Enable/disable plugins ​

Toggle plugins without recopying addon files:

bash
theatre enable ~/path/to/your-godot-project              # enable both
theatre enable ~/path/to/your-godot-project --stage   # stage only
theatre enable ~/path/to/your-godot-project --disable     # disable both

Regenerate MCP config ​

If you skipped .mcp.json generation during theatre init, or need to update it after changing the port or binary location, run:

bash
theatre mcp ~/path/to/your-godot-project

This generates (or overwrites) .mcp.json with the portable bare commands stage and director. It detects which addons are installed and includes only those in the config. The configured Theatre binary directory must be on the PATH inherited by the agent process.

Use --yes to skip prompts (accepts port 9077 and overwrites any existing file):

bash
theatre mcp ~/path/to/your-godot-project --yes

Use --port to specify a non-default port:

bash
theatre mcp ~/path/to/your-godot-project --port 9078

After regenerating, restart your AI agent to pick up the updated server configuration.

Use a nested sandbox or switch projects ​

Run theatre init /absolute/path/to/project once for each Godot project that needs Theatre's addons. If you start the agent from a repository root whose MCP configuration already points at a nested sandbox, keep that root configuration; do not also load the nested generated .mcp.json or duplicate generated rules.

Stage uses THEATRE_PROJECT_DIR for its startup selection. In persistent MCP, call project_select with the absolute project_path to switch without restarting. An optional port overrides the new project's stage.toml port; otherwise Stage uses that TOML port or 9077. Each selection clears watches, snapshot/delta baselines, spatial indexes, session overrides and the cached clip location—even when selecting the same project again. Take a fresh snapshot and recreate watches after switching. A target that is not running stays selected and disconnected while Stage retries; it never silently returns to the old game. Check the returned identity and readiness.

The MCP startup env applies only to the Stage subprocess, and project_select does not change the optional client feedback hook's environment. To make that hook select a nested project from a repository-root session, launch the client with the absolute project environment too:

bash
THEATRE_PROJECT_DIR=/absolute/path/to/project claude --plugin-dir "$HOME/.local/share/theatre/client-plugins/claude"
THEATRE_PROJECT_DIR=/absolute/path/to/project codex

An explicit hook selection is authoritative; if it is wrong, the hook stays quiet rather than surfacing an ancestor project's queue. When it is unset, the hook keeps the existing nearest-ancestor project lookup. For a one-off Stage CLI call, override selection directly:

bash
THEATRE_PROJECT_DIR=/absolute/path/to/project stage runtime_status '{}'

Director selects independently: pass the absolute Godot project directory as project_path on every call. Consecutive Director calls can target different projects without restarting the server.

The default Stage and Director ports are shared local resources. Stop the old running game before starting another project on the same ports, then verify Stage's reported project, scene, and run with runtime_status. Follow the target repository's ownership rules when setup files are generated; update the owning generator rather than making a durable direct edit to its output.

Manual setup (alternative) ​

If you prefer not to use the CLI, you can set things up manually.

Build from source ​

bash
git clone https://github.com/nklisch/theatre
cd theatre
cargo build --workspace --release

Build output:

  • target/release/stage — Stage MCP server + CLI binary
  • target/release/director — Director MCP server binary
  • target/release/libstage_godot.so — Stage GDExtension (Linux)
  • target/release/libstage_godot.dylib — Stage GDExtension (macOS)
  • target/release/stage_godot.dll — Stage GDExtension (Windows)

Copy addons ​

bash
cp -r addons/stage ~/path/to/your-godot-project/addons/
cp -r addons/director ~/path/to/your-godot-project/addons/
cp -r addons/theatre_shared ~/path/to/your-godot-project/addons/

Copy the GDExtension binary to the correct platform subdirectory:

bash
mkdir -p ~/path/to/your-godot-project/addons/stage/bin/linux/
cp target/release/libstage_godot.so ~/path/to/your-godot-project/addons/stage/bin/linux/

Then in Godot: Project → Project Settings → Plugins → enable Stage and Director.

Configure MCP ​

Create .mcp.json in your project root:

json
{
  "mcpServers": {
    "stage": {
      "type": "stdio",
      "command": "stage",
      "args": ["serve"]
    },
    "director": {
      "type": "stdio",
      "command": "director",
      "args": ["serve"]
    }
  }
}

Use the bare commands shown above so checked-in configuration works across machines and operating systems. Ensure the binary directory is on the agent process's PATH. Both binaries require the serve subcommand for MCP mode (without it, they run in CLI mode).

Use THEATRE_PORT=9078 in an env block if you need a non-default port.

Install client plugins and agent skills (optional) ​

The Theatre distribution includes self-contained Claude and Codex plugin roots under ~/.local/share/theatre/client-plugins/. Both retain the plugin ID theatre-feedback, bundle the theatre-stage and theatre-director operating skills, and provide the optional pending-feedback hook. They do not register Stage or Director MCP servers; keep using the project's existing .mcp.json.

Claude Code can load the installed plugin root for a session without modifying a marketplace:

bash
claude --plugin-dir "$HOME/.local/share/theatre/client-plugins/claude"

For Codex, the containing directory is a local marketplace:

bash
codex plugin marketplace add "$HOME/.local/share/theatre/client-plugins"
codex plugin add theatre-feedback@theatre-local

Plugin installation and hook trust remain explicit client actions. Restart or reload the client when it requires that to discover newly installed skills. The plugins add operating guidance and a feedback notice only; they do not replace theatre init, change the active Godot project, or deliver feedback images.

If a client does not load native plugins, install the same operating skills in the project instead. Project skills are also useful when guidance should travel with a repository:

bash
# From within the Theatre source checkout
cp -r .agents/skills/theatre-stage <your-project>/.agents/skills/
cp -r .agents/skills/theatre-director <your-project>/.agents/skills/

A client may discover both plugin and project copies. They describe the same Theatre tools; do not duplicate MCP registration or agent rules because both are present. The canonical source is .agents/skills/ in the Theatre repository, and distributed plugin copies are synchronized from it.

For broader Godot coding guidance, godot-gdscript-patterns remains available through the Theatre skilltap collection:

bash
skilltap install nklisch/theatre

Read and diff Godot files freely. Prefer Director for structural scene and resource edits so Godot validates types, references, ownership, and serialization. Theatre can generate this guidance for your agent.

Via the CLI ​

theatre init prompts for this automatically. To add rules to an existing project:

bash
theatre rules ~/path/to/your-godot-project

This gives you three options:

  • .claude/rules/godot.md — Claude Code auto-loads this (recommended for Claude Code users)
  • CLAUDE.md — appends rules to your project's CLAUDE.md
  • AGENTS.md — appends rules for non-Claude agents

Use --yes to skip prompts and generate .claude/rules/godot.md:

bash
theatre rules ~/path/to/your-godot-project --yes

Manual snippet ​

If you prefer to add the rules yourself, paste this into your project's CLAUDE.md, AGENTS.md, or .claude/rules/godot.md:

md
# Godot Project File Guidance

## Installation and launch intent

Machine installation, project wiring, and per-run observation/capture are separate
decisions. If Theatre is missing and would help, explain the needed scope and ask
the user before installing or enabling it in this project. Do not treat a failed
connection or `--yes` as installation consent. Once approved, noninteractive
project setup uses `theatre init . --yes --accept-project-install`; existing addons
and MCP configuration are preserved unless replacement is explicitly authorized.

Ordinary launches need neither Stage observation nor recording. Enable only the
evidence needed for an autonomous task, expressly requested by the user, or needed
for a specific human capture request. Do not change persistent preferences to
satisfy one run. Respect explicit local preferences and explicit per-run off.

On Windows, choose launch presentation explicitly for agent-initiated work:

- Agent visual review: use `presentation=automated`.
- Background testing: use headless execution when it preserves the required
  evidence; otherwise use `presentation=automated`.
- Prepare human testing: use `presentation=deferred`. After confirming the
  project's real readiness condition, tell the user in the normal agent response
  that the scene is ready and name any checks they should perform. The user focuses
  the ordinary Godot window; Theatre has no separate handoff action.
- Human-visible review expressly requested by the user: use
  `presentation=interactive`.

Omitting presentation preserves legacy behavior; it is not an automation safety
default. If automated or deferred launch reports degraded protection, inspect its
`launch_requested` and `game_running` facts, stop the run before any fallback, and
do not announce a degraded deferred run as ready without explaining the limitation
and obtaining a new user decision. Capture operator, presets, readiness, viewport,
recording, and Stage controls do not grant focus or physical-input permission.
These presentation modes are Windows-only; on Linux and macOS, keep the project's
established headless, graphical, and wrapper-based workflows, using omission or
explicit interactive presentation for ordinary editor launches.

This generated guidance intentionally does not invent the project's launch target,
successful readiness transition, Quick Sandbox or equivalent review target, or
local background-test command. Record those facts in the consuming project's own
instructions beneath this policy when they are known.

Use Director `editor_run.launch` or `theatre run` to select observation independently
from startup/play capture. Human review normally uses `operator=human` and
`play_start=manual`: startup can finish and save, but play does not collect hours
of idle data while the person is away. This does not pause the game's simulation.
Minimal captures explicit metrics only; Light adds scoped spatial samples;
Standard adds images; Heavy allows whole-scene, higher-frequency capture.
Light and Standard require scene-relative node paths or explicit `group:name`
selectors. Images, sampling intervals, bounds, retention, and saving are separate
options, not hidden side effects of operator choice.

For asynchronous loading, locate the project's actual readiness transition and
explicitly add the following call there, only after all prerequisites succeed:

```gdscript
var stage := get_node_or_null("/root/StageRuntime")
if stage != null:
    stage.notify_ready()
```

Use `readiness=project` (the default). Do not use a scene's `_ready()` callback,
frame rate, or a quiet timeout as a substitute for application readiness. Do not
notify after canceled/failed loading. Duplicate notifications are safe. Only
simple synchronous scenes should explicitly select `readiness=scene`, whose
weaker boundary is scene initialization, not completion of background work.
Missing readiness stops startup at its capture bound and never starts play.

Human controls and `clips` support Start new, Continue, Stop, Keep, and Discard.
Continue starts a separate immutable segment with the same recording identity;
it never fills the uncaptured gap or retroactively increases evidence detail.
Unkept play drafts live in memory and are lost on exit. Keep before closing.
Metrics, saved clips, and their markers can be inspected after the game stops.

Shared defaults belong in `[launch]` in `stage.toml`. Private preferences can use
the OS application-config directory's `theatre/settings.toml`, or per-project
`stage.local.toml`. Before creating that local project file, request approval for
the narrow `stage.local.toml` ignore entry and verify the project ignores it.
Never commit private configuration or machine paths. Keep repository-owned paths
relative and use installed executable names through PATH. On Windows these names
resolve to `theatre.exe`, `director.exe`, and `stage.exe`; do not replace Unix
instructions with Windows-only paths or suffixes.

## Inspect project files freely

Read Godot project files and inspect their diffs whenever that helps you understand the
project or review a change. This includes text-serialized scenes and resources such as
`.tscn` and `.tres`, project settings such as `project.godot`, and related Godot files.
Use Director's `scene_read`, `resource_read`, and `scene_diff` when structured output is
more useful than raw text.

## Choose the edit path that matches the file

Edit GDScript (`.gd`) and shader source (`.gdshader`) with normal code-editing tools.
After source changes, use Director's `project_reload` when Godot-backed validation is
useful.

For structural scene, resource, and project-setting changes, prefer **Director** MCP
tools (or CLI) or the Godot editor. These paths use Godot's APIs and serialization for
engine types, resource references, UIDs, scene ownership, and signals:

- `scene_create`, `node_add`, `node_remove`, `node_set_properties`, `node_reparent`
- `material_create`, `shape_create`, `resource_duplicate`
- `tilemap_set_cells`, `gridmap_set_cells`
- `animation_create`, `animation_add_track`
- `signal_connect`, `signal_disconnect`
- `physics_set_layers`, `project_settings_set`, `autoload_add`, `autoload_remove`
- `batch` for sequential operations in one Godot invocation

Do not automatically fall back to arbitrary text mutations when a structural operation
is unavailable. Inspect the file, choose an appropriate Godot-backed workflow, or explain
the missing operation instead.

Director changes any open target scene through its live root and native undo history.
Individual and batch changes remain unsaved until `scene_save`. That operation serializes
only the selected scene, retains undo, and does not save unrelated external resources. The
editor's native dirty marker may remain. Read each operation's persistence data and verify
saved content after partial failures. Detached headless scene and resource operations persist
their target files.

Use `engine_api` for focused ClassDB discovery when a property, type, signal, method, enum,
or default is uncertain. Use ordinary project-owned GDScript for unusual procedural
authoring that typed operations express poorly. Theatre does not provide a general
arbitrary-code execution operation.

Use **Director** `editor_run` with a verified open editor to start, stop, or restart a
selected saved scene. Live Stage tools require explicit `launch.observe=true`.
A launch request does not establish Stage readiness. Check
`runtime_status` for the actual project, run, current scene, and readiness.

Use **Stage** MCP tools to observe and interact with the running game:

- `runtime_status`, `runtime_diagnostics`, `viewport` — identify the run, inspect bounded
  process diagnostics, and capture the latest completed render on demand
- `spatial_snapshot`, `spatial_delta`, `spatial_query` — inspect the game world
- `spatial_inspect` — examine one node in depth
- `spatial_action` — teleport, pause, set properties, call methods, or run a bounded paused
  interaction sequence
- `scene_tree` — navigate the node hierarchy

A viewport read is independent of recording and is not atomic with spatial state. Runtime
actions are temporary. Interaction sequences release their held named actions during
supported cleanup, but they do not make gameplay deterministic.

If a tool result reports pending human feedback, use `feedback` status and retrieve the
matching item. Retrieval does not handle or delete evidence. Handle it explicitly after
addressing it; delete it only through a separate deliberate operation.

Using the CLI (alternative to MCP) ​

Both Stage and Director support standalone CLI calls. Stage CLI calls are one-shot: they do not share session state. Use persistent MCP for deltas, watches, session configuration updates, and actions with return_delta. The CLI rejects these requests before connection or mutation with persistent_session_required and exit code 2. Empty configuration reads, ordinary observations/actions, and clip operations remain available.

bash
# Stage — observe a running game
stage spatial_snapshot '{"detail": "summary"}'
stage spatial_inspect '{"node": "player"}'
stage scene_tree '{"action": "roots"}'

# Director — modify project files
director scene_create '{"project_path": "/home/user/game", "scene_path": "res://level.tscn", "root_type": "Node3D"}'
director scene_read '{"project_path": "/home/user/game", "scene_path": "res://level.tscn"}'

# Stdin piping works too
echo '{"detail": "summary"}' | stage spatial_snapshot

# Help and version
stage --help
director --help
stage --version   # {"version": "0.6.2"}

CLI output is JSON to stdout. Exit codes 1 and 2 report runtime and usage failures. Director can also return a structured operation result with "success": false at exit code 0, so inspect success, error, context, and persistence — including ordered per-entry batch results — before deciding what succeeded or should be retried.

Verify the full setup ​

  1. Open your Godot project in the editor
  2. Run the game (F5 or the play button)
  3. In your AI agent, ask: "Take a spatial snapshot"

The agent should call spatial_snapshot and return a JSON summary of your scene. If it times out or returns a connection error, check:

  • The Stage addon is enabled and the extension loaded (check the editor dock)
  • The game is actually running (not just the editor)
  • Port 9077 is not blocked by a firewall

Troubleshooting ​

"Extension not found" in the dock ​

The GDExtension binary wasn't found or is for the wrong platform. Re-run theatre deploy and check the addons/stage/bin/ directory contains the .so/.dylib/.dll.

Connection refused / timeout ​

Stage only accepts connections while the game is running. Make sure you press F5 (Run project) before asking the agent for a snapshot.

"SCRIPT ERROR: Parse error" in Godot ​

The GDScript addon has a syntax error, or it is referencing a GDExtension class that didn't load. Check the Godot output panel for the specific error. The addon is designed to gracefully degrade when the extension is missing — if you see a parse error, it is likely a version mismatch.

Build fails: "linker not found" ​

On Linux, install gcc or clang: sudo apt install build-essential (Ubuntu) or sudo dnf install gcc (Fedora).

Build fails on macOS: "xcrun: error" ​

Run xcode-select --install to install the command-line developer tools.

Runtime activation and readiness ​

Installed does not mean active: ordinary launches create no Stage listener, logger, sampling or capture controls. Use explicit launch options only when the user or investigation needs evidence. See Getting Started for observation and the required asynchronous-ready integration checklist, then Recording for presets and private preferences. Before creating stage.local.toml, obtain approval for its narrow project ignore rule and ensure that rule is present. Do not silently infer always-on consent from legacy settings.