@dcl-regenesislabs/opendcl 0.2.1-26165320302.commit-e6effe4 → 0.2.1-26238928766.commit-28648d7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +5 -3
  2. package/context/sdk7-cheat-sheet.md +4 -0
  3. package/dist/index.js +0 -12
  4. package/dist/index.js.map +1 -1
  5. package/extensions/dcl-init.ts +58 -6
  6. package/package.json +3 -3
  7. package/prompts/system.md +71 -41
  8. package/skills/add-3d-models/SKILL.md +120 -70
  9. package/skills/add-interactivity/SKILL.md +74 -2
  10. package/skills/advanced-input/SKILL.md +34 -1
  11. package/skills/advanced-rendering/SKILL.md +82 -9
  12. package/skills/animations-tweens/SKILL.md +203 -98
  13. package/skills/audio-analysis/SKILL.md +164 -0
  14. package/skills/audio-video/SKILL.md +184 -83
  15. package/skills/build-ui/SKILL.md +25 -2
  16. package/skills/camera-control/SKILL.md +78 -7
  17. package/skills/create-scene/SKILL.md +56 -13
  18. package/skills/deploy-scene/SKILL.md +12 -0
  19. package/skills/deploy-worlds/SKILL.md +35 -0
  20. package/skills/editor-gizmo/.gitignore +11 -0
  21. package/skills/editor-gizmo/SKILL.md +222 -0
  22. package/skills/editor-gizmo/src/__editor/camera.ts +277 -0
  23. package/skills/editor-gizmo/src/__editor/discovery.ts +186 -0
  24. package/skills/editor-gizmo/src/__editor/drag.ts +265 -0
  25. package/skills/editor-gizmo/src/__editor/gizmo.ts +496 -0
  26. package/skills/editor-gizmo/src/__editor/history.ts +72 -0
  27. package/skills/editor-gizmo/src/__editor/index.ts +137 -0
  28. package/skills/editor-gizmo/src/__editor/input.ts +55 -0
  29. package/skills/editor-gizmo/src/__editor/math-utils.ts +114 -0
  30. package/skills/editor-gizmo/src/__editor/persistence.ts +113 -0
  31. package/skills/editor-gizmo/src/__editor/selection.ts +157 -0
  32. package/skills/editor-gizmo/src/__editor/state.ts +117 -0
  33. package/skills/editor-gizmo/src/__editor/ui.tsx +697 -0
  34. package/skills/game-design/SKILL.md +1 -2
  35. package/skills/lighting-environment/SKILL.md +103 -56
  36. package/skills/multiplayer-sync/SKILL.md +31 -2
  37. package/skills/nft-blockchain/SKILL.md +45 -40
  38. package/skills/npcs/SKILL.md +180 -0
  39. package/skills/optimize-scene/SKILL.md +7 -2
  40. package/skills/particle-system/SKILL.md +222 -0
  41. package/skills/player-avatar/SKILL.md +133 -7
  42. package/skills/player-physics/SKILL.md +93 -0
  43. package/skills/scene-runtime/SKILL.md +9 -5
  44. package/skills/visual-feedback/SKILL.md +1 -0
  45. package/extensions/dcl-setup-ollama.ts +0 -312
package/README.md CHANGED
@@ -26,7 +26,7 @@ The result: **more creators building more scenes, faster.**
26
26
  ## Features
27
27
 
28
28
  - **Branded header** — on startup, displays a block-character "Decentraland" ASCII art banner with version and working directory. Falls back to a compact text header on narrow terminals
29
- - **Multi-provider LLM support** — works with Claude, OpenAI, Google, Ollama (free/local), OpenRouter, and more
29
+ - **Multi-provider LLM support** — works with Claude, OpenAI, Google, OpenRouter, and more
30
30
  - **Scene-aware** — automatically detects your project's `scene.json`, SDK version, and entry points
31
31
  - **20 built-in skills** — scaffolding, 3D models, interactivity, UI, animations, multiplayer, authoritative server, audio/video, deployment (Genesis City & Worlds), optimization, camera control, lighting, player/avatar, NFT/blockchain, advanced rendering, advanced input, scene runtime, visual feedback, game design
