@genex-ai/cli-demo 0.33.0 → 0.34.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 CHANGED
@@ -8,6 +8,7 @@ genex init <name> # authorize + create the draft project
8
8
  genex link <slug> # re-link this folder to an existing game of yours (recovery)
9
9
  genex preview # build + push to the hosted draft URL (unlisted)
10
10
  genex publish # build + push, then list the game in the gallery
11
+ genex make-remixable # make this game remixable — migrate a private source to a public repo
11
12
  genex model "<prompt>" # generate a 3D model → prints an asset URL
12
13
  genex skybox "<prompt>" # generate a 360° sky → prints an asset URL
13
14
  genex sfx "<prompt>" # generate a sound fx → prints an asset URL
package/dist/index.js CHANGED
@@ -659,7 +659,12 @@ async function createDraftProject(opts) {
659
659
  "Content-Type": "application/json",
660
660
  Authorization: `Bearer ${token}`
661
661
  },
662
- body: JSON.stringify(opts.repoUrl ? { name, repoUrl: opts.repoUrl } : { name })
662
+ body: JSON.stringify({
663
+ name,
664
+ ...opts.repoUrl ? { repoUrl: opts.repoUrl } : {},
665
+ ...opts.private ? { private: true } : {},
666
+ ...opts.remixedFromSlug ? { remixedFromSlug: opts.remixedFromSlug } : {}
667
+ })
663
668
  });
