AGENTS.md
Operating guide for human and AI contributors working in this repository.
1) Purpose and Current Product Stage
XRENGINE is a Windows-first C# XR engine + editor and is not yet shipped.
Implications:
- No backward-compatibility obligation exists until v1 ships. Breaking API changes, renames, and layout restructures are acceptable when they produce a cleaner v1.
- The goal is to ship the best possible default codebase as version 1. Prefer getting it right now over preserving legacy patterns.
- Favor clear, maintainable, high-performance architecture over quick hacks.
2) Default Working Agreement (Owner Preferences)
These are repository-default expectations unless a task explicitly says otherwise:
- Change style: Prefer clean architecture improvements, not only micro-patches.
- Scope: Allow broader subsystem sweeps when they materially improve correctness/maintainability.
- Testing bar: Run targeted tests closest to your changes.
- Risk posture: Balanced risk controls.
- Risky operations: Propose first and wait for approval before submodule bumps, dependency upgrades, schema/data migrations, or other high-blast-radius changes.
- Docs policy: Always update docs when user-facing behavior, launch flags, environment variables, tasks, or workflows change.
- Unrelated issues during validation: Opportunistically fix easy ones; report anything larger.
- Commit style (when committing is requested): simple imperative commit messages.
3) Environment and Platform Constraints
- Primary platform: Windows 10/11.
- Runtime/tooling: .NET 10 SDK.
- Rendering baseline: OpenGL 4.6 path is primary; Vulkan/DX12 remain WIP.
- XR paths exist for OpenXR and SteamVR/OpenVR; OpenVR is currently tested path.
- Repo uses git submodules under
Build/Submodules.
4) Repository Map (High Value Areas)
XREngine/- core runtime, scene graph, rendering, XR systems.XREngine.Editor/- desktop editor and unit-testing world bootstrap.XREngine.Server/- dedicated server executable.XREngine.VRClient/- standalone VR client executable.XREngine.UnitTests/- test project for engine/editor subsystems.Assets/UnitTestingWorldSettings.jsonc- generated local startup world toggles file used by unit-testing world flows.Build/Logs/- per-run log root when file logging is enabled; each session gets its own subdirectory..vscode/tasks.jsonand.vscode/launch.json- source of truth for local run/debug task orchestration.ExecTool.bat- interactive launcher for allTools/scripts (see §6).docs/- architecture, API guides, rendering notes, backlog/design docs.docs/architecture/rendering/default-render-pipeline-notes.md- known issues and invariants for DefaultRenderPipeline (texture storage, FBO lifecycle, bloom, auto-exposure, MSAA, etc.).docs/features/mcp-server.md- full MCP server documentation (see §15).
Editor UI Paths
The editor ships with two UI pipelines:
- ImGui editor — The current day-to-day interface. Fast to iterate on, fully functional, and the recommended path for development and testing right now.
- Native UI editor — The intended production-quality editor UI, built on the native scene-node pipeline with multithreaded layouting. It is under rigorous active development and not yet dependable for regular use. Expect missing features, layout instability, and breaking changes.
When working on editor tooling or features, default to the ImGui path unless the task explicitly targets the native UI pipeline.
5) First 10 Minutes in a Task
- Read the user request fully.
- Identify target subsystem(s) and nearest tests.
- Check existing docs and task/launch configs before changing workflows.
- Decide whether the request permits a subsystem sweep.
- If risky operation is involved, stop and request approval with a concrete plan.
6) Build, Run, and Debug Workflows
Build
- Full solution:
dotnet restoredotnet build XRENGINE.slnx
- Editor only:
dotnet build .\XREngine.Editor\XREngine.Editor.csproj
Primary run modes
- Editor CLI:
dotnet run --project .\XREngine.Editor\XREngine.Editor.csproj- add
--unit-testingorXRE_WORLD_MODE=UnitTestingto boot the Unit Testing World instead of the default world
- Common VS Code tasks (preferred for local orchestration):
Build-Editor,Build-Server,Build-VRClientStart-Editor-NoDebug,Start-Server-NoDebugStart-Client-NoDebug,Start-Client2-NoDebug,Start-2Clients-NoDebugStart-DedicatedServer-NoDebug- Pose sync tasks:
Start-PoseServer-NoDebugStart-PoseSourceClient-NoDebugStart-PoseReceiverClient-NoDebugStart-LocalPoseSync-NoDebug
Generate-UnitTestingWorldSettingsregenerates the JSONC settings files and schema fromUnitTestingWorld.Toggles
Logs and Diagnostics
- When file logging is enabled, per-run engine logs are written under
Build/Logs/<configuration>_<tfm>/<platform>/<session>/. - Profiler traces in that same run directory include
profiler-main-thread-invokes.log,profiler-fps-drops.log, andprofiler-render-stalls.log. - Math Intersections benchmark runs also write
math-intersections-benchmarks.loginto the same session directory.
ExecTool (interactive script launcher)
The repository root contains ExecTool.bat, which provides an interactive numbered menu for every script under Tools/.
ExecTool # interactive menu
ExecTool 16 # run tool #16 directly (Find-BuildWarnings)
ExecTool --bootstrap # full project setup (submodules, deps, generated settings, build, launch)
ExecTool --list # print all tools and exit
ExecTool --help # show usage
Tools are grouped into categories: Setup, Build, Editor, Repo, Docs, Reports, and Deps (dependency installers). Each entry shows a one-line description and the script path.
The Setup category contains a Bootstrap entry (also available as ExecTool --bootstrap) that performs full first-time project setup: initializes all git submodules, downloads every dependency, builds submodules, generates the Unit Testing World settings, builds the DocFX site, then launches the DocFX server and editor in separate windows.
Each category that supports it (Repo, Docs, Reports, Deps) also has an Execute ALL entry that runs every tool in that category sequentially.
Debug profiles
Use .vscode/launch.json profiles as canonical local debug setup, including:
Editor (Default World)Editor (Unit Testing World)Debug Client (Server & other client run separately)Debug Server (Clients runs separately)/Debug Server (Server only)Debug VRClient (Editor runs separately)- Profiler configurations
Unit Testing World Settings
- The canonical settings file is the generated local
Assets/UnitTestingWorldSettings.jsonc; the server mirror lives atXREngine.Server/Assets/UnitTestingWorldSettings.jsonc. - The file is loaded relative to the process working directory, so the VS Code launch configs intentionally set
cwdto the workspace root for the editor flows. - The JSONC files are mapped to
.vscode/schemas/unit-testing-world-settings.schema.json, so editors get hover docs, enum completion, and import-flag snippets while editing. - The root JSONC is ignored by Git for per-workstation tuning.
ExecTool --bootstrapcreates it on first setup. - Edit the JSONC directly for day-to-day tuning. If the settings type changes, regenerate the schema and both JSONC outputs with
Tools/Generate-UnitTestingWorldSettings.ps1or theGenerate-UnitTestingWorldSettingstask. Editor (Unit Testing World)and theStart-Pose*tasks are the normal entry points for unit-test-world validation.- The pose/networking test world is driven by
XRE_UNIT_TEST_WORLD_KIND=NetworkingPoseplus the role env vars used by the pose tasks (server,sender,receiver). Assets/UnitTestingWorldSettings.jsonccontrols the selected unit-test world and its toggles, including render API, import lists, physics, lighting, and related startup behavior.
7) Testing and Validation Policy
Default validation sequence:
- Run the most targeted tests for changed subsystem.
- If no tests exist, perform narrow build + run-path validation that exercises the changed flow.
- If unrelated failures appear:
- Fix easy nearby issues opportunistically.
- Report larger unrelated failures without blocking handoff.
Useful predefined tasks include:
Test-SurfelGiTest-VulkanPhase3-Regression
When adding new tests:
- Place tests in
XREngine.UnitTests/using nearby naming patterns. - Keep tests deterministic and focused on behavior, not implementation details.
8) Architecture and Refactor Guidance
Because this product is pre-ship and no backward compatibility is owed, architecture can and should improve as we touch code.
Preferred approach:
- Solve root causes, not only symptoms.
- Permit broader subsystem cleanup when directly related to the task's correctness or maintainability.
- Breaking changes to internal/public APIs are fine if they produce a cleaner v1.
- Actively reduce per-frame allocations when refactoring hot paths (see §11 Hot-Path Allocation Discipline).
- Avoid speculative rewrites with weak payoff.
Avoid:
- Unbounded cross-repo churn unrelated to task goals.
- New abstractions without immediate use.
- Silent behavior changes without docs updates.
9) Risk Management Rules
Must request approval first
- Upgrading or replacing major dependencies/submodules.
- Data format/storage migrations.
- Large changes to build/release/deployment scripts.
- Changes that could break existing editor/server/client launch flows.
License compliance (mandatory)
Every NuGet package or submodule pulled into the repository must have a license that permits both open-source and commercial use (e.g., MIT, Apache-2.0, BSD, Zlib, Unlicense). Copyleft licenses (GPL, AGPL) are acceptable only for the engine's own code or when the linking model keeps them isolated (e.g., LGPL via dynamic linking).
When any dependency is added, upgraded, or replaced:
- Run the dependency-inventory generator to refresh the license audit:
pwsh Tools/Generate-Dependencies.ps1 - Review the updated
docs/DEPENDENCIES.mdanddocs/licenses/output for any(unknown)or newly flagged license. - If a license is incompatible or unknown, do not merge — escalate for owner review.
- Include the refreshed
docs/DEPENDENCIES.mdand any newdocs/licenses/files in the same commit.
Can proceed without extra approval
- Localized code fixes/refactors in scoped subsystem.
- Targeted tests and small test additions.
- Docs updates that reflect behavior/task/flag changes.
10) Docs and Communication Requirements
Update docs in the same change when modifying user-visible behavior, including:
- CLI flags and env vars (e.g., networking/pose/test-world variables).
- Debug or task orchestration in
.vscode/tasks.jsonor.vscode/launch.json. - New prerequisites, native dependency handling, or setup steps.
Likely doc touchpoints:
README.mdfor top-level workflows.docs/README.mdindex links.- Relevant architecture/API/work docs under
docs/.
Design-To-Todo Workflow
When generating a todo document from a design document:
- Start the todo document with a first task to create a dedicated branch for that todo list.
- End the todo document with a final task to merge that branch back into
mainafter the todo list is complete and validated.
11) Coding Conventions for Agents
- Follow existing style and naming in touched files.
- Prefer explicit, readable code over cleverness.
- Keep diffs coherent (group related edits, avoid drive-by formatting).
- Add comments only when they clarify non-obvious reasoning.
- No legacy API preservation is required pre-ship; improve APIs freely when it yields a better v1.
XRBase Field Mutation Rule
- For any class deriving from
XRBase(directly or indirectly), do not set backing fields directly from property setters or similar mutation paths. - Use
SetField(...)for state changes so the engine's change-notification/invalidation pipeline remains correct and consistent. - When touching existing code that assigns fields directly in
XRBase-derived types, prefer refactoring toSetField(...)as part of the change.
Warnings Policy
- Keep compiler warnings to a minimum. New code must not introduce warnings.
- When touching a file that already has warnings, fix them if the fix is low-risk.
- Treat
#pragma warning disableas a last resort; prefer resolving the root cause.
Hot-Path Allocation Discipline
This is a game engine. Heap allocations in per-frame hot paths are treated as bugs unless proven harmless by profiling.
Hot paths include (but are not limited to):
- Render – draw call submission, command buffer recording, material/shader bind.
- Swap – buffer swap, frame presentation.
- Collect Visible – frustum culling, octree/BVH traversal, visibility determination.
- Fixed Update – physics step, fixed-rate simulation ticks.
- Update – per-frame game logic, transform propagation, animation tick.
When reviewing or writing code in these paths:
- Flag / refactor any
newobject allocations, LINQ queries,foreachover non-struct enumerators, closures/lambdas that capture,stringconcatenation, or boxing. - Prefer:
Span<T>,stackalloc, object pooling / rent-return patterns, pre-allocated lists/arrays,ref struct,unsafepointer arithmetic where appropriate, and cached delegates. - Suggest allocation-reducing improvements proactively when touching nearby code, even if not explicitly requested.
- When an allocation is unavoidable (e.g., first-time init, rare path), add a brief comment explaining why it's acceptable.
12) PR / Commit Expectations
When asked to prepare commits:
- Use simple imperative subject lines.
- Good:
Refactor asset import fallback for deterministic extension selection - Good:
Update networking pose task docs for client role flags
- Good:
Suggested PR summary structure:
- What changed
- Why
- Validation performed (targeted tests/build)
- Risks and follow-ups
13) Native Dependencies and External Tooling Notes
Be aware of repository-managed native/tooling dependencies:
- CoACD build/fetch scripts under
Tools/Dependencies/. - MagicPhysX native interop binary expectations.
- Rive native DLL workflow via submodules/build scripts.
- Optional YouTube URL extraction via
yt-dlp(Install-YtDlptask). - Optional nvCOMP/CUDA native binaries via
Tools/Dependencies/Get-NvComp.ps1(Install-NvComptask). - Optional NVIDIA SDK binaries under
ThirdParty/NVIDIA/SDK/win-x64/.
Do not silently change these supply paths; treat as risky operations requiring proposal/approval when impact is non-trivial.
After any change to NuGet packages or submodules, run:
pwsh Tools/Generate-Dependencies.ps1
and commit the refreshed docs/DEPENDENCIES.md + docs/licenses/ output. See §9 License compliance for the full policy.
14) Ready-to-Use Task Template for Agents
Before coding:
- Confirm subsystem and expected run mode (Editor/Server/VRClient/Pose).
- Confirm if broader subsystem sweep is desired (default: yes when useful).
During coding:
- Keep a small, explicit checklist.
- Make coherent edits with root-cause intent.
Before handoff:
- Run targeted tests/build for touched area.
- Include any opportunistic unrelated fixes you made (if small).
- Call out any larger unrelated failures.
- Update docs for any user-facing workflow/flag/task changes.
15) MCP Server (AI / External Tool Integration)
The editor embeds an MCP (Model Context Protocol) server that exposes scene hierarchy, component, transform, asset, and editor-state operations over HTTP JSON-RPC 2.0. This lets AI assistants (e.g., GitHub Copilot, Claude) and custom tooling interact with a running editor instance.
Full documentation: docs/features/mcp-server.md.
Enabling / disabling the server
The MCP server can be toggled at any time while the editor is running — it is not limited to startup.
Option A — Editor Preferences (recommended for runtime toggling):
Open the Global Editor Preferences panel in the ImGui editor and look for the MCP Server category. Flip McpServerEnabled to true. Changes take effect immediately; the server starts (or stops) without restarting the editor. You can also change McpServerPort on the fly — the server will restart on the new port.
Option B — Command-line flags (set-and-persist):
XREngine.Editor.exe --mcp # enable on default port 5467
XREngine.Editor.exe --mcp --mcp-port 8080 # enable on custom port
Command-line flags write to the same preferences, so the server stays enabled on subsequent launches unless the preference is toggled back off.
Connecting VS Code / Copilot
Add the server to .vscode/mcp.json (workspace-scoped) or VS Code user settings:
{
"servers": {
"xrengine": {
"type": "http",
"url": "http://localhost:5467/mcp/"
}
}
}
Once the editor's MCP server is running, the tools (e.g., list_worlds, list_scene_nodes, create_scene_node, capture_viewport_screenshot) appear in the Copilot Chat tools panel.
Key settings reference
| Setting | Default | Description |
|---|---|---|
McpServerEnabled | false | Enable/disable at runtime |
McpServerPort | 5467 | HTTP port |
McpServerRequireAuth | false | Require Authorization: Bearer header |
McpServerReadOnly | false | Block mutating tools |
McpServerAllowedTools / McpServerDeniedTools | "" | Per-tool allow/deny lists |
McpServerRateLimitEnabled | false | Per-client rate limiting |
See docs/features/mcp-server.md for the full settings table, protocol details, available commands, and instructions for adding new tools.
Regenerating MCP docs
After adding or renaming MCP tools, regenerate the tool table in the docs:
pwsh Tools/Reports/generate_mcp_docs.ps1
If this file conflicts with an explicit task request, follow the explicit request and note the deviation in your summary.