32
32
  - **Integrated commands** — `/init` to scaffold, `/preview` to launch the dev server, `/tasks` to manage running processes, `/review` to audit code
@@ -99,6 +99,7 @@ This uses the open [skills](https://github.com/vercel-labs/skills) CLI to copy S
99
99
  | `/deploy` | Deploy the scene to Genesis City or a World (auto-detects from scene.json) |
100
100
  | `/tasks` | Interactively manage running background processes (preview server, etc.) |
101
101
  | `/review` | Review scene code for quality, performance, and SDK7 best practices |
102
+ | `/save-editor` | Apply pending visual editor changes to scene source code |
102
103
  | `/explain <concept>` | Explain a Decentraland SDK7 concept (e.g., `/explain tweens`) |
103
104
 
104
105
  The agent also has a `screenshot` tool it can call automatically to see the running preview. On first use it asks for your permission to open a headless browser. The browser stays open for the entire session — no repeated logins.
@@ -129,6 +130,7 @@ OpenDCL loads domain-specific skills on demand based on what you're asking:
129
130
  | `scene-runtime` | Async tasks, fetch, timers, realm info, restricted actions, testing |
130
131
  | `visual-feedback` | Use the screenshot tool to see your scene, verify changes, iterate visually |
131
132
  | `game-design` | Plan game architecture, scene limits, state management, MVP planning |
133
+ | `editor-gizmo` | Use a visual in-scene editor with translate/rotate gizmos |
132
134
 
133
135
  ## How It Works
134
136
 
@@ -150,7 +152,7 @@ opendcl/
150
152
  │ └── scene-context.ts # Scene detection & context formatting
151
153
  ├── extensions/
152
154
  │ ├── dcl-context.ts # Auto-detect scene, inject metadata
153
- │ ├── dcl-init.ts # /init command
155
+ │ ├── dcl-init.ts # /init command + editor setup
154
156
  │ ├── dcl-preview.ts # /preview command
155
157
  │ ├── dcl-deploy.ts # /deploy command
156
158
  │ ├── dcl-setup.ts # /setup command (cloud API provider config)
@@ -159,6 +161,7 @@ opendcl/
159
161
  │ ├── dcl-validate.ts # Post-write TypeScript validation
160
162
  │ ├── dcl-screenshot.ts # screenshot tool (headless Chrome, persistent browser)
161
163
  │ ├── dcl-tasks.ts # /tasks command (process manager)
164
+ │ ├── dcl-editor-save.ts # /save-editor command (apply visual editor changes)
162
165
  │ ├── process-registry.ts # Shared background process registry
163
166
  │ └── permissions/ # Permission gate for dangerous operations
164
167
  ├── skills/ # 20 SKILL.md files (domain expertise)
@@ -231,7 +234,6 @@ OpenDCL supports any provider compatible with pi-coding-agent:
231
234
  | Anthropic (Claude) | `ANTHROPIC_API_KEY` | Best quality |
232
235
  | OpenAI | `OPENAI_API_KEY` | GPT-4o, o1, etc. |
233
236
  | Google | `GOOGLE_API_KEY` | Gemini models |
234
- | Ollama | — | Free, runs locally |
235
237
  | OpenRouter | `OPENROUTER_API_KEY` | Access to many models |
236
238
 
237
239
  Set the environment variable or enter the key on first run. Switch models anytime with `Ctrl+P`.
@@ -34,6 +34,10 @@ removeEntityWithChildren(engine, entity)
34
34
 
35
35
  // Components — CRUD
36
36
  Transform.create(entity, { position: Vector3.create(8, 1, 8) })
37
+ // ⚠️ NEVER pass undefined values in Transform fields — the SDK serializer crashes
38
+ // reading .x on undefined. If a field is optional, omit the key entirely:
39
+ // BAD: Transform.create(e, { position, rotation }) // rotation may be undefined
40
+ // GOOD: Transform.create(e, rotation ? { position, rotation } : { position })
37
41
  const t = Transform.get(entity) // read-only, throws if missing
38
42
  const t = Transform.getMutable(entity) // mutable reference
39
43
  const t = Transform.getOrNull(entity) // read-only, returns null if missing
package/dist/index.js CHANGED
@@ -67,10 +67,6 @@ const extensions = headless
67
67
  "dcl-asset-path.ts",
68
68
  "dcl-screenshot.ts",
69
69
  ];
