@genex-ai/cli-demo 0.7.0 → 0.10.0
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.
- package/README.md +13 -12
- package/dist/index.js +410 -154
- package/package.json +10 -11
- package/templates/README.md +8 -7
- package/templates/skills/genex-ai-model/SKILL.md +5 -5
- package/templates/skills/genex-ai-sfx/SKILL.md +1 -1
- package/templates/skills/genex-ai-skybox/SKILL.md +2 -2
- package/templates/skills/genex-ai-texture/SKILL.md +1 -1
- package/templates/skills/genex-getting-started/SKILL.md +10 -6
- package/templates/skills/genex-threejs-embed-auth/SKILL.md +174 -0
- package/templates/skills/genex-threejs-multiplayer/SKILL.md +193 -100
- package/templates/skills/genex-threejs-multiplayer/references/genre-recipes.md +115 -0
- package/templates/skills/genex-threejs-multiplayer/references/realtime-patterns.md +138 -123
- package/templates/skills/genex-threejs-precipitation-surfaces/SKILL.md +59 -0
- package/templates/skills/genex-threejs-precipitation-surfaces/references/precipitation-surfaces.md +181 -0
- package/templates/skills/genex-threejs-procedural-architecture/SKILL.md +2 -1
- package/templates/skills/genex-threejs-procedural-architecture/references/architecture-systems.md +1 -1
- package/templates/skills/genex-threejs-procedural-fields/SKILL.md +0 -5
- package/templates/skills/genex-threejs-procedural-geometry/SKILL.md +0 -5
- package/templates/skills/genex-threejs-procedural-materials/SKILL.md +2 -17
- package/templates/skills/genex-threejs-procedural-vegetation/SKILL.md +11 -1
- package/templates/skills/genex-threejs-procedural-vfx/SKILL.md +3 -1
- package/templates/skills/genex-threejs-shadow-systems/SKILL.md +0 -5
- package/templates/skills/genex-threejs-skill-router/SKILL.md +10 -5
- package/templates/skills/genex-threejs-skill-router/references/routing-map.md +9 -6
- package/templates/skills/genex-threejs-spectral-ocean/SKILL.md +11 -1
- package/templates/skills/genex-threejs-temporal-surfaces/SKILL.md +3 -1
- package/templates/skills/genex-threejs-water-optics/SKILL.md +14 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Set up your ~/.claude workspace, authorize, create a game project, generate AI assets, and publish (genex CLI).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,14 +15,6 @@
|
|
|
15
15
|
"engines": {
|
|
16
16
|
"node": ">=20"
|
|
17
17
|
},
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsup",
|
|
20
|
-
"prepack": "pnpm build",
|
|
21
|
-
"start": "node src/index.ts",
|
|
22
|
-
"dev": "node --watch src/index.ts",
|
|
23
|
-
"typecheck": "tsc --noEmit",
|
|
24
|
-
"test": "node --test test/*.test.ts"
|
|
25
|
-
},
|
|
26
18
|
"keywords": [
|
|
27
19
|
"cli",
|
|
28
20
|
"claude",
|
|
@@ -46,5 +38,12 @@
|
|
|
46
38
|
"bugs": {
|
|
47
39
|
"url": "https://github.com/me-ai-org/genex-demo/issues"
|
|
48
40
|
},
|
|
49
|
-
"homepage": "https://github.com/me-ai-org/genex-demo/tree/main/apps/cli#readme"
|
|
50
|
-
|
|
41
|
+
"homepage": "https://github.com/me-ai-org/genex-demo/tree/main/apps/cli#readme",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"start": "node src/index.ts",
|
|
45
|
+
"dev": "node --watch src/index.ts",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"test": "node --test test/*.test.ts"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/templates/README.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# Genex workspace
|
|
2
2
|
|
|
3
|
-
These files were installed into your
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
These files were installed by `genex init` into your coding agent's workspace —
|
|
4
|
+
Claude Code (`~/.claude`), Codex (`~/.codex/skills`), and Cursor
|
|
5
|
+
(`~/.cursor/skills`), whichever it detected. They give your agent superpowers
|
|
6
|
+
for making 3D games in the browser.
|
|
6
7
|
|
|
7
8
|
Genex is built around agent superpowers for browser games: Three.js skills,
|
|
8
|
-
one-click publishing, multiplayer-ready architecture, and team workflows.
|
|
9
|
-
installed files are yours to edit, extend, and keep with each project.
|
|
9
|
+
one-click publishing, multiplayer-ready architecture, and team workflows.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
Files whose names start with `genex-` are managed by Genex: re-running
|
|
12
|
+
`genex init` refreshes them to the latest version. Anything you add yourself is
|
|
13
|
+
never touched.
|
|
13
14
|
|
|
14
15
|
- `skills/` - reusable Genex skills for 3D game creation.
|
|
15
16
|
- `agents/` - example subagent definitions.
|
|
@@ -54,8 +54,8 @@ i.e. "looking forward"). A hero whose nose points sideways reads as broken at a
|
|
|
54
54
|
|
|
55
55
|
## Load it into the scene
|
|
56
56
|
|
|
57
|
-
Use Three.js `GLTFLoader`
|
|
58
|
-
|
|
57
|
+
Use Three.js `GLTFLoader` (the game serves at the domain root
|
|
58
|
+
`https://<slug>.genex.technology/`, so relative or absolute paths both work):
|
|
59
59
|
|
|
60
60
|
```ts
|
|
61
61
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
@@ -73,12 +73,12 @@ To place many copies, `model.clone()` per instance. For animated GLBs, drive
|
|
|
73
73
|
|
|
74
74
|
## Publish checklist (so players see the model)
|
|
75
75
|
|
|
76
|
-
- Reference assets with **relative** paths (`./assets/...`)
|
|
77
|
-
(`/assets/...`)
|
|
76
|
+
- Reference assets with **relative** paths (`./assets/...`); absolute
|
|
77
|
+
(`/assets/...`) also resolves since the game serves at the domain root.
|
|
78
78
|
- Set `base: "./"` in `vite.config.ts` before `npm run build` (see the scaffold
|
|
79
79
|
prompt's publish step).
|
|
80
80
|
- Keep generated assets under `public/assets/` — Vite only ships files under `public/`
|
|
81
|
-
(or files you `import`); `npx genex publish`
|
|
81
|
+
(or files you `import`); `npx genex publish` ships that folder with the game.
|
|
82
82
|
|
|
83
83
|
## Options
|
|
84
84
|
|
|
@@ -56,7 +56,7 @@ Reuse one loaded `buffer` across many plays; create a fresh `Audio`/`PositionalA
|
|
|
56
56
|
## Publish checklist
|
|
57
57
|
|
|
58
58
|
- Relative path `./assets/sfx/...`; `base: "./"` in `vite.config.ts`; files live under
|
|
59
|
-
`public/assets/` so Vite ships them; `npx genex publish`
|
|
59
|
+
`public/assets/` so Vite ships them; `npx genex publish` ships them to R2.
|
|
60
60
|
|
|
61
61
|
## Troubleshooting
|
|
62
62
|
|
|
@@ -61,10 +61,10 @@ texture.dispose; // (dispose the PMREM source later if you stop using it)
|
|
|
61
61
|
|
|
62
62
|
## Publish checklist
|
|
63
63
|
|
|
64
|
-
- Use the **relative** path `./assets/skybox/...` (
|
|
64
|
+
- Use the **relative** path `./assets/skybox/...` (absolute `/assets/...` also works — the game serves at the domain root).
|
|
65
65
|
- `base: "./"` in `vite.config.ts` before `npm run build`.
|
|
66
66
|
- Generated files live under `public/assets/` so Vite ships them; `npx genex publish`
|
|
67
|
-
|
|
67
|
+
ships that folder with the game.
|
|
68
68
|
|
|
69
69
|
## Troubleshooting
|
|
70
70
|
|
|
@@ -68,7 +68,7 @@ scene.add(ground);
|
|
|
68
68
|
## Publish checklist
|
|
69
69
|
|
|
70
70
|
- Relative path `./assets/textures/...`; `base: "./"` in `vite.config.ts`; files live under
|
|
71
|
-
`public/assets/` so Vite ships them; `npx genex publish`
|
|
71
|
+
`public/assets/` so Vite ships them; `npx genex publish` ships them to R2.
|
|
72
72
|
|
|
73
73
|
## Troubleshooting
|
|
74
74
|
|
|
@@ -23,12 +23,14 @@ are never touched).
|
|
|
23
23
|
|
|
24
24
|
Start with `$genex-threejs-skill-router` for broad game or graphics requests.
|
|
25
25
|
It routes the agent to focused skills for cameras, procedural geometry,
|
|
26
|
-
materials, atmosphere, water, VFX, post-processing, and visual
|
|
26
|
+
materials, atmosphere, water, weather, VFX, post-processing, and visual
|
|
27
|
+
validation.
|
|
27
28
|
|
|
28
29
|
## Generating real assets
|
|
29
30
|
|
|
30
31
|
Beyond procedural code, Genex can generate **real, AI-made assets** from a prompt
|
|
31
|
-
and drop them into
|
|
32
|
+
and drop them into `public/assets/` (shipped with your published game; load them
|
|
33
|
+
as `./assets/...` — the `public/` prefix is stripped when served):
|
|
32
34
|
|
|
33
35
|
```bash
|
|
34
36
|
npx genex model "weathered wooden barrel" # a 3D mesh (GLB)
|
|
@@ -43,18 +45,20 @@ npx genex texture "mossy cobblestone" --terrain # a tiling surface texture
|
|
|
43
45
|
Each has a focused skill with the exact loader code — `$genex-ai-model`,
|
|
44
46
|
`$genex-ai-skybox`, `$genex-ai-sfx`, `$genex-ai-texture`.
|
|
45
47
|
|
|
46
|
-
Your
|
|
48
|
+
Your own files were left untouched. `genex init` only adds missing files and
|
|
49
|
+
refreshes the genex-owned ones.
|
|
47
50
|
|
|
48
51
|
## Re-running setup
|
|
49
52
|
|
|
50
|
-
Safe to run any time
|
|
53
|
+
Safe to run any time — genex-owned skills are refreshed to the latest version,
|
|
54
|
+
and your own files are never touched:
|
|
51
55
|
|
|
52
56
|
```bash
|
|
53
57
|
npx @genex-ai/cli-demo@latest init
|
|
54
58
|
```
|
|
55
59
|
|
|
56
|
-
Use `--force` only if you intentionally want
|
|
57
|
-
|
|
60
|
+
Use `--force` only if you intentionally want your own existing files overwritten
|
|
61
|
+
by the bundled templates too.
|
|
58
62
|
|
|
59
63
|
## Authorization
|
|
60
64
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: genex-threejs-embed-auth
|
|
3
|
+
description: Wire up signed-in identity for a Genex game via @genex-ai/embed-sdk. Load this UNCONDITIONALLY for every game, multiplayer or not, BEFORE writing any boot code — identity is required for play, saving progress, and multiplayer; there is no anonymous mode.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Genex Three.js Embed Auth
|
|
7
|
+
|
|
8
|
+
`@genex-ai/embed-sdk` is how a Genex game learns **who is playing it**. Every
|
|
9
|
+
game needs it — there is **no anonymous play**: without a signed-in identity
|
|
10
|
+
the game is not playable, cannot save progress, and cannot join multiplayer.
|
|
11
|
+
The SDK handles both contexts with one `initEmbed(...)` call:
|
|
12
|
+
|
|
13
|
+
- **Embedded in the Genex dashboard (an iframe):** a silent handshake with the
|
|
14
|
+
dashboard signs the player in within a couple of seconds — no login screen.
|
|
15
|
+
- **Standalone (someone opens the game's link directly):** the SDK redirects
|
|
16
|
+
through Genex sign-in (first-time visitors sign up there) and returns to the
|
|
17
|
+
game automatically. This is a real page navigation, by design — game code
|
|
18
|
+
does not need to handle any of it.
|
|
19
|
+
|
|
20
|
+
While identity is resolving (or missing) the SDK shows its own full-screen
|
|
21
|
+
overlay over the game, so never build a separate "connecting" screen for auth.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm i @genex-ai/embed-sdk @sentry/browser
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
(`@sentry/browser` powers the crash reporting + session replay wiring below —
|
|
30
|
+
it's an optional peer of the SDK, and every Genex game installs it. Already
|
|
31
|
+
installed if you followed Step 3 of the scaffold; repeated here so this skill
|
|
32
|
+
is self-contained.)
|
|
33
|
+
|
|
34
|
+
## Bootstrap (required, every game)
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// main.ts — the FIRST things in the boot sequence, before any other game code
|
|
38
|
+
import { initGameSentry } from "@genex-ai/embed-sdk/sentry";
|
|
39
|
+
import { initEmbed } from "@genex-ai/embed-sdk";
|
|
40
|
+
import { GENEX } from "./genex.config";
|
|
41
|
+
|
|
42
|
+
// Crash reporting + session replay FIRST — so even a failure inside the auth
|
|
43
|
+
// boot below gets reported. One required field; never pass tokens to it.
|
|
44
|
+
initGameSentry({ slug: GENEX.slug });
|
|
45
|
+
|
|
46
|
+
initEmbed({
|
|
47
|
+
slug: GENEX.slug,
|
|
48
|
+
apiUrl: GENEX.apiUrl,
|
|
49
|
+
dashboardOrigins: GENEX.dashboardOrigins,
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Scene setup and asset loading may continue immediately after this call — auth
|
|
54
|
+
never blocks rendering. Gate the **identity-dependent** parts (multiplayer
|
|
55
|
+
connect, saving/loading progress, showing the player's name) on `waitForAuth()`:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { waitForAuth, getColyseusAuth, getEmbedToken } from "@genex-ai/embed-sdk";
|
|
59
|
+
|
|
60
|
+
const { user } = await waitForAuth(); // resolves when signed in; rejects if blocked
|
|
61
|
+
// user.id / user.name are the real Genex identity
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## API surface (exact — do not invent methods)
|
|
65
|
+
|
|
66
|
+
- `initEmbed({ slug, apiUrl, dashboardOrigins })` — call once, first. All three
|
|
67
|
+
fields required (from `genex.config.ts`).
|
|
68
|
+
- `waitForAuth()` → `Promise<{ user }>` — THE gate for `connect()` and `/state`
|
|
69
|
+
calls. Rejects if the session ends up blocked — catch it and let the SDK's
|
|
70
|
+
overlay handle the UX (don't build your own sign-in UI).
|
|
71
|
+
- `isEmbedded()` → `boolean` — structural "is in an iframe" check; NOT the same
|
|
72
|
+
question as "is signed in".
|
|
73
|
+
- `getAuthState()` → `"pending" | "authenticated" | "blocked"` — synchronous.
|
|
74
|
+
- `getUser()` → `{ id, name, image? } | null` — non-null only when authenticated.
|
|
75
|
+
- `getEmbedToken()` → `string | undefined` — for `Authorization: Bearer` on
|
|
76
|
+
`GET`/`PUT ${GENEX.apiUrl}/api/projects/${GENEX.slug}/state` (both REQUIRE it).
|
|
77
|
+
- `getColyseusAuth()` → `{ embedToken } | undefined` — pass as `connect()`'s
|
|
78
|
+
`auth` option (REQUIRED — the relay rejects tokenless joins). Read it fresh
|
|
79
|
+
at every `connect()` call; tokens rotate automatically (~every 10 minutes).
|
|
80
|
+
- `on(event, cb)` → unsubscribe fn. Events: `"authenticated"`, `"blocked"`,
|
|
81
|
+
`"error"`.
|
|
82
|
+
|
|
83
|
+
From `@genex-ai/embed-sdk/sentry` (crash reporting; exactly these two):
|
|
84
|
+
|
|
85
|
+
- `initGameSentry({ slug, dsn?, environment? })` — call once, BEFORE
|
|
86
|
+
`initEmbed()`. Only `slug` is required; the shared Genex Sentry project DSN
|
|
87
|
+
is built in. Errors, tracing, and session replay all start here; the signed-in
|
|
88
|
+
user is attached automatically after auth (no code needed).
|
|
89
|
+
- `sentryCanvasSnapshot(canvas)` — session replay records the DOM, not the 3D
|
|
90
|
+
canvas; call this once per frame at the END of the render loop so replays
|
|
91
|
+
show actual gameplay. Works for BOTH WebGL and WebGPU renderers; internally
|
|
92
|
+
throttled, so calling at 60fps is fine:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
function animate() {
|
|
96
|
+
requestAnimationFrame(animate);
|
|
97
|
+
// ...game update...
|
|
98
|
+
renderer.render(scene, camera);
|
|
99
|
+
sentryCanvasSnapshot(renderer.domElement); // AFTER render, same frame
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Crash reporting rules
|
|
104
|
+
|
|
105
|
+
- `initGameSentry` has token scrubbing built in (the sign-in return-trip pass
|
|
106
|
+
in URLs is redacted automatically). Never wrap, reimplement, or bypass it —
|
|
107
|
+
and never add Sentry options that capture network request/response bodies.
|
|
108
|
+
- Don't call `Sentry.init` yourself or add a second error reporter —
|
|
109
|
+
`initGameSentry` is the one entry point.
|
|
110
|
+
- Manual capture is fine where a try/catch swallows a real bug:
|
|
111
|
+
`import * as Sentry from "@sentry/browser"; Sentry.captureException(err)`.
|
|
112
|
+
|
|
113
|
+
## NEVER log the tokens
|
|
114
|
+
|
|
115
|
+
**NEVER log the return value of `getEmbedToken()` or `getColyseusAuth()` — not
|
|
116
|
+
to `console.log`, not to a crash-reporter or analytics breadcrumb.** The token
|
|
117
|
+
is bounded (15 minutes, one game, one scope), but third-party logging-service
|
|
118
|
+
retention can outlive that. Nothing in normal game code ever needs to print it.
|
|
119
|
+
|
|
120
|
+
## Config wiring (already done — do NOT hand-write URLs)
|
|
121
|
+
|
|
122
|
+
**`genex init` already wrote the config files** — do not create or edit them,
|
|
123
|
+
and NEVER hardcode an environment URL anywhere in game code:
|
|
124
|
+
|
|
125
|
+
- `src/genex.config.ts` — a static env-reader (production URL defaults,
|
|
126
|
+
overridable via `VITE_GENEX_*` env vars). Import `GENEX` from it as shown
|
|
127
|
+
above; treat the file as read-only.
|
|
128
|
+
- `.env` — `VITE_GENEX_SLUG` (the game's identity; committed).
|
|
129
|
+
- `.env.development.local` — present only when init ran against a local/dev
|
|
130
|
+
stack: URL overrides that apply in `npm run dev` ONLY. A production build
|
|
131
|
+
(`vite build`) always uses the production defaults, so localhost values can
|
|
132
|
+
never ship. Gitignored via `*.local` — never commit it.
|
|
133
|
+
|
|
134
|
+
If `src/genex.config.ts` is somehow missing (e.g. it was deleted), re-run
|
|
135
|
+
`genex init` in the project folder rather than writing one by hand.
|
|
136
|
+
|
|
137
|
+
## Standalone behavior (what to expect, not something to code)
|
|
138
|
+
|
|
139
|
+
Opening the game's link directly (not from the dashboard) bounces through the
|
|
140
|
+
Genex sign-in page and back before the game becomes playable — including during
|
|
141
|
+
your own local `npm run dev` checks (sign in once; the bounce is instant after
|
|
142
|
+
that). The return trip carries a one-time pass in the URL that the SDK consumes
|
|
143
|
+
and removes immediately. Don't code around any of this: no `?`/`#` URL params
|
|
144
|
+
of yours will be affected, and `isEmbedded()` / the return-trip handling are
|
|
145
|
+
internal SDK concerns.
|
|
146
|
+
|
|
147
|
+
## Checklist
|
|
148
|
+
|
|
149
|
+
- [ ] `initGameSentry({ slug: GENEX.slug })` is the very first call in `main.ts`.
|
|
150
|
+
- [ ] `initEmbed(...)` follows it, with all three config fields.
|
|
151
|
+
- [ ] `sentryCanvasSnapshot(renderer.domElement)` runs after `renderer.render()`
|
|
152
|
+
in the main loop (WebGL and WebGPU alike).
|
|
153
|
+
- [ ] `genex.config.ts` includes `dashboardOrigins` (from `.genex/project.json`).
|
|
154
|
+
- [ ] Everything identity-dependent awaits `waitForAuth()` (multiplayer `connect`,
|
|
155
|
+
`/state` load/save, player-name UI).
|
|
156
|
+
- [ ] `/state` fetches send `Authorization: Bearer ${getEmbedToken()}`.
|
|
157
|
+
- [ ] No token value is ever logged or sent to analytics.
|
|
158
|
+
- [ ] No custom sign-in/anonymous-fallback UI — the SDK overlay + dashboard own that.
|
|
159
|
+
|
|
160
|
+
## Troubleshooting
|
|
161
|
+
|
|
162
|
+
- **Game loads then immediately navigates away (standalone/local dev)** — that's
|
|
163
|
+
the sign-in bounce working as designed. Sign in once in the browser; it
|
|
164
|
+
returns to the game automatically.
|
|
165
|
+
- **`waitForAuth()` rejects / state is `"blocked"`** — the visitor declined or
|
|
166
|
+
failed sign-in, or the dashboard session ended. The SDK overlay (or the
|
|
167
|
+
dashboard, when embedded) shows the sign-in prompt; the game just stays
|
|
168
|
+
paused behind it. Don't retry in a loop.
|
|
169
|
+
- **Multiplayer join rejected with 401** — `connect()` ran before
|
|
170
|
+
`waitForAuth()` resolved, without `auth: getColyseusAuth()!`, or with a stale
|
|
171
|
+
cached token on reconnect (read it fresh each call).
|
|
172
|
+
- **`/state` returns 401/403** — missing `Authorization` header (401) or the
|
|
173
|
+
token belongs to a different game (403): `GENEX.slug` doesn't match this
|
|
174
|
+
project.
|