664
669
  } catch (err) {
665
670
  log.warn(`Couldn't reach the API at ${apiUrl} to create the project.`);
@@ -990,6 +995,8 @@ async function runInit(opts) {
990
995
  token,
991
996
  name: projectName,
992
997
  repoUrl: opts.repo?.trim() || void 0,
998
+ private: opts.private,
999
+ remixedFromSlug: opts.remixedFrom?.trim() || void 0,
993
1000
  colyseusUrl,
994
1001
  dashboardUrl: authBaseUrl,
995
1002
  log
@@ -1328,10 +1335,12 @@ async function callPublish(ctx, commit, opts, log) {
1328
1335
  return true;
1329
1336
  }
1330
1337
  async function pushSource(cwd, ctx, log) {
1331
- const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
1332
1338
  const target = await fetchPushUrl(ctx, log);
1333
1339
  if (!target) return false;
1334
- const { pushUrl, managed } = target;
1340
+ return pushWorktree(cwd, target.pushUrl, target.managed, log);
1341
+ }
1342
+ async function pushWorktree(cwd, pushUrl, managed, log) {
1343
+ const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
1335
1344
  const failed = () => {
1336
1345
  log.error("Couldn't save your game's source \u2014 please try again.");
1337
1346
  return false;
@@ -1440,6 +1449,75 @@ async function waitUntilLive(playUrl, fingerprint, timeoutMs, log) {
1440
1449
  log.dim(" (If the previous build shows, hard-refresh in a few seconds.)");
1441
1450
  }
1442
1451
 
1452
+ // src/commands/make-remixable.ts
1453
+ async function runMakeRemixable(opts) {
1454
+ const log = createLogger({ quiet: opts.quiet });
1455
+ log.plain(c.bold("genex make-remixable"));
1456
+ log.plain("");
1457
+ const meta = await readProject();
1458
+ if (!meta) {
1459
+ log.error("No genex project here. Run `genex init` in this directory first.");
1460
+ process.exitCode = 1;
1461
+ return;
1462
+ }
1463
+ const token = await readUserToken(opts.envPath);
1464
+ if (!token) {
1465
+ log.error("Not authorized. Run `genex init` first to sign in.");
1466
+ process.exitCode = 1;
1467
+ return;
1468
+ }
1469
+ const apiUrl = getApiUrl(opts.apiUrl ?? meta.apiUrl);
1470
+ log.step("Preparing a public repo for your game\u2026");
1471
+ let res;
1472
+ try {
1473
+ res = await apiFetch(`${apiUrl}/api/projects/${meta.id}/make-remixable`, {
1474
+ method: "POST",
1475
+ headers: { Authorization: `Bearer ${token}` }
1476
+ });
1477
+ } catch (err) {
1478
+ log.error(`Couldn't reach the API at ${apiUrl}: ${String(err)}`);
1479
+ process.exitCode = 1;
1480
+ return;
1481
+ }
1482
+ if (res.status === 401) {
1483
+ log.error("Not authorized \u2014 your token may have expired. Re-run `genex init`.");
1484
+ process.exitCode = 1;
1485
+ return;
1486
+ }
1487
+ if (res.status === 404) {
1488
+ log.error("That game wasn't found on your account. Re-run `genex init` or `genex link <slug>`.");
1489
+ process.exitCode = 1;
1490
+ return;
1491
+ }
1492
+ if (!res.ok) {
1493
+ log.error(`Couldn't make the game public (HTTP ${res.status}).`);
1494
+ process.exitCode = 1;
1495
+ return;
1496
+ }
1497
+ const data = await res.json().catch(() => null);
1498
+ if (!data?.pushUrl) {
1499
+ log.error("The API didn't return a push URL.");
1500
+ process.exitCode = 1;
1501
+ return;
1502
+ }
1503
+ log.step("Copying your game's source to the public repo\u2026");
1504
+ if (!await pushWorktree(process.cwd(), data.pushUrl, true, log)) {
1505
+ process.exitCode = 1;
1506
+ return;
1507
+ }
1508
+ const newCloneUrl = data.project?.cloneUrl;
1509
+ if (newCloneUrl && newCloneUrl !== meta.cloneUrl) {
1510
+ await writeProject({ ...meta, cloneUrl: newCloneUrl });
1511
+ }
1512
+ log.plain("");
1513
+ log.success("Your game is public \u2014 anyone can remix it now. \u{1F310}");
1514
+ const dashboard = meta.dashboardOrigins?.[0];
1515
+ if (dashboard) {
1516
+ const page = meta.status === "published" ? "world" : "draft";
1517
+ log.plain(` your game's page: ${c.cyan(`${dashboard}/${page}/${meta.slug}`)}`);
1518
+ }
1519
+ }
1520
+
1443
1521
  // src/lib/detect-features.ts
1444
1522
  import fs10 from "fs/promises";
1445
1523
  import path11 from "path";
@@ -2128,6 +2206,8 @@ ${c.bold("Usage")}
2128
2206
  update the same live game. Never creates a project.
2129
2207
  genex preview [options] Build + push to the hosted draft URL (unlisted).
2130
2208
  genex publish [options] Build + push, then list the game in the gallery.
2209
+ genex make-remixable [options] Make THIS game remixable by everyone \u2014 migrates a
2210
+ private source onto a public managed genex repo.
2131
2211
  genex model "<prompt>" [options] Generate a 3D model (GLB) into public/assets/models.
2132
2212
  genex skybox "<prompt>" [options] Generate a skybox (equirect) into public/assets/skybox.
2133
2213
  genex sfx "<prompt>" [options] Generate a sound effect (mp3) into public/assets/sfx.
@@ -2150,6 +2230,8 @@ ${c.bold("Options for `init`")}
2150
2230
  --name <name> Same as the positional name.
2151
2231
  --repo <url> Host the source in your own git repo (https/ssh) instead of a managed one;
2152
2232
  preview/publish push there with your git credentials.
2233
+ --private Create the game private \u2014 only you can remix it (managed repos only).
2234
+ --remixed-from <slug> Record the game this one was remixed from (lineage).
2153
2235
  --agents <list> Agents to install skills for (claude,codex,cursor; default: auto-detect).
2154
2236
  --dir <path> Single destination workspace (overrides --agents).
2155
2237
  --env <path> Token env file (default: ~/.genex/env).
@@ -2207,6 +2289,7 @@ ${c.bold("Examples")}
2207
2289
  genex preview
2208
2290
  genex publish
2209
2291
  genex publish --categories games,vfx
2292
+ genex make-remixable
2210
2293
  genex publish --no-push --title "My Game"
2211
2294
  genex model "weathered wooden barrel with iron bands"
2212
2295
  genex skybox "golden hour over a misty mountain range"
@@ -2232,6 +2315,7 @@ function parseArgs(argv) {
2232
2315
  "--agents",
2233
2316
  "--name",
2234
2317
  "--repo",
2318
+ "--remixed-from",
2235
2319
  "--title",
2236
2320
  "--description",
2237
2321
  "--categories",
@@ -2275,6 +2359,9 @@ function parseArgs(argv) {
2275
2359
  case "--regenerate-cover":
2276
2360
  parsed.options.regenerateCover = true;
2277
2361
  break;
2362
+ case "--private":
2363
+ parsed.options.private = true;
2364
+ break;
2278
2365
  case "--quiet":
2279
2366
  parsed.options.quiet = true;
2280
2367
  break;
@@ -2334,6 +2421,9 @@ function applyValueFlag(options, flag, value) {
2334
2421
  case "--repo":
2335
2422
  options.repo = value;
2336
2423
  break;
2424
+ case "--remixed-from":
2425
+ options.remixedFrom = value;
2426
+ break;
2337
2427
  case "--title":
2338
2428
  options.title = value;
2339
2429
  break;
@@ -2412,6 +2502,9 @@ async function main() {
2412
2502
  case "link":
2413
2503
  await runLink(parsed.options);
2414
2504
  break;
2505
+ case "make-remixable":
2506
+ await runMakeRemixable(parsed.options);
2507
+ break;
2415
2508
  case "controller":
2416
2509
  await runController({ ...parsed.options, kind: parsed.options.name });
2417
2510
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/cli-demo",
3
- "version": "0.33.0",
3
+ "version": "0.34.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": {