Imported from directivegames/Grim2 (
AGENTS.md). Install upstream withnpx skills add directivegames/Grim2. Copyright stays with the author.
GENESYS-SDK-BEGIN
Assets
Engine Assets
-
The engine's default assets are located in the
node_modules/@gnsx/genesys.js/assetsdirectory. -
To reference these assets in your code, replace the
node_modules/@gnsx/genesys.jsprefix with@enginein the asset path.Example:
If an asset is located at:
node_modules/@gnsx/genesys.js/assets/models/SM_Cube.glb
Then the corresponding URL should be:
@engine/assets/models/SM_Cube.glb
Project Assets
-
The project's assets are located in the
/assetsdirectory. -
To reference these assets in your code, use the fully qualified path with
@projectprefix.Example:
If an asset is located at:
/assets/models/tiger.glb
Then the corresponding URL should be:
@project/assets/models/tiger.glbImportant: Always use the complete path with
@project/assets/prefix rather than relative paths. This ensures compatibility with publishing tools and build processes. You should never construct a project path programmatically.
Resolve Asset Paths
- Using asset paths containing
@engineor@projectin raw html will not work out of the box as the browser doesn't know how to resolve them. The solution is to resolve them usingENGINE.resolveAssetPathsInTextfirst. Example:const htmlString = '...<img src="@engine/assets/textures/Checkerboard.png">...' const resolvedHtml = await ENGINE.resolveAssetPathsInText(htmlString); // then use resolvedHtml as normal
Loading Textures (Runtime)
@project//@engine/:ENGINE.resourceManager.loadTexture(ENGINE.AssetPath.fromString('@project/.../foo.png'))— keep the logical path (.png/.jpg) even with baking.- Never
TextureLoaderafter resolve (baking →.ktx2).TextureLoaderonly for external URLs;resolveAssetPathsInTextonly for HTML.
Prefabs
- Prefabs are json files stored under
/assets(commonly/assets/prefabs), with the suffix.prefab.json. - Prefer Prefabs for reusable scene-node templates.
- When referencing classes in prefab/serialized data, use the appropriate prefix.
Engine classes must be referenced as
ENGINE.{class name}, example:ENGINE.SceneNode,ENGINE.MeshNode. Custom game classes must be referenced asGAME.{class name}, example:GAME.MyCustomNode,GAME.MyPickupRoot.
Scene And Editor State
Do not read or open *.genesys-scene files unless the user explicitly asks or MCP is unavailable and filesystem fallback is appropriate. These files are large and the editor is the source of truth for scene state.
For scene-visible or editor-authored changes, use Genesys MCP first when Connected or Probe-capable (see .cursor/rules/genesys-mcp.mdc and .agents/skills/genesys-mcp-orchestrator/SKILL.md). Before mutations, run query_editor(getState); read-only queries can go straight to query_node / run_script(readOnly). Mutate with action_node, action_scene, or batch_execute / run_script, then action_scene(save) when the scene changed.
Before writing code, decide where this state should live (scene/editor vs runtime behaviour) and route accordingly.
| State owner | Use |
|---|---|
| Scene / editor | MCP first — per-scene or per-instance node transform, hierarchy, node properties (material on MeshNode, colours, mesh/model refs, light/camera settings), prefab instance overrides, active scene |
| Runtime behaviour | TypeScript — reusable gameplay logic, class defaults, constructors for new runtime objects, new SceneNode/PrimitiveNode subclasses, input, networking, UI logic, systems not already in the scene |
| Both | Code first to build/register the capability, then MCP to place or configure it in the scene |
Do not use beginPlay, constructors, or one-off runtime hacks to patch a specific editor-authored node just to persist a visual scene change. It is still correct to define reusable class defaults, construct runtime-created objects, and initialise behaviour in code when those values should apply to every instance or to objects spawned at runtime.
Coding Rules
CRITICAL: Never edit auto-imports.ts - This file is automatically generated by the build pipeline to register all @ENGINE.GameClass() decorated classes. Any manual changes will be overwritten and may break the build system. Classes with proper @ENGINE.GameClass() decorators are automatically discovered and imported.
General Guidelines
- Before implementing, take a hard look of the engine and figure out what can be used to implement the user's requirement. Do not reinvent wheels. When using the search tool, expand the search parameters with similar keywords.
- Work WITH the engine architecture, NOT against it.
- Try to find and use appropriate art assets as needed if the user does not specify. Check both engine and project assets for something that fits the feature.
- You should avoid writing monolithic code — do not place all logic, definitions, and configurations into a single file.
Instead, structure your code into modular, reusable, and maintainable components. - Custom node classes must not be registered as
EngineClass, useGameClassinstead. - Do not create documentation or test/example code unless specifically asked to.
- Be very brief on the summary when the implementation is completed.
Engine Source Reference
- The engine source code is available in the
.enginefolder at the project root. - Use the engine source as the primary reference when implementing game code to understand:
- Class hierarchies and inheritance patterns
- Available methods, properties, and their signatures
- Engine conventions and coding patterns
- How built-in features are implemented
- When extending engine classes or implementing similar functionality, study the existing engine code to ensure consistency and proper integration.
- The
.enginefolder mirrors the structure of the engine package — search here first when you need to understand how a particular system works.
UI
- Any HTML UI you create MUST NOT be added to the document root directly. Add them to the game UI container, which can be accessed through
world.gameContainer. - For in-game UI (HUD, menus, buttons, bars, inventories, crosshairs, minimaps, counters, etc.), prefer the engine's
BaseUIComponentwidgets (Game UI Kit) over hand-rolling HTML / CSS. See thegenesys-ui-kitskill in.agents/skills/genesys-ui-kit/— itsreferences/catalog.mdlists every shipped widget. Fall back to raw HTML only when the user asks for a custom look or no widget matches. - Safe UI (XSS): Dynamic strings (player names, chat, scores, RPC /
joinParams) go through text setters (setLabel,setMessage,setTitle) orelement.textContent— neverinnerHTML,setHTML,iconHtml/setIconHtml, orimageHtml. Those*HtmlAPIs are for developer-authored markup only (e.g.ENGINE.Icons.*). Do not put network or player strings intocustomStyles. Follow the Safe UI section in thegenesys-ui-kitskill and.agents/skills/genesys-ui-kit/references/safe-ui.md.
Testing Constraints
- You may only use
pnpm buildto verify code compilation. - You must use
pnpm lintto detect and auto-fix linting issues. - For every shell command (
pnpm,git, TypeScript tools, etc.), setworkingDirectoryto this game project root — the folder that containspackage.jsonand the.genesys-projectfile. Do not rely on the default shell cwd; it may be the Genesys desktop app process directory. - To register newly added game classes in the running editor, use MCP
action_build(action="buildProject");pnpm build-projecttalks to the SDK app file server and is not reliable from an agent shell. - Do not run
pnpm test,pnpm dev, orpnpm start— these commands are not supported. - All testing is the responsibility of the user.
You are encouraged to:- Recommend suitable testing approaches.
- Collaborate with the user to evaluate test results.
Prompt Handling & Clarification
Before implementing any user request, you must interpret the prompt, identify ambiguities, and either:
- State clear assumptions before coding, or
- Ask the user targeted clarification questions.
Required Steps
- Understand intent — Restate what the user is asking in your own words.
- Identify ambiguities — Look for vague or overloaded terms.
- Clarify or assume —
- If unclear, ask specific, short questions to confirm meaning.
- If the user cannot clarify, proceed with explicit, written assumptions.
- Confirm scope — Specify what systems, assets, or files you will change.
This process prevents incorrect implementations when user wording is incomplete or ambiguous.
Implementation Plan Tags
When planning mixed work, tag each step by state owner so scene edits are not mistaken for code tasks:
[Code]— TypeScript/source changes[MCP]— scene, node, prefab, material, transform, or other editor state changes[Asset]— imported, moved, or generated asset files[Verify]— build, lint, diagnostics, or editor re-query
Example: [MCP] Set MeshNode material on Floor root → [Verify] Re-query node and confirm scene saved.