70
- // Conditionally load dcl-setup-ollama (hidden by default, enable with ENABLE_OLLAMA_SETUP=true)
71
- if (!headless && process.env.ENABLE_OLLAMA_SETUP === "true") {
72
- extensions.push("dcl-setup-ollama.ts");
73
- }
74
70
  for (const ext of extensions) {
75
71
  args.push("-e", join(extDir, ext));
76
72
  }
@@ -90,14 +86,6 @@ if (!isDev()) {
90
86
  }
91
87
  // InteractiveMode patches — only needed for terminal UI, skip in headless mode
92
88
  if (!headless) {
93
- // Suppress pi's generic "No models available" warning — our dcl-setup-ollama
94
- // extension shows a more helpful message that mentions /setup-ollama.
95
- const _showWarning = InteractiveMode.prototype.showWarning;
96
- InteractiveMode.prototype.showWarning = function (msg) {
97
- if (msg.startsWith("No models available"))
98
- return;
99
- _showWarning.call(this, msg);
100
- };
101
89
  // Suppress pi's "What's New" changelog notification on startup — it shows pi's
102
90
  // own version/changes, which confuses OpenDCL users.
103
91
  InteractiveMode.prototype.getChangelogForDisplay = function () {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -3,24 +3,40 @@
3
3
  *
4
4
  * Registers the `init` tool (LLM-callable) and `/init` command that scaffolds
5
5
  * a new Decentraland scene project using `npx @dcl/sdk-commands init`.
6
+ * After scaffolding, triggers the editor-gizmo skill to set up the visual editor.
7
+ * On session start, prompts the user to enable the editor if a scene exists but lacks it.
6
8
  */
7
9
 
8
10
  import type { ExtensionFactory } from "@mariozechner/pi-coding-agent";
9
11
  import { Type } from "@sinclair/typebox";
10
12
  import { join } from "node:path";
11
13
  import { readFile, writeFile } from "node:fs/promises";
12
- import { fileExists } from "./scene-utils.js";
14
+ import { fileExists, findSceneRoot } from "./scene-utils.js";
15
+
16
+ function triggerEditorSkill(pi: { sendMessage(msg: unknown, opts?: unknown): void }) {
17
+ pi.sendMessage(
18
+ {
19
+ customType: "editor-setup",
20
+ content: "Scene initialized (dependencies not yet installed). Now set up the visual editor by following the editor-gizmo skill.",
21
+ display: true,
22
+ },
23
+ { triggerTurn: true }
24
+ );
25
+ }
13
26
 
14
27
  async function initScene(
15
28
  cwd: string,
16
- pi: { exec(cmd: string, args: string[], opts?: unknown): Promise<{ code: number; stdout: string; stderr: string }> }
29
+ pi: {
30
+ exec(cmd: string, args: string[], opts?: unknown): Promise<{ code: number; stdout: string; stderr: string }>;
31
+ sendMessage(msg: unknown, opts?: unknown): void;
32
+ }
17
33
  ): Promise<{ message: string; isError?: boolean }> {
18
34
  if (await fileExists(join(cwd, "scene.json"))) {
19
35
  return { message: "A scene.json already exists in this directory. Aborting to prevent overwriting.", isError: true };
20
36
  }
21
37
 
22
38
  try {
23
- const result = await pi.exec("npx", ["@dcl/sdk-commands", "init", "--yes"], {
39
+ const result = await pi.exec("npx", ["@dcl/sdk-commands", "init", "--yes", "--skip-install"], {
24
40
  cwd,
25
41
  timeout: 180000,
26
42
  });
@@ -36,7 +52,23 @@ async function initScene(
36
52
  } catch {
37
53
  // Non-fatal: scene was still initialized successfully
38
54
  }
39
- return { message: "Scene initialized and dependencies installed! Use the preview tool to start." };
55
+
56
+ // Append OpenDCL build artifacts to .gitignore so they don't get committed.
57
+ // main.crdt is generated from main-entities.ts at bundle time.
58
+ try {
59
+ const ignorePath = join(cwd, ".gitignore");
60
+ let existing = "";
61
+ try { existing = await readFile(ignorePath, "utf-8"); } catch {}
62
+ if (!existing.split(/\r?\n/).includes("main.crdt")) {
63
+ const sep = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
64
+ await writeFile(ignorePath, existing + sep + "main.crdt\n");
65
+ }
66
+ } catch {
67
+ // Non-fatal: scene still works without .gitignore updates
68
+ }
69
+
70
+ triggerEditorSkill(pi);
71
+ return { message: "Scene initialized! Setting up visual editor..." };
40
72
  } else {
41
73
  return { message: `Init failed (exit code ${result.code}): ${result.stderr || result.stdout}`, isError: true };
42
74
  }
@@ -50,7 +82,7 @@ const extension: ExtensionFactory = (pi) => {
50
82
  name: "init",
51
83
  label: "Init Scene",
52
84
  description:
53
- "Initialize a new Decentraland SDK7 scene. Scaffolds scene.json, package.json, tsconfig.json, and src/index.ts. Use when user wants to create or start a new scene.",
85
+ "Initialize a new Decentraland SDK7 scene with visual editor. Scaffolds scene.json, package.json, tsconfig.json, src/index.ts, and the __editor/ directory. Use when user wants to create or start a new scene.",
54
86
  parameters: Type.Object({}),
55
87
  async execute(_id, _params, _signal, _onUpdate, ctx) {
56
88
  const result = await initScene(ctx.cwd, pi);
@@ -60,7 +92,7 @@ const extension: ExtensionFactory = (pi) => {
60
92
  });
61
93
 
62
94
  pi.registerCommand("init", {
63
- description: "Initialize a new Decentraland scene project in the current directory",
95
+ description: "Initialize a new Decentraland scene project with visual editor",
64
96
  handler: async (_args, ctx) => {
65
97
  ctx.ui.notify("Initializing new Decentraland scene...", "info");
66
98
  const result = await initScene(ctx.cwd, pi);
@@ -68,6 +100,26 @@ const extension: ExtensionFactory = (pi) => {
68
100
  if (!result.isError) await ctx.reload();
69
101
  },
70
102
  });
103
+
104
+ // Prompt on session start if scene exists but editor is not installed
105
+ let editorPromptShown = false;
106
+ pi.on("before_agent_start", async (_event, ctx) => {
107
+ if (editorPromptShown) return;
108
+ editorPromptShown = true;
109
+
110
+ const sceneRoot = await findSceneRoot(ctx.cwd);
111
+ if (!sceneRoot) return;
112
+
113
+ if (await fileExists(join(sceneRoot, "src", "__editor", "state.ts"))) return;
114
+
115
+ const enable = await ctx.ui.confirm(
116
+ "Visual Editor",
117
+ "Enable the visual editor for this scene?"
118
+ );
119
+ if (!enable) return;
120
+
121
+ triggerEditorSkill(pi);
122
+ });
71
123
  };
72
124
 
73
125
  export default extension;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcl-regenesislabs/opendcl",
3
- "version": "0.2.1-26165320302.commit-e6effe4",
3
+ "version": "0.2.1-26238928766.commit-28648d7",
4
4
  "description": "AI coding assistant for Decentraland SDK7 scene development",
5
5
  "type": "module",
6
6
  "bin": {
@@ -48,7 +48,7 @@
48
48
  "url": "git+https://github.com/dcl-regenesislabs/opendcl.git"
49
49
  },
50
50
  "dependencies": {
51
- "@mariozechner/pi-coding-agent": "^0.54.0",
51
+ "@mariozechner/pi-coding-agent": "^0.62.0",
52
52
  "playwright-core": "^1.58.2"
53
53
  },
54
54
  "devDependencies": {
@@ -71,5 +71,5 @@
71
71
  "prompts/",
72
72
  "context/"
73
73
  ],
74
- "commit": "e6effe4fc6a905650318f31bf496a5d108a1d182"
74
+ "commit": "28648d736e3cd0f11630168013ee7ca6075abb45"
75
75
  }
package/prompts/system.md CHANGED
@@ -25,26 +25,58 @@ You are **OpenDCL**, an AI coding assistant specialized in Decentraland SDK7 sce
25
25
  - 1 parcel: ~512 entities, ~10,000 triangles. Scales with parcel count.
26
26
  - All coordinates are in meters. Y is up. Scene origin (0,0,0) is the southwest corner of the base parcel at ground level.
27
27
 
28
- ### Key Patterns
28
+ ### Authoring Model: Data in `main-entities.ts`, Behavior in `src/`
29
29
 
30
- **Creating an entity with components:**
31
- ```typescript
32
- import { engine, Transform, MeshRenderer, Material } from '@dcl/sdk/ecs'
33
- import { Vector3, Color4 } from '@dcl/sdk/math'
30
+ OpenDCL scenes split the source of truth in two:
31
+
32
+ - **`main-entities.ts`** at the scene root — typed declarative entities keyed by Name, with their data components (Transform, GltfContainer, MeshRenderer, Material, AudioSource, etc.). Compiled to `main.crdt` at build time and preloaded by the engine before `main()` runs.
33
+ - **`src/index.ts`** — behavior only. References entities by Name and attaches systems, pointer events, tweens.
34
34
 
35
- const cube = engine.addEntity()
36
- Transform.create(cube, { position: Vector3.create(8, 1, 8) })
37
- MeshRenderer.setBox(cube)
38
- Material.setPbrMaterial(cube, { albedoColor: Color4.Red() })
35
+ **Adding a declared entity (in `main-entities.ts`):**
36
+ ```typescript
37
+ import type { Scene } from '@dcl/sdk/scene-types'
38
+
39
+ export const scene = {
40
+ blue_cube: {
41
+ components: {
42
+ Transform: { position: { x: 8, y: 1, z: 8 }, rotation: { x: 0, y: 0, z: 0, w: 1 }, scale: { x: 1, y: 1, z: 1 } },
43
+ MeshRenderer: { mesh: { $case: 'box', box: { uvs: [] } } },
44
+ Material: { material: { $case: 'pbr', pbr: { albedoColor: { r: 1, g: 0, b: 0, a: 1 } } } },
45
+ },
46
+ },
47
+ } satisfies Scene
39
48
  ```
40
49
 
41
- **Adding interactivity:**
50
+ **Referencing it in code:**
42
51
  ```typescript
43
- import { pointerEventsSystem, InputAction } from '@dcl/sdk/ecs'
52
+ import { engine, pointerEventsSystem, InputAction } from '@dcl/sdk/ecs'
53
+ import type { scene } from '../main-entities'
44
54
 
45
- pointerEventsSystem.onPointerDown({ entity: cube, opts: { button: InputAction.IA_POINTER, hoverText: 'Click me' } }, () => {
46
- // Handle click
47
- })
55
+ type EntityName = keyof typeof scene
56
+
57
+ export function main() {
58
+ const cube = engine.getEntityOrNullByName<EntityName>('blue_cube')
59
+ if (cube === null) return
60
+
61
+ pointerEventsSystem.onPointerDown(
62
+ { entity: cube, opts: { button: InputAction.IA_POINTER, hoverText: 'Click me' } },
63
+ () => { /* handle click */ },
64
+ )
65
+ }
66
+ ```
67
+
68
+ **Rules:**
69
+ - Every declarative entity goes in `main-entities.ts` with a unique Name. The `satisfies Scene` clause keeps literal keys typed for safe references.
70
+ - Parents are referenced by Name (`parent: 'barrel_1'`); the build resolves them.
71
+ - Pure-data components (Transform, GltfContainer, MeshRenderer, MeshCollider, Material, AudioSource, VideoPlayer, TextShape, Animator config, NftShape, Billboard, VisibilityComponent) all live in `main-entities.ts`.
72
+ - Behavior, callbacks, systems, conditional logic stay in `src/`.
73
+ - The `scene` literal must contain only JSON-compatible values — no function calls, no spreads, no comments inside the object.
74
+
75
+ **Dynamic entities** spawned at runtime (effects, projectiles, runtime markers) still use `engine.addEntity()` and **don't get Names** — they're invisible to the editor and not persisted:
76
+ ```typescript
77
+ const explosion = engine.addEntity()
78
+ Transform.create(explosion, { position: Vector3.create(...) })
79
+ GltfContainer.create(explosion, { src: 'models/Explosion.glb' })
48
80
  ```
49
81
 
50
82
  **Systems (per-frame logic):**
@@ -73,10 +105,11 @@ export function setupUi() {
73
105
  ```
74
106
  scene-project/
75
107
  ├── scene.json # Scene metadata (parcels, title, main entry)
108
+ ├── main-entities.ts # Declarative entities (data) — preloaded into the engine before main() runs
76
109
  ├── package.json # Dependencies (@dcl/sdk)
77
- ├── tsconfig.json # TypeScript config
110
+ ├── tsconfig.json # TypeScript config (must include main-entities.ts)
78
111
  └── src/
79
- ├── index.ts # Main entry point (export function main)
112
+ ├── index.ts # Main entry point references entities by Name, attaches behavior
80
113
  └── ui.tsx # UI components (optional)
81
114
  ```
82
115
 
@@ -94,19 +127,25 @@ scene-project/
94
127
  ## How to Help Users
95
128
 
96
129
  ### Empty Folder (No scene.json)
97
- 1. Ask the user what they want to build.
98
- 2. **Use the `init` tool first** — this uses the official SDK scaffolding to create scene.json, package.json, tsconfig.json, and src/index.ts with the correct, up-to-date configuration, and installs dependencies. Never create these files manually.
99
- 3. After init completes, customize `scene.json` (title, description, parcels) and add the first element to `src/index.ts`. Then offer next steps — don't build the entire scene at once.
130
+ **Do NOT ask the user what they want to build.** Instead, immediately run the `init` tool to scaffold the project — no questions, no menu of options, just init. This uses the official SDK scaffolding to create scene.json, package.json, tsconfig.json, and src/index.ts with the correct, up-to-date configuration, and installs dependencies. Never create these files manually. After init completes, ask the user what they'd like to do next. Offer small, concrete steps — don't propose building an entire scene at once.
100
131
 
101
132
  ### Existing Scene
102
- 1. Read scene.json and src/index.ts to understand the project.
133
+ 1. Read scene.json, main-entities.ts (if it exists), and src/index.ts to understand the project.
103
134
  2. Offer contextual help — adding features, fixing bugs, optimizing.
104
135
  3. Always preserve existing code when making edits.
136
+ 4. When adding a new declarative entity (cube, model, lamp, etc.), edit `main-entities.ts` and reference the new Name from `src/index.ts` if it needs behavior. Don't reach for `engine.addEntity()` in code as a default.
105
137
 
106
138
  ### Best Practices
139
+
140
+ **Always declare static / editable entities in `main-entities.ts`** — never via `engine.addEntity()` in `src/index.ts` for things the user might want to move, rotate, or see in the visual editor. Entities declared in `main-entities.ts` are preloaded by the engine before `main()` runs, are visible in the editor's hierarchy panel, and are draggable. Entities created at runtime via `engine.addEntity()` are invisible to the editor and lost when the user reloads.
141
+
142
+ Use `engine.addEntity()` only for genuinely dynamic things (effects spawned at runtime, projectiles, throwaway markers). Those entities should NOT have a `Name` component — Naming is the marker for "this entity belongs in main-entities.ts."
143
+
144
+ When the user asks to add a barrel, a tree, a prop, a model — that goes in `main-entities.ts` first, and code references it via `engine.getEntityOrNullByName<EntityName>(name)`. Don't fall back to the old `addEntity + Transform.create + GltfContainer.create` pattern in code unless the user explicitly asks for runtime spawning.
145
+
107
146
  - Always position objects within the scene boundaries (based on parcels).
108
- - Use `Vector3.create()` and `Quaternion.fromEulerDegrees()` for transforms.
109
- - For 3D models, use `GltfContainer.create(entity, { src: 'models/myModel.glb' })`.
147
+ - For positions/rotations inside `main-entities.ts`, use plain object literals (`{ x: 8, y: 1, z: 8 }`), not `Vector3.create()` — the `scene` literal must stay JSON-compatible. In `src/index.ts` (behavior code), `Vector3.create()` and `Quaternion.fromEulerDegrees()` are fine.
148
+ - For 3D models, declare `GltfContainer: { src: 'models/myModel.glb' }` inside the entity's `components` block in `main-entities.ts`.
110
149
  - `GltfContainer` only works with **local files** — never use external URLs for the `src` field. Always download models into the scene's `models/` directory first.
111
150
  - Place `.glb` files in a `models/` directory, textures in `images/`.
112
151
  - Don't start the preview server automatically after writing code. The user will type `/preview` when ready.
@@ -115,39 +154,30 @@ scene-project/
115
154
  - Search with `grep -i "keyword" skills/add-3d-models/references/model-catalog.md`, fetch the preview thumbnail to confirm, then download with curl.
116
155
  - Download matching models with `curl -o models/filename.glb "URL"` before referencing them in code.
117
156
 
118
- ### Visual Iteration Workflow
119
-
120
- When the preview server is running, **proactively use the `screenshot` tool after making scene changes**. Don't wait for the user to check — verify your own work:
121
-
122
- 1. Write code or modify the scene.
123
- 2. Use `screenshot` (with a `wait` of ~2000ms for hot-reload) to see the result.
124
- 3. Describe what you see honestly — what's working, what's missing, what looks wrong.
125
- 4. If something is off, fix it and screenshot again.
157
+ ### Visual Feedback
126
158
 
127
- This way the user gets a working scene without having to open a browser and report issues back to you.
159
+ When the preview server is running, use the `screenshot` tool **after completing code changes** to verify the result. Do NOT use screenshots to explore or navigate the scene.
128
160
 
129
- The screenshot tool supports actions before capture — move around (moveForward, moveLeft, etc.), look around (lookLeft, lookUp), click objects, press keys. Use these to explore from different angles or test interactivity.
161
+ 1. Make all code changes first.
162
+ 2. Take **one** screenshot (with `wait: 2000` for hot-reload) to verify.
163
+ 3. Describe what you see honestly — what works, what's wrong.
164
+ 4. If something is off, fix the code and take **one more** screenshot to confirm.
130
165
 
131
- The browser stays open between calls only the first screenshot takes ~15s (launch + enter scene). Subsequent ones are instant.
166
+ Keep it to **1-2 screenshots per task**. Each screenshot consumes significant tokens. Do not wander around taking multiple screenshots to "explore" — that wastes the user's budget.
132
167
 
133
- If the user asks you to iterate autonomously (e.g., "keep going until it looks right"):
134
- 1. Make code changes.
135
- 2. Wait for hot reload (~2s), then take a screenshot.
136
- 3. Analyze whether the result matches the goal.
137
- 4. If not, make targeted fixes and screenshot again.
138
- 5. Repeat (up to 5 iterations) until done.
168
+ The screenshot tool supports actions before capture (move, look, click, key press), but use these sparingly and only when needed to verify a specific thing (e.g., moving to see an object you just placed behind the spawn point).
139
169
 
140
170
  ## Tools & Commands
141
171
 
142
172
  You have these Decentraland-specific tools — **use them directly** when the user's request matches:
143
173
  - `init` — Scaffold a new scene (**always use this first** in an empty folder)
144
174
  - `preview` — Start the Bevy-web preview server
145
- - `screenshot` — Capture a screenshot of the running preview. Supports movement and interaction actions before capture.
175
+ - `screenshot` — Capture a screenshot of the running preview to verify code changes. Limit to 1-2 per task.
146
176
  - `deploy` — Deploy to Genesis City or a World (auto-detects from scene.json)
147
177
  - `tasks` — List or stop running background processes
148
178
 
149
179
  The user can also type these as `/init`, `/preview`, `/deploy`, `/tasks` slash commands directly.
150
- Additional user-only commands: `/review`, `/explain`, `/setup`, `/setup-ollama`
180
+ Additional user-only commands: `/review`, `/explain`, `/setup`
151
181
 
152
182
  ## Pacing
153
183