@genex-ai/cli-demo 0.81.0-dev.214 → 0.85.0-dev.216

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 (27) hide show
  1. package/README.md +9 -7
  2. package/dist/index.js +2623 -1684
  3. package/package.json +1 -1
  4. package/templates/controllers/character/first-person.ts +54 -0
  5. package/templates/controllers/character/follow-camera.ts +35 -1
  6. package/templates/skills/genex-ai-character/SKILL.md +25 -5
  7. package/templates/skills/genex-ai-hud/SKILL.md +175 -63
  8. package/templates/skills/genex-ai-hud/references/masked-fill.md +19 -13
  9. package/templates/skills/genex-ai-hud/references/stage1-prompt-template.md +42 -5
  10. package/templates/skills/genex-ai-hud/references/stage2-prompt-template.md +7 -3
  11. package/templates/skills/genex-ai-image/SKILL.md +40 -2
  12. package/templates/skills/genex-ai-menu/SKILL.md +47 -22
  13. package/templates/skills/genex-ai-model/SKILL.md +8 -0
  14. package/templates/skills/genex-ai-music/SKILL.md +142 -0
  15. package/templates/skills/genex-ai-skybox/SKILL.md +21 -5
  16. package/templates/skills/genex-ai-video/SKILL.md +13 -7
  17. package/templates/skills/genex-ai-voice/SKILL.md +151 -0
  18. package/templates/skills/genex-game-director/SKILL.md +183 -58
  19. package/templates/skills/genex-game-director/references/design-contract.md +40 -10
  20. package/templates/skills/genex-game-director/references/routing-map.md +44 -29
  21. package/templates/skills/genex-threejs-camera-direction/SKILL.md +4 -1
  22. package/templates/skills/genex-threejs-character-controller/SKILL.md +25 -1
  23. package/templates/skills/genex-threejs-character-controller/references/wiring.md +13 -2
  24. package/templates/skills/genex-threejs-creatures/SKILL.md +201 -0
  25. package/templates/skills/genex-threejs-game-ui/SKILL.md +79 -71
  26. package/templates/skills/genex-threejs-multiplayer/SKILL.md +6 -1
  27. package/templates/skills/genex-threejs-visual-validation/SKILL.md +9 -4
@@ -1,7 +1,8 @@
1
1
  # Stage 1 prompt template — the game concept: full-HUD mockup
2
2
 
3
- Fill the four placeholders, then pass the whole text as the prompt to
4
- `npx genex image "<filled prompt>" --size 2560x1440 --quality high --candidates 2`.
3
+ Fill the placeholders, then pass the whole text as the prompt to
4
+ `npx genex image "<filled prompt>" --size 2560x1440 --quality high`.
5
+ ONE concept image — no candidate variants unless the player asks for them.
5
6
  This image IS the game concept — the user's style checkpoint and the anchor
6
7
  for all later art — so the scene half deserves the same care as the HUD half.
7
8
 
@@ -26,11 +27,35 @@ Placeholders:
26
27
  rival truck closing on the left, late-afternoon glare"
27
28
  - `[STYLE_BRIEF]` — your full 3–5 sentence style brief with the named 4–5 hue
28
29
  palette. Do NOT append the per-sprite cutout sentence here — this is a full
29
- frame, not a cutout.
30
+ frame, not a cutout. **End the brief with a named register anchor**: "in
31
+ the register of <2–3 real games>" from the table below. Anchors set the
32
+ REGISTER (stroke weight, ornament budget, composure) — never copy their
33
+ assets, and never show their names in-game. Pick 2–3; genres between rows
34
+ blend the neighbors.
35
+
36
+ | Genre register | Anchor games (2–3) |
37
+ |---|---|
38
+ | Gothic / soulslike | Bloodborne, Elden Ring |
39
+ | Clean sci-fi / arena shooter | Destiny 2, Titanfall 2 |
40
+ | Arcade racing / rally | Forza Horizon, vintage Baja rally decals |
41
+ | Cozy / farming / life sim | Stardew Valley, Spiritfarer |
42
+ | Analog survival horror | Resident Evil 7, Signalis |
43
+ | Retro pixel | Shovel Knight |
44
+ | Ornate high fantasy RPG | Diablo IV |
45
+
46
+ - `[N]` — the exact count of elements in `[ELEMENT_LIST]`, spelled out in
47
+ the ONLY-these line. The bans in that line are load-bearing: without them
48
+ the model completes the genre's canonical HUD past your list (invented
49
+ kill feeds, leaderboards, timers, extra slots — measured in 5/7 genres).
30
50
  - `[ELEMENT_LIST]` — a bullet list of your 4–7 chosen widgets with one-line
31
51
  descriptions. List only asset-backed widgets; pure-geometry elements
32
52
  (crosshairs, tick rails, plain shapes) are built in code and stay off the
33
- list.
53
+ list. **Name each element as the shaped object it is** — "bare glowing
54
+ digits with a pip row", "an etched line silhouette", "stencil digits held
55
+ by two rivet brackets". Never "panel" or "plate" unless a physical plate
56
+ IS the art (a diegetic device, a pinned note). **State exact counts**
57
+ ("exactly one tool slot", "exactly three gem sockets") — the model honors
58
+ them.
34
59
 
35
60
  ## The template
36
61
 
@@ -39,10 +64,12 @@ A screenshot of a complete game HUD for [GENRE_BRIEF]. The HUD is composited ove
39
64
 
40
65
  Visual style: [STYLE_BRIEF]
41
66
 
42
- The HUD includes these elements, arranged naturally as a real game would lay them out (you decide the layout — do not force a grid, place each element where it makes the HUD readable and combat-ready):
67
+ The HUD includes ONLY these [N] elements and nothing else — do not add any other UI: no kill feed, no leaderboard, no map, no timer, no chat, no crosshair, no extra slots, no duplicates. Arrange them naturally as a real game would lay them out (you decide the layout — do not force a grid, place each element where it makes the HUD readable and combat-ready):
43
68
 
44
69
  [ELEMENT_LIST]
45
70
 
71
+ Widget construction rules: every widget is a shaped object with its own silhouette — an ornamented frame or emblem drawn directly over the game scene. NO rectangular backing panels behind bars, digits, or icons; no dark filler boxes; the game scene stays visible right up to each widget's frame edge. All ornament and material character lives ON the frame outline itself. Keep the frames detailed and characterful — confident AAA game UI, not a sterile minimal overlay. Size widgets like a shipped game: the HUD hugs the screen edges and no single widget exceeds about one eighth of the frame width. Every meter channel interior reads visibly darker than both its fill and its surrounding frame.
72
+
46
73
  This is a real in-game screenshot. Sharp detail on every UI element. No motion blur on the HUD. The HUD is clear and combat-readable. No watermarks. No external annotations.
47
74
 
48
75
  CRITICAL — flat HUD framing: draw every HUD element flat and head-on, parallel to the screen plane, like a 2D overlay painted directly onto the display (orthographic / screen-space UI). The HUD must NOT be tilted, angled, skewed, rotated in 3D, shown in perspective, or made to recede into depth — no isometric interface, no vanishing point on the panels, no 3D-extruded or floating-at-an-angle widgets, no curved/wrapped screen. ONLY the game scene behind the HUD may show 3D depth and perspective; the HUD layer itself is a flat 2D plane with square-on, axis-aligned edges, so each widget can be cleanly cut out as a flat sprite.
@@ -53,6 +80,16 @@ not deconstruct cleanly (angled panel edges have no clean silhouette, so
53
80
  Stage 2 produces sliced, skewed cutouts). If the mockup comes back tilted,
54
81
  regenerate it before proceeding; do not try to salvage it downstream.
55
82
 
83
+ **Never delete the widget-construction paragraph either** — it is what keeps
84
+ the mockup from coming back as generic rectangles: without it, every genre
85
+ grows heavy rectangular backing plates behind its bars and digits, and the
86
+ lane's whole value (shaped, characterful chrome) is lost. The channel-contrast
87
+ sentence in it is deliberate phrasing: channels read "visibly darker than
88
+ both their fill and their frame" — a RELATIVE rule that works on light
89
+ palettes too (an absolute "dark" trough fought cozy/pale briefs). Stage 2's
90
+ EMPTY-state law (dark empty tracks on the sheet) is separate and stays
91
+ absolute.
92
+
56
93
  One more Stage-1 rule that pays off at mask time: **meter channels must be
57
94
  continuous** — never place a label or ornament in the MIDDLE of a fill
58
95
  channel (it splits the mask and the fill into fragments); labels sit above or
@@ -25,7 +25,11 @@ Fill `[ASSET_LIST]`, then pass the whole text as the prompt to
25
25
  - **requests variant cells for discrete icon counters** — hearts, ammo
26
26
  pips, stars ship as repeated sprites, not masks, so their item asks for
27
27
  the states as SEPARATE same-size cells ("the heart icon: one full, one
28
- half, one empty cell") instead of an annotated pair.
28
+ half, one empty cell") instead of an annotated pair;
29
+ - **asks for extra whitespace between meters that were STACKED in the
30
+ mockup** ("place the health-bar cells and the stamina-bar cells in
31
+ separate rows with generous spacing") — adjacent meters otherwise cluster
32
+ into one crop and the extraction tools refuse the pair.
29
33
 
30
34
  ## The template
31
35
 
@@ -37,7 +41,7 @@ Lay these assets on a pure flat white #ffffff background, separated by at least
37
41
  [ASSET_LIST]
38
42
 
39
43
  If an asset is a generated progress/bar/meter frame, output TWO CELLS immediately beside each other:
40
- 1. LEFT CELL — the clean production asset the game will use. Preserve exact style, baked_static labels, frame metal, bevels, dividers, scratches, proportions, and texture. Remove runtime dynamic fill and values. Do not paint technical colors on this clean cell.
44
+ 1. LEFT CELL — the clean production asset the game will use. Preserve exact style, baked_static labels, frame metal, bevels, dividers, scratches, proportions, and texture. Remove runtime dynamic fill and values. Every meter/bar cell shows the meter EMPTY: the channel interior is painted as the meter's dark empty track in the art's own style — recessed, unlit, like a drained lamp-oil groove or a powered-down light strip. NEVER white, NEVER a filled bar, NEVER the sheet background color inside a frame. Do not paint technical colors on this clean cell.
41
45
  2. RIGHT CELL — an annotated duplicate of the same production asset. It must be the same asset, same scale, same canvas bounds, same position, and same outer shape as the left cell. The only difference: paint runtime-fill zones with pure green key color #00ff00. Green marks only the places where runtime bar/progress fill should appear. Paint the green as a FLAT, UNIFORM, fully-saturated #00ff00 fill — no shading, no gradient, no inner shadow, no vignette, NO DARKENING TOWARD THE EDGES, no lighting, no highlights, no texture; constant color edge-to-edge with a HARD, CRISP boundary against the frame. The green is a chroma-key, not a lit surface — any edge shading makes the extracted alpha mask ragged. For segmented meters, paint each segment slot as a separate green shape; do not merge slots into one continuous strip and do not paint half-segments. Never place a label or ornament in the middle of a fill channel — labels belong above/beside the channel or on the frame's end caps.
42
46
 
43
47
  Do NOT create a separate black-background mask cell. Do NOT create a standalone simplified silhouette. The right cell is a registration-safe annotation map; local tooling derives the alpha mask from its green pixels and uses the left cell as the frame.
@@ -55,7 +59,7 @@ KEEP these baked into the asset — they are part of the panel's IDENTITY and ne
55
59
 
56
60
  REMOVE runtime-owned content:
57
61
  - Current numeric values (the "1247" coins, the "47" ammo count)
58
- - Current bar fill levels (the colored fill INSIDE a bar — runtime code reveals it through a mask)
62
+ - Current bar fill levels (the colored fill INSIDE a bar — runtime code paints the fill; the emptied channel shows the meter's own dark empty track, never white, never the sheet background)
59
63
  - Current item icons inside slots (the sword, potion — runtime renders the equipped item)
60
64
  - Current map content / radar blips (the game paints these at runtime)
61
65
  - Any editable or localizable label the design does not fuse into the frame, even if it does not change frame-to-frame
@@ -141,6 +141,32 @@ use the quad fallback or a hit-spark VFX instead. Impact marks are a first-class
141
141
  generated surface for any weapon/collision game — inventory them up front with
142
142
  the rest of your art, don't discover the bare walls at the end.
143
143
 
144
+ ## Real-translucency glass panels — `--glass`
145
+
146
+ A sprite cut from an unknown background can never carry semi-transparency —
147
+ but a panel generated on a CONTROLLED backdrop can. `--glass` appends a
148
+ flat-magenta key-screen suffix to your prompt, then (after generation) solves
149
+ the per-pixel contamination locally into REAL fractional alpha and writes
150
+ ready RGBA files (`glass-1.png`, one per candidate, into `--out-dir`,
151
+ default `.`) plus the key metrics (key color, strength, flatness):
152
+
153
+ ```bash
154
+ npx genex image "frosted translucent dark glass panel, about 40 percent opacity, thin luminous cyan frame" --glass --size 1280x832 --quality high
155
+ ```
156
+
157
+ - **Steer the translucency with words**: "frosted translucent … about 40
158
+ percent opacity" → real see-through glass; "dark smoked glass" → near-
159
+ opaque tint. The suffix handles the backdrop; your prompt owns the glass.
160
+ - **Wire the PNG like any sprite** — its alpha IS the glass. No CSS opacity
161
+ on top, no plate underneath.
162
+ - **Not for magenta/pink-hued art**: magenta in the SUBJECT keys as
163
+ translucency. Panels, frames, HUD plates — yes; a pink neon sign — no.
164
+ - A candidate whose backdrop came back shaded is REJECTED with a retryable
165
+ message (rare — regenerate). `--glass` is generation-only: it conflicts
166
+ with `--edit`/`--clean`/`--upscale`/`--transparent`/`--remove-bg`/`--no-wait`.
167
+ - Glass files are LOCAL outputs (like HUD sprites) — they ship with the
168
+ build; commit them under `public/assets/`.
169
+
144
170
  ## Multiplayer
145
171
 
146
172
  The asset URL is public, permanent, and CORS-open, so it is safe to broadcast the
@@ -181,10 +207,22 @@ See `$genex-threejs-multiplayer` for the `shared` channel rules and the room API
181
207
  - `--quality <low|medium|high>` — quality preset; higher costs more and takes longer.
182
208
  - `--size <WxH>` — exact pixel size (multiples of 16, each side ≤ 3840, aspect ≤ 3:1).
183
209
  - `--edit <url>` — edit THAT generated image with the prompt (image-to-image).
210
+ - `--inpaint <mask.png|url>` — with `--edit`: a region mask (local PNG or
211
+ asset URL; TRANSPARENT hole = the zone to change). It targets WHERE the
212
+ edit lands — the other regions keep their designs — but the WHOLE image
213
+ still re-renders and alpha is destroyed either way: after any masked edit,
214
+ re-run `--clean`/re-extraction downstream. A targeting scope, not a pixel
215
+ freeze.
184
216
  - `--clean <url>` — ML background removal of THAT image only (prompt recorded, unused).
217
+ - `--upscale <url>` — 2x utility upscale of THAT image (prompt recorded,
218
+ unused; ~2-credit class). Use before printing/large billboards, not by
219
+ default.
185
220
  - `--remove-bg` — chain ML background removal after the generation/edit.
186
- - `--bg-mode <sprite|glyph|sheet>` — background-removal model (`glyph` for
187
- digits/closed shapes; `--clean` defaults to `sheet`).
221
+ - `--bg-mode <sprite|glyph|sheet|matte>` — background-removal model (`glyph`
222
+ for digits/closed shapes; `--clean` defaults to `sheet`; `matte` = BiRefNet
223
+ SOFT alpha for hair/glow/smoke edges the binary cutters butcher).
224
+ - `--glass` — the magenta-key real-translucency lane (section above);
225
+ writes local RGBA files into `--out-dir` (default `.`).
188
226
  - `--no-wait` — enqueue and return immediately, without the URL. Fire-and-forget
189
227
  only: re-running the command creates (and bills) a NEW image.
190
228
  - `--api-url <url>` — override the API base (local dev).
@@ -81,7 +81,10 @@ reason is the failure mode this section exists to kill:**
81
81
  (cinematic, the example below) / CSS plate (styled FROM the brief —
82
82
  gradients, borders, chamfers per the game-ui corner rules; default-gray
83
83
  plates are a defect) / sprite chrome (from the HUD sheet or a dedicated
84
- generation — Tier 2b, when the brief is ornate). The per-genre lean lives
84
+ generation — Tier 2b, when the brief is ornate) / real glass
85
+ (`npx genex image "<frosted panel>" --glass` — menus love frosted panels,
86
+ and the solved RGBA carries TRUE translucency over the moving backdrop;
87
+ `$genex-ai-image` documents the lane). The per-genre lean lives
85
88
  in the style capsules (`$genex-threejs-game-ui`'s
86
89
  references/style-capsules.md) — a lean, not a rule.
87
90
 
@@ -136,7 +139,7 @@ cycle. Two stacked `<video>` elements with the same src crossfade at the
136
139
  cycle end; any seam disappears deterministically, no regeneration lottery.
137
140
 
138
141
  **Phone tiers get the poster, not the videos** (`$genex-threejs-adaptive-quality`):
139
- two preloading 720p decoders while the 3D scene boots is a spike at exactly the
142
+ two preloading HD decoders while the 3D scene boots is a spike at exactly the
140
143
  moment phones get killed for memory. On a phone tier, show the key-art poster
141
144
  image (a captured frame of the clip works) and skip `seamlessLoop` entirely —
142
145
  or defer ONE non-preloading video until after the first gameplay frame:
@@ -171,19 +174,40 @@ export function seamlessLoop(holder: HTMLElement, url: string, fade = 0.6): void
171
174
 
172
175
  Pause both videos when the menu phase hides (they're decode work), and
173
176
  resume the front one when it returns. Watch ONE full cycle in the browser
174
- before calling the menu done — that's the seam check.
177
+ before calling the menu done — that's the seam check, and once the video is
178
+ wired it is the menu's capture in the milestone smoke pass: one full loop
179
+ cycle watched AS RENDERED. A metadata probe (ffprobe) can't see a seam, a
180
+ panel covering the video, or a video that never plays — only watching can.
175
181
 
176
182
  **Work async — the menu must never block the game.** The still is
177
- `--edit`-anchored to the concept mockup, so it's style-dependent: generate it
178
- the moment the user approves the concept (not before), enqueue the video with
179
- `--no-wait`, ship the CSS menu
180
- (buttons + title over the frame IMAGE as a static backdrop), and swap the
181
- `<video>` in when `genex wait` prints the URL. The frame image doubles as the
183
+ `--edit`-anchored to the concept mockup, so it's style-dependent: enqueue it
184
+ `--no-wait` **the moment the concept mockup LANDS** it rides the same
185
+ immediate chain as the HUD Stage-2 sheet and the logotype; the user's
186
+ keep/change answer never gates it (a later "change" just re-edits it against
187
+ the new frame, image-priced). **Only the VIDEO the expensive item waits,
188
+ and its trigger is an event, never a clock: fire it at the FIRST of (a) the
189
+ user's yes to the concept, (b) the next `genex preview` push after the still
190
+ has landed (a shipped milestone with the user silent = the pick stands), or
191
+ (c) style art being the only work left. Never fire it while a user objection
192
+ is open** ("change the colors" blocks it until the loop resolves). Ship the
193
+ CSS menu (buttons + title over the frame IMAGE as a static backdrop) and
194
+ swap the `<video>` in when `genex wait` prints the URL. The frame image doubles as the
182
195
  **loading screen background** — it exists minutes before the video does (see
183
196
  `$genex-threejs-game-ui`'s loader spec). Both assets live in Genex storage
184
197
  (R2) — permanent, public, CORS-open; you load them straight from the printed
185
198
  URLs, nothing is downloaded or committed.
186
199
 
200
+ **When the generated art lands, the upgrade is a RE-COMPOSITION — not a
201
+ backdrop swap.** DELETE the placeholder panel/card the moment the still or
202
+ video goes in: the still was generated with negative space precisely so the
203
+ buttons and logo sit DIRECTLY on the key art. A placeholder card left
204
+ floating over the finished video is the single most common bad menu — a
205
+ near-opaque panel (plus its darkening layers) hides the art you just paid
206
+ for, and the menu reads as the plain CSS draft it started as. Allowed over
207
+ the art: a thin, low-opacity scrim strictly behind the button rail for
208
+ legibility, and at most ONE subtle full-screen grade layer. NEVER a
209
+ card/panel covering the art.
210
+
187
211
  **Two failed video attempts = ship the still. Hard stop.** Video is the one
188
212
  generation that fails server-side with real frequency (render timeouts), and
189
213
  every attempt costs minutes of waiting. One retry is fair — shorten the clip
@@ -350,7 +374,11 @@ not):
350
374
  `npx genex image "the word 'EMBERFALL' as an ornate engraved game logo, <style brief>" --transparent`
351
375
  — the wordmark alone on a transparent background, in the brief's display
352
376
  register, no extra text or scenery. Clean with `--bg-mode glyph` if letter
353
- counters get eaten, trim with `npx genex ui trim`. Short names (one or two
377
+ counters get eaten, trim with `npx genex ui trim`. Then VERIFY it is
378
+ actually transparent — view the trimmed PNG over a bright test background;
379
+ background removal sometimes leaves an opaque disc or plate behind the
380
+ mark, and that plate ships as a hole punched in your key art. If any
381
+ background remains, re-run the clean. Short names (one or two
354
382
  words) come out best. Wire it as the menu title AND the loader mark; the
355
383
  DOM keeps an accessible text fallback (`aria-label` or visually-hidden
356
384
  text).
@@ -370,14 +398,12 @@ not):
370
398
  re-anchored the look) re-opens this rule once — re-edit the still
371
399
  (`--edit` against the new concept mockup) and re-run the video from the
372
400
  new still. Agent-initiated polish never does.
373
- - **The menu (`--frame`) path renders 720pdon't force 1080p.** The
374
- frame-conditioned first-last-frame route was rejected by the provider at
375
- 1080p (repeated 422 failures that shipped a dead static menu), so the menu
376
- video path defaults to the proven-good, seamless-looping 720p no flag
377
- needed. The DOM crossfade + full-screen scale read fine at 720p; do NOT pass
378
- `--resolution 1080p` on a `--frame` menu clip just to sharpen it, or you risk
379
- re-triggering the 422 and losing the video entirely. (Plain text-to-video,
380
- without `--frame`, still defaults to 1080p.)
401
+ - **The menu video renders 1080p by default leave it alone.** Every video
402
+ path, the frame-conditioned (`--frame`) menu route included, defaults to
403
+ 1080p: the menu clip is full-screen key art, and 720p stretched across a
404
+ desktop reads soft. Don't pass a resolution flag at all; `--resolution 720p`
405
+ exists only as a deliberate cost opt-down for clips that are genuinely
406
+ incidental never the main menu.
381
407
  - **Pause/victory/defeat variants reuse the same video — as GRADES.** Same
382
408
  `<video>` element or URL, different emotion via CSS `filter` on the
383
409
  background: pause = a plain dark overlay (`rgba(0,0,0,0.55)`); defeat =
@@ -407,11 +433,10 @@ not):
407
433
  genuine state change; expect a loop seam.
408
434
  - `--duration <sec>` (video) — 4, 6, or 8 for frame-conditioned clips;
409
435
  default 8.
410
- - `--resolution <720p|1080p>` (video) — plain text-to-video defaults to 1080p;
411
- the frame-conditioned (`--frame`) menu path defaults to **720p** for
412
- reliability (1080p was rejected there). `720p` is also the cost fallback
413
- (~half the credits). Loop clips (`--loop`) ignore it (that model has no
414
- resolution parameter).
436
+ - `--resolution <720p|1080p>` (video) — every path defaults to **1080p**, the
437
+ `--frame` menu route included. `720p` is the deliberate cost opt-down
438
+ (~half the credits) for incidental clips — not for the menu. Loop clips
439
+ (`--loop`) ignore it (that model has no resolution parameter).
415
440
  - `--aspect 16:9 --quality high` (image) — the right settings for a menu frame.
416
441
  - `--no-wait` — enqueue and return immediately with the generation id; pick
417
442
  the result up later with `npx genex wait <id>` (safe to re-run — it attaches
@@ -14,6 +14,14 @@ Turn a text prompt into a real, game-ready **GLB** and drop it into the project.
14
14
  - **Use `$genex-threejs-procedural-geometry`** for parametric/abstract shapes,
15
15
  terrain, or anything you want to generate in code (infinite variations, no files).
16
16
 
17
+ **The output is a STATIC, unrigged mesh — no skeleton, no animation clips.**
18
+ A "wolf" or "guard" from this command can be posed and moved as one object,
19
+ but its limbs cannot animate. Anything that must walk, attack, or die on
20
+ screen routes to the creature lane instead: `npx genex creature` for
21
+ biped-shaped bodies (real rig + library clips), or this command plus the
22
+ procedural-motion recipes for everything else — `$genex-threejs-creatures`
23
+ owns that split. The player's own character is `$genex-ai-character`.
24
+
17
25
  ## Run
18
26
 
19
27
  ```bash
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: genex-ai-music
3
+ description: Generate a real instrumental background-music track (mp3) from a text prompt with `npx genex music`, then loop it quietly under the game in Three.js. Use for the one looping gameplay track every game with generated audio should have (reused on the menu at lower volume), plus optional boss or menu-specific tracks — always instrumental, always behind Music/SFX volume sliders in settings.
4
+ ---
5
+
6
+ # Genex AI · Music
7
+
8
+ Turn a prompt into a real **mp3** instrumental track and loop it under the game.
9
+ One track transforms how finished a game feels — a silent game with polished art
10
+ still reads as a tech demo.
11
+
12
+ ## When to use this vs. sfx
13
+
14
+ - **Use `npx genex music`** for the continuous bed: the gameplay loop, a boss
15
+ theme, a menu theme. Tracks are instrumental by design (the API enforces it —
16
+ vocals under gameplay read as karaoke).
17
+ - **Use `$genex-ai-sfx`** for event sounds — impacts, pickups, UI ticks. The
18
+ 0.5–22 s sfx lane cannot produce a music bed; don't try.
19
+
20
+ **The default plan is ONE track:** a ~90 s loopable gameplay track, reused on
21
+ the menu (same URL, lower volume). Propose extra tracks (boss/menu-specific) as
22
+ their own Assets-table rows only when the game's shape earns them.
23
+
24
+ ## Run
25
+
26
+ ```bash
27
+ npx genex music "<prompt>" --no-wait
28
+ npx genex music "dark orchestral hunt, low strings and taiko, steady menace, seamless loop, consistent energy, no intro, no outro" --duration 120 --no-wait
29
+ ```
30
+
31
+ `--duration <sec>` (10–300) sets the length; the default **90 s** is the sweet
32
+ spot for a loop. Music takes a minute-plus — enqueue with `--no-wait` alongside
33
+ your other generations and pick it up with `npx genex wait <id>`. Prints:
34
+
35
+ ```
36
+ https://assets.genex.technology/generations/<id>/audio-music
37
+ ```
38
+
39
+ The mp3 lives in Genex storage (R2) and loads straight from that URL — you don't
40
+ download it and nothing is committed to your repo. The URL is permanent (local
41
+ dev, published game, and remixes alike).
42
+
43
+ ## Prompt recipe for loopable game music
44
+
45
+ Mood + instrumentation + energy + loop wording:
46
+
47
+ - Name the game's emotional register and 2–3 instruments ("brooding synthwave,
48
+ analog pads and arpeggio", "cozy acoustic folk, fingerpicked guitar and soft
49
+ strings").
50
+ - Always end with: **"seamless loop, consistent energy, no intro, no outro"** —
51
+ there is no API loop flag; consistent energy at both ends is what makes
52
+ `setLoop(true)` inaudible. A track with a big intro pops every cycle.
53
+ - Don't ask for vocals — the lane forces instrumental regardless.
54
+
55
+ ## Wire it in Three.js
56
+
57
+ Music is **non-positional** (`THREE.Audio`, not `PositionalAudio`), looped,
58
+ and QUIET — the default volume is **0.30**: it sits under the sfx, never over
59
+ them. Browsers block autoplay, so start it on the first user gesture:
60
+
61
+ ```ts
62
+ import * as THREE from "three";
63
+
64
+ const listener = new THREE.AudioListener();
65
+ camera.add(listener); // ONE listener serves music and every sfx
66
+
67
+ // the URL `npx genex music` printed (R2 sends CORS headers, cross-origin works):
68
+ const MUSIC_URL = "https://assets.genex.technology/generations/<id>/audio-music";
69
+ const music = new THREE.Audio(listener);
70
+ new THREE.AudioLoader().loadAsync(MUSIC_URL).then((buffer) => {
71
+ music.setBuffer(buffer);
72
+ music.setLoop(true);
73
+ music.setVolume(0.30); // the default — under the sfx, never over them
74
+ // autoplay policy: start on the first gesture (the menu's PLAY click is ideal)
75
+ const start = (): void => {
76
+ if (!music.isPlaying) music.play();
77
+ };
78
+ window.addEventListener("click", start, { once: true });
79
+ window.addEventListener("keydown", start, { once: true });
80
+ });
81
+
82
+ // Suspend when the tab hides (decode work + politeness), resume on return:
83
+ document.addEventListener("visibilitychange", () => {
84
+ const ctx = listener.context;
85
+ if (document.hidden) void ctx.suspend();
86
+ else void ctx.resume();
87
+ });
88
+ ```
89
+
90
+ **Menu reuse:** the same `music` object at lower volume (`setVolume(0.18)`)
91
+ during the menu phase, restored to the setting's value on PLAY — zero extra
92
+ generations. If the loop point is audible (the track came back with an
93
+ intro/outro despite the prompt), crossfade the tail into the head with a second
94
+ `THREE.Audio` on the same buffer rather than regenerating.
95
+
96
+ ## Volume sliders are NOT optional
97
+
98
+ A game with generated audio and no volume control is a failure mode. The
99
+ settings screen gets **two sliders — Music and SFX** (music default 0.30, sfx
100
+ ~0.7), persisted (localStorage or the save slot) and applied live:
101
+ `music.setVolume(v)` for the music bed; keep every sfx's volume routed through
102
+ one shared multiplier. `$genex-threejs-game-ui` carries this as a hard settings
103
+ rule — wire the sliders in the same milestone as the track.
104
+
105
+ ## Publish checklist
106
+
107
+ - Load it from the **URL** the command printed — absolute and permanent, so it
108
+ resolves the same in local dev, the published game, and remixes. Nothing to
109
+ commit.
110
+ - The track must be audible in the shipped game AND adjustable in settings —
111
+ an unwired paid track is flagged at preview/publish (the wiring audit).
112
+
113
+ ## Options
114
+
115
+ - `--duration <sec>` — track length 10–300; default 90 (the loop sweet spot).
116
+ Longer costs more; a 90–120 s loop outlasts most sessions.
117
+ - `--no-wait` — enqueue and return immediately with the generation id; pick it
118
+ up later with `npx genex wait <id>` (safe to re-run — it attaches to the SAME
119
+ generation). The default for music: build while it renders.
120
+ - `--api-url <url>` — override the API base (local dev).
121
+
122
+ ## Troubleshooting
123
+
124
+ - **"Not authorized"** — run `npx genex init` first (in the project — it resolves this project's own CLI) (it writes your `GENEX_TOKEN`).
125
+ - **"Out of credits" (`insufficient_credits`)** — the account has no credits left
126
+ for this music generation. Tell the user the facts the CLI printed: their
127
+ balance, this generation's cost, and when their credits refill. Then continue
128
+ the build without a music bed (the game must work silent anyway) and mark the
129
+ spot with `// TODO(genex): regenerate when credits refill` so the real track
130
+ is one command away later. Do not stop the session over this.
131
+ - **"Email not verified" (`email_verification_required`)** — generation credits
132
+ unlock after the account's email is verified. Give the user the verify link
133
+ the CLI printed, wait for them to confirm, then re-run the command.
134
+ - **No sound** — the `AudioContext` is suspended until a user gesture; the
135
+ first `music.play()` must come from a click/keydown. Confirm the camera has
136
+ an `AudioListener`.
137
+ - **The loop "pops" every cycle** — the track has an intro/outro (the prompt
138
+ missed the loop wording). One regeneration with "seamless loop, consistent
139
+ energy, no intro, no outro" is fair; after that, crossfade tail-into-head
140
+ with a second `THREE.Audio` on the same buffer instead of re-rolling.
141
+ - **Music drowns the game** — 0.30 is the ceiling for a bed, not the floor;
142
+ drop it further under dialogue-heavy or ambience-led scenes.
@@ -10,13 +10,26 @@ also lights it (image-based lighting).
10
10
 
11
11
  ## When to use this vs. a procedural sky
12
12
 
13
- - **Use `npx genex skybox`** for a specific, recognizable sky/backdrop you can
14
- describe — "golden hour over misty mountains", "stormy alien sky", "city at
15
- night". You get a real image.
13
+ - **Use `npx genex skybox`** for a specific, describable ENVIRONMENT "golden
14
+ hour over misty mountains", "rolling thunderstorm, towering cumulonimbus",
15
+ "alien purple nebula", "hazy dusk sky over a distant sea horizon". You get a
16
+ real image.
16
17
  - **Use `$genex-threejs-atmosphere-aerial-perspective`** (or
17
18
  `$genex-threejs-volumetric-clouds`) for a fully procedural, animated,
18
19
  time-of-day sky generated in shaders.
19
20
 
21
+ **A skybox is environment only — never content.** Buildings, trees, ruins,
22
+ towers, or any object painted into the sky render at infinite distance: they
23
+ never get closer as the player moves, they sit at the wrong parallax against
24
+ the real 3D world, and they read as broken the moment the camera strafes.
25
+ Structures belong in the scene as geometry (`npx genex model`); the sky
26
+ carries atmosphere — light, weather, clouds, haze, stars. The CLI enforces
27
+ this: every skybox prompt gets an environment-only suffix appended (you'll
28
+ see `↳ environment-only guard applied` and the full final prompt is stored
29
+ with the generation). If you genuinely need content baked into the sky —
30
+ e.g. a space station panorama for a scene with no world geometry — pass
31
+ `--raw` to send your prompt exactly as written.
32
+
20
33
  ## Run
21
34
 
22
35
  ```bash
@@ -81,8 +94,11 @@ scene.background = texture; // keep the raw texture for the visible sky
81
94
 
82
95
  ## Options
83
96
 
84
- - `--no-wait` — enqueue and return immediately (the file won't be downloaded;
85
- re-run without `--no-wait` to fetch it).
97
+ - `--raw` — send the prompt exactly as written, skipping the appended
98
+ environment-only guard (for the rare sky that must carry content).
99
+ - `--no-wait` — enqueue and return immediately with the generation id; pick
100
+ the result up later with `npx genex wait <id>` (safe to re-run — it attaches
101
+ to the SAME generation).
86
102
  - `--api-url <url>` — override the API base (local dev).
87
103
 
88
104
  ## Troubleshooting
@@ -37,11 +37,13 @@ The clip lives in Genex storage (R2) and loads straight from that URL — you do
37
37
  download it and nothing is committed to your repo. The URL is permanent (local dev,
38
38
  published game, and remixes alike).
39
39
 
40
- > **Cost & length:** the default is a **5-second, 720p** clip, and that IS the right
41
- > default for a looping screen or backdrop only pass `--duration` when the content
42
- > genuinely needs to be longer (a cutscene). Longer, higher-res clips cost more and
43
- > take longer. mp4 has **no alpha channel**, so a video is always a full rectangle
44
- > (there are no transparent video decals).
40
+ > **Cost & length:** the default is a **5-second, 1080p** clip the right default
41
+ > for anything the player looks at directly. Only pass `--duration` when the content
42
+ > genuinely needs to be longer (a cutscene), and `--resolution 720p` only when the
43
+ > clip is genuinely incidental (a small in-world screen seen from a distance): it
44
+ > halves the cost, but 720p stretched across the whole screen reads soft. mp4 has
45
+ > **no alpha channel**, so a video is always a full rectangle (there are no
46
+ > transparent video decals).
45
47
 
46
48
  ## Play it in Three.js
47
49
 
@@ -80,8 +82,9 @@ window.addEventListener("keydown", () => {
80
82
  One `VideoTexture` can feed **many** surfaces — a bank of monitors, N sprays. Cost is
81
83
  per distinct `<video>` element (media decode + one GPU upload per frame), **not** per
82
84
  surface, so sharing one element for every screen is nearly free (all play in sync).
83
- Keep clips **≤720p**. Pause the element (`video.pause()`) when no video surface is
84
- visible.
85
+ Pause the element (`video.pause()`) when no video surface is visible; on phones,
86
+ prefer the clip's source still as a poster and start the video only where it plays
87
+ smoothly.
85
88
 
86
89
  ## Video decals
87
90
 
@@ -132,6 +135,9 @@ See `$genex-threejs-multiplayer` for the `shared` channel rules and the room API
132
135
  - `--loop` — a seamless loop (for screens, ambient backdrops, video decals).
133
136
  - `--duration <sec>` — clip length 1–15; default 5. Only raise it when the content
134
137
  genuinely needs more — longer clips cost more and take longer.
138
+ - `--resolution 720p|1080p` — output resolution (default **1080p**). `--resolution
139
+ 720p` halves the cost — use it only when quality genuinely doesn't matter (a small
140
+ far-away in-world screen). `--loop` clips ignore it (model default).
135
141
  - `--frame <url>` — one generated image as BOTH first and last frame — the
136
142
  seamless-loop mode (motion must return to its start).
137
143
  - `--first-frame <url>` / `--last-frame <url>` — two-frame motion between two