@series-inc/stowkit-cli 0.1.18 → 0.1.21

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.
@@ -64,7 +64,13 @@ export const PREVIEW_FLAG_STRINGS = {
64
64
  mainTex: 1,
65
65
  tint: 2,
66
66
  alphaTest: 3,
67
+ metalness: 4,
68
+ roughness: 5,
69
+ normalMap: 6,
70
+ emissiveMap: 7,
71
+ emissive: 8,
67
72
  };
68
73
  export const PREVIEW_FLAG_TO_STRING = {
69
74
  0: 'none', 1: 'mainTex', 2: 'tint', 3: 'alphaTest',
75
+ 4: 'metalness', 5: 'roughness', 6: 'normalMap', 7: 'emissiveMap', 8: 'emissive',
70
76
  };
@@ -39,7 +39,12 @@ export declare enum PreviewPropertyFlag {
39
39
  None = 0,
40
40
  MainTex = 1,
41
41
  Tint = 2,
42
- AlphaTest = 3
42
+ AlphaTest = 3,
43
+ Metalness = 4,
44
+ Roughness = 5,
45
+ NormalMap = 6,
46
+ EmissiveMap = 7,
47
+ Emissive = 8
43
48
  }
44
49
  export declare enum AacQuality {
45
50
  Lowest = 0,
@@ -49,6 +49,11 @@ export var PreviewPropertyFlag;
49
49
  PreviewPropertyFlag[PreviewPropertyFlag["MainTex"] = 1] = "MainTex";
50
50
  PreviewPropertyFlag[PreviewPropertyFlag["Tint"] = 2] = "Tint";
51
51
  PreviewPropertyFlag[PreviewPropertyFlag["AlphaTest"] = 3] = "AlphaTest";
52
+ PreviewPropertyFlag[PreviewPropertyFlag["Metalness"] = 4] = "Metalness";
53
+ PreviewPropertyFlag[PreviewPropertyFlag["Roughness"] = 5] = "Roughness";
54
+ PreviewPropertyFlag[PreviewPropertyFlag["NormalMap"] = 6] = "NormalMap";
55
+ PreviewPropertyFlag[PreviewPropertyFlag["EmissiveMap"] = 7] = "EmissiveMap";
56
+ PreviewPropertyFlag[PreviewPropertyFlag["Emissive"] = 8] = "Emissive";
52
57
  })(PreviewPropertyFlag || (PreviewPropertyFlag = {}));
53
58
  // ─── Audio Enums ────────────────────────────────────────────────────────
54
59
  export var AacQuality;
package/dist/init.js CHANGED
@@ -49,15 +49,17 @@ export async function initProject(projectDir) {
49
49
  catch {
50
50
  await fs.writeFile(gitignorePath, stowkitIgnores + '\n');
51
51
  }
52
- // Copy Claude skill file
53
- const skillDir = path.join(absDir, '.claude', 'skills');
54
- await fs.mkdir(skillDir, { recursive: true });
52
+ // Copy AI skill/rule files (CLI skill only — loader skills are installed locally with their packages)
55
53
  const thisDir = path.dirname(fileURLToPath(import.meta.url));
56
54
  const skillSrc = path.resolve(thisDir, '../skill.md');
57
- const skillDst = path.join(skillDir, 'stowkit.md');
58
55
  try {
59
56
  const skillContent = await fs.readFile(skillSrc, 'utf-8');
60
- await fs.writeFile(skillDst, skillContent);
57
+ const claudeDir = path.join(absDir, '.claude', 'skills', 'stowkit');
58
+ await fs.mkdir(claudeDir, { recursive: true });
59
+ await fs.writeFile(path.join(claudeDir, 'SKILL.md'), skillContent);
60
+ const cursorDir = path.join(absDir, '.cursor', 'rules');
61
+ await fs.mkdir(cursorDir, { recursive: true });
62
+ await fs.writeFile(path.join(cursorDir, 'stowkit.mdc'), `---\ndescription: StowKit asset pipeline — CLI usage, .stowmeta/.stowmat formats, GLB containers, and runtime reader packages\nalwaysApply: true\n---\n\n${skillContent}`);
61
63
  }
62
64
  catch {
63
65
  // Skill file not found in package — skip silently
@@ -66,7 +68,7 @@ export async function initProject(projectDir) {
66
68
  console.log(` Source art dir: ${srcArtDir}/`);
67
69
  console.log(` Output dir: public/cdn-assets/`);
68
70
  console.log(` Config: .felicityproject`);
69
- console.log(` Claude skill: .claude/skills/stowkit.md`);
71
+ console.log(` AI skills: .claude/skills/stowkit/SKILL.md, .cursor/rules/stowkit.mdc`);
70
72
  console.log('');
71
73
  console.log('Drop your assets (PNG, JPG, FBX, WAV, etc.) into assets/');
72
74
  console.log('Then run: npx stowkit build');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@series-inc/stowkit-cli",
3
- "version": "0.1.18",
3
+ "version": "0.1.21",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "stowkit": "./dist/cli.js"
@@ -17,7 +17,7 @@
17
17
  "dev": "tsc --watch"
18
18
  },
19
19
  "dependencies": {
20
- "@series-inc/stowkit-packer-gui": "^0.1.9",
20
+ "@series-inc/stowkit-packer-gui": "^0.1.11",
21
21
  "@series-inc/stowkit-editor": "^0.1.2",
22
22
  "draco3d": "^1.5.7",
23
23
  "fbx-parser": "^2.1.3",
package/skill.md CHANGED
@@ -7,12 +7,12 @@ StowKit is a game asset pipeline that compresses and packs assets into `.stow` b
7
7
  `.stowmeta` files are **auto-generated by the CLI**. To add any asset to the project:
8
8
 
9
9
  1. Place the source file (GLB, PNG, FBX, WAV, etc.) into the `srcArtDir`
10
- 2. Run `npx stowkit build` (or `npx stowkit scan`)
10
+ 2. Run `stowkit build` (or `stowkit scan`)
11
11
  3. The CLI detects the new file, generates the correct `.stowmeta` with proper defaults, and processes it
12
12
 
13
13
  **Do not write `.stowmeta` files by hand.** Only edit an existing `.stowmeta` after it has been generated by the CLI (e.g. to change quality settings, pack assignment, or stringId). The same applies to GLB children — the `children` array is populated automatically on the first build.
14
14
 
15
- To create materials, use `npx stowkit create-material <path>` — this scaffolds a `.stowmat` file with the right structure. You can also create `.stowmat` files manually if needed.
15
+ To create materials, use `stowkit create-material <path>` — this scaffolds a `.stowmat` file with the right structure. You can also create `.stowmat` files manually if needed.
16
16
 
17
17
  ## Project Structure
18
18
 
@@ -36,20 +36,20 @@ A StowKit project has a `.felicityproject` JSON file at its root:
36
36
  ## CLI Commands
37
37
 
38
38
  ```bash
39
- npx stowkit init [dir] # Scaffold a new project (creates .felicityproject, assets/, public/cdn-assets/)
40
- npx stowkit build [dir] # Full build: scan + process + pack
41
- npx stowkit scan [dir] # Detect new assets and generate .stowmeta defaults
42
- npx stowkit process [dir] # Compress assets (respects cache)
43
- npx stowkit status [dir] # Show project summary, stale asset count
44
- npx stowkit clean [dir] # Delete orphaned .stowcache and .stowmeta files
45
- npx stowkit create-material <path> # Create a .stowmat material file (--schema pbr|unlit|<name>)
46
- npx stowkit rename <path> <name> # Rename an asset file (preserves extension, updates sidecars)
47
- npx stowkit move <path> <folder> # Move an asset to a different folder (updates GLB child refs)
48
- npx stowkit delete <path> # Delete an asset and its .stowmeta/.stowcache files
49
- npx stowkit set-id <path> <id> # Change an asset's stringId
50
- npx stowkit packer [dir] # Open the packer GUI in browser
51
- npx stowkit editor [dir] # Open the level editor in browser
52
- npx stowkit serve [dir] # Start API server only (no GUI)
39
+ stowkit init [dir] # Scaffold a new project (creates .felicityproject, assets/, public/cdn-assets/)
40
+ stowkit build [dir] # Full build: scan + process + pack
41
+ stowkit scan [dir] # Detect new assets and generate .stowmeta defaults
42
+ stowkit process [dir] # Compress assets (respects cache)
43
+ stowkit status [dir] # Show project summary, stale asset count
44
+ stowkit clean [dir] # Delete orphaned .stowcache and .stowmeta files
45
+ stowkit create-material <path> # Create a .stowmat material file (--schema pbr|unlit|<name>)
46
+ stowkit rename <path> <name> # Rename an asset file (preserves extension, updates sidecars)
47
+ stowkit move <path> <folder> # Move an asset to a different folder (updates GLB child refs)
48
+ stowkit delete <path> # Delete an asset and its .stowmeta/.stowcache files
49
+ stowkit set-id <path> <id> # Change an asset's stringId
50
+ stowkit packer [dir] # Open the packer GUI in browser
51
+ stowkit editor [dir] # Open the level editor in browser
52
+ stowkit serve [dir] # Start API server only (no GUI)
53
53
  ```
54
54
 
55
55
  All commands default to the current directory.
@@ -76,7 +76,7 @@ All commands default to the current directory.
76
76
 
77
77
  ## .stowmeta Files (auto-generated — do not create manually)
78
78
 
79
- Every source asset gets a `.stowmeta` sidecar file generated by `npx stowkit build` or `npx stowkit scan`. These files control processing settings and should only be **edited** (never created) by hand. The examples below are reference for understanding and editing existing files.
79
+ Every source asset gets a `.stowmeta` sidecar file generated by `stowkit build` or `stowkit scan`. These files control processing settings and should only be **edited** (never created) by hand. The examples below are reference for understanding and editing existing files.
80
80
 
81
81
  **Texture example:**
82
82
  ```json
@@ -269,7 +269,7 @@ Each child in the `children` array supports the same settings as its correspondi
269
269
  - Animation children: `targetMeshId`
270
270
  - All children: `excluded`, `tags`, `pack`, `stringId`
271
271
 
272
- Edit these fields in the container's `.stowmeta` to customize per-child processing, then run `npx stowkit build`.
272
+ Edit these fields in the container's `.stowmeta` to customize per-child processing, then run `stowkit build`.
273
273
 
274
274
  ## .stowmat Files (Material Schemas)
275
275
 
@@ -323,14 +323,43 @@ For GLB mesh children, `materialOverrides` are auto-assigned from the GLB's sub-
323
323
 
324
324
  ## Setting Up a New Project
325
325
 
326
- 1. Run `npx stowkit init` in the project root
327
- 2. Place source art files in `assets/` (or whatever `srcArtDir` is set to)
328
- 3. Run `npx stowkit build` to process and pack everything
329
- 4. Output `.stow` files appear in `public/cdn-assets/`
326
+ 1. Install the CLI globally: `npm install -g @series-inc/stowkit-cli`
327
+ 2. Run `stowkit init` in the project root
328
+ 3. Place source art files in `assets/` (PNG, JPG, GLB, FBX, WAV, etc.)
329
+ 4. Run `stowkit build` to scan, compress, and pack everything
330
+ 5. Output `.stow` files appear in `public/cdn-assets/`
331
+
332
+ ## Packer GUI
333
+
334
+ Run `stowkit packer` to open a visual asset management UI in the browser (default http://localhost:3210). The packer provides:
335
+
336
+ - **Asset browser** — browse all assets in the project organized by folder, with type icons, file sizes, and processing status
337
+ - **Drag-and-drop import** — drag files directly into the browser to import them into the `srcArtDir`
338
+ - **3D mesh preview** — preview static meshes and skinned meshes with PBR lighting, grid, and human-scale reference
339
+ - **Texture preview** — view compressed KTX2 textures with resolution and channel info
340
+ - **Audio preview** — play back audio assets directly
341
+ - **Material editing** — view and edit `.stowmat` material properties, texture assignments, and preview flags
342
+ - **Per-asset settings** — adjust compression quality, resize, pack assignment, stringId, tags, and other settings through the inspector panel
343
+ - **GLB child management** — expand GLB containers to see and configure individual child assets (textures, meshes, materials, animations)
344
+ - **Pack management** — create, rename, and assign assets to different packs
345
+ - **Build button** — trigger a full build from the UI and see pack sizes
346
+ - **Folder management** — create, rename, move, and delete folders
347
+
348
+ The packer runs alongside the CLI build server — changes made in the GUI are written to the `.stowmeta` files on disk and stay in sync with CLI builds.
349
+
350
+ ### When to recommend the packer
351
+
352
+ - The user wants to **visually inspect** their assets (mesh previews, texture quality, audio playback)
353
+ - The user needs to **bulk-adjust settings** across many assets
354
+ - The user is **new to StowKit** and wants to understand the project structure
355
+ - The user wants to **import many files at once** via drag-and-drop
356
+ - The user is **debugging material/texture assignments** on meshes
357
+
358
+ For quick one-off changes (adjust a quality setting, rename an asset), the CLI commands are faster.
330
359
 
331
360
  ## Modifying Asset Settings
332
361
 
333
- Edit the `.stowmeta` file for any asset, then run `npx stowkit build`.
362
+ Edit the `.stowmeta` file for any asset, then run `stowkit build`. Or use the packer GUI to change settings visually.
334
363
  The build respects cache — only assets whose settings or source files changed get reprocessed.
335
364
  Use `--force` to reprocess everything.
336
365
 
@@ -361,12 +390,127 @@ Cache is automatically invalidated when source files or settings change.
361
390
  GLB children have their own cache entries stored alongside the container.
362
391
  Add `*.stowcache` to `.gitignore`.
363
392
 
393
+ ## Runtime Reader Packages
394
+
395
+ The CLI builds `.stow` packs. To **load** them at runtime you need a reader package. Choose based on your rendering engine:
396
+
397
+ | Package | Install | Use When |
398
+ |---------|---------|----------|
399
+ | `@series-inc/stowkit-reader` | `npm install @series-inc/stowkit-reader` | You want the low-level WASM reader only (zero deps) — parse packs, list assets, read binary data |
400
+ | `@series-inc/stowkit-three-loader` | `npm install @series-inc/stowkit-three-loader three` | Your game uses **Three.js** — loads meshes, skinned meshes, animations, textures, audio |
401
+ | `@series-inc/stowkit-phaser-loader` | `npm install @series-inc/stowkit-phaser-loader phaser` | Your game uses **Phaser** — loads KTX2/Basis compressed textures and audio |
402
+
403
+ If the project has a `.stow` build output but no reader dependency in `package.json`, the user likely needs one of these.
404
+
405
+ ### Three.js Quick Start
406
+
407
+ ```typescript
408
+ import { StowKitLoader } from '@series-inc/stowkit-three-loader';
409
+
410
+ const pack = await StowKitLoader.load('game.stow');
411
+
412
+ const mesh = await pack.loadMesh('building');
413
+ scene.add(mesh);
414
+
415
+ const character = await pack.loadSkinnedMesh('player');
416
+ scene.add(character);
417
+
418
+ const { mixer } = await pack.loadAnimation(character, 'walk');
419
+
420
+ // In animation loop
421
+ mixer.update(clock.getDelta());
422
+
423
+ // Cleanup
424
+ pack.dispose();
425
+ ```
426
+
427
+ Key APIs on `StowKitPack`:
428
+ - `loadMesh(stringId)` / `loadMeshByIndex(i)` — static mesh → `THREE.Group`
429
+ - `loadSkinnedMesh(stringId)` / `loadSkinnedMeshByIndex(i)` — skeletal mesh → `THREE.Group`
430
+ - `loadAnimation(skinnedGroup, stringId)` — returns `{ mixer, action, clip }`
431
+ - `loadAnimationClip(stringId)` — returns `THREE.AnimationClip` without playback
432
+ - `loadTexture(stringId)` — KTX2 → `THREE.CompressedTexture`
433
+ - `loadAudio(stringId, listener)` — AAC → `THREE.Audio`
434
+ - `listAssets()` — full manifest of the pack
435
+ - `dispose()` — free resources
436
+
437
+ Loader options (passed to `StowKitLoader.load`):
438
+ - `wasmPath` — path to `stowkit_reader.wasm` (default `'/stowkit/stowkit_reader.wasm'`)
439
+ - `basisPath` — path to Basis Universal transcoder (default `'/stowkit/basis/'`)
440
+ - `dracoPath` — path to Draco decoder (default `'/stowkit/draco/'`)
441
+
442
+ The three-loader auto-copies WASM/Basis/Draco files into `public/stowkit/` via a postinstall script.
443
+
444
+ ### Phaser Quick Start
445
+
446
+ ```typescript
447
+ import { StowKitPhaserLoader } from '@series-inc/stowkit-phaser-loader';
448
+
449
+ const pack = await StowKitPhaserLoader.load('/assets/game.stow');
450
+
451
+ await pack.loadTexture('characters/player', this); // registers with Phaser texture manager
452
+ const player = this.add.sprite(400, 300, 'characters/player');
453
+
454
+ const audioBuffer = await pack.loadAudio('sounds/bgm');
455
+
456
+ pack.dispose();
457
+ ```
458
+
459
+ Key APIs on `StowKitPhaserPack`:
460
+ - `loadTexture(assetPath, scene)` — KTX2 → Phaser texture (auto-transcodes to best GPU format)
461
+ - `loadAudio(assetPath, audioContext?)` — AAC → `AudioBuffer`
462
+ - `listAssets()` / `getAssetCount()` — pack manifest
463
+ - `dispose()` — free resources
464
+
465
+ Phaser limitation: no 3D model support — only 2D textures and audio. For 3D, use the three-loader.
466
+
467
+ ### Low-Level Reader
468
+
469
+ ```typescript
470
+ import { StowKitReader } from '@series-inc/stowkit-reader';
471
+
472
+ const reader = new StowKitReader();
473
+ await reader.init();
474
+ await reader.open(await fetch('assets.stow').then(r => r.arrayBuffer()));
475
+
476
+ const assets = reader.listAssets();
477
+ const texInfo = reader.parseTextureMetadata(0);
478
+ const audioInfo = reader.parseAudioMetadata(1);
479
+ const data = reader.readAssetData(0);
480
+
481
+ reader.close();
482
+ ```
483
+
484
+ All binary parsing is done in WASM (Zig) — 10-50x faster than JavaScript DataView.
485
+
486
+ ### Multiple Packs
487
+
488
+ All reader packages support loading multiple `.stow` packs simultaneously with isolated state:
489
+
490
+ ```typescript
491
+ const [envPack, charPack] = await Promise.all([
492
+ StowKitLoader.load('environment.stow'),
493
+ StowKitLoader.load('characters.stow'),
494
+ ]);
495
+ ```
496
+
497
+ ### Performance Logging
498
+
499
+ All reader packages re-export `PerfLogger`:
500
+
501
+ ```typescript
502
+ import { PerfLogger } from '@series-inc/stowkit-three-loader';
503
+ PerfLogger.enable();
504
+ // ... load assets — timing details appear in console ...
505
+ PerfLogger.disable();
506
+ ```
507
+
364
508
  ## Common Tasks for AI Agents
365
509
 
366
510
  ### Adding a GLB model (recommended 3D workflow)
367
511
 
368
512
  1. Place the `.glb` file into the `srcArtDir` (e.g. `assets/models/hero.glb`)
369
- 2. Run `npx stowkit build`
513
+ 2. Run `stowkit build`
370
514
  3. The pipeline automatically:
371
515
  - Creates a `glbContainer` `.stowmeta` for the file
372
516
  - Parses the GLB and extracts all textures, meshes, materials, and animations
@@ -385,7 +529,7 @@ To enable hierarchy preservation on a GLB, edit its `.stowmeta` and set `"preser
385
529
  ```bash
386
530
  # After the first build has generated the .stowmeta, edit it:
387
531
  # Set "preserveHierarchy": true in assets/models/hero.glb.stowmeta
388
- npx stowkit build
532
+ stowkit build
389
533
  ```
390
534
 
391
535
  The CLI always re-extracts GLB containers on every build, so changes to `preserveHierarchy` take effect immediately — no `--force` needed.
@@ -398,17 +542,17 @@ The CLI always re-extracts GLB containers on every build, so changes to `preserv
398
542
 
399
543
  ### Other common tasks
400
544
 
401
- - **Add a texture:** Place PNG/JPG into `assets/`, run `npx stowkit build`. The CLI auto-generates the `.stowmeta`. Do NOT create it yourself.
402
- - **Add audio:** Place WAV/MP3/OGG into `assets/`, run `npx stowkit build`. Same rule — never manually create `.stowmeta`.
403
- - **Add an FBX mesh:** Place FBX into `assets/`, run `npx stowkit build`.
404
- - **Enable preserve hierarchy on a GLB:** Edit the `.stowmeta` for the GLB container, set `"preserveHierarchy": true`, then `npx stowkit build`
405
- - **Change compression quality:** Edit the **existing** `.stowmeta` file's quality/resize fields (after it was generated by a build/scan), then `npx stowkit build`
406
- - **Create a material:** Run `npx stowkit create-material materials/MyMat` (creates `assets/materials/MyMat.stowmat` with PBR template). Use `--schema unlit` for unlit materials, or `--schema <name>` for a custom schema. Then run `npx stowkit build`.
545
+ - **Add a texture:** Place PNG/JPG into `assets/`, run `stowkit build`. The CLI auto-generates the `.stowmeta`. Do NOT create it yourself.
546
+ - **Add audio:** Place WAV/MP3/OGG into `assets/`, run `stowkit build`. Same rule — never manually create `.stowmeta`.
547
+ - **Add an FBX mesh:** Place FBX into `assets/`, run `stowkit build`.
548
+ - **Enable preserve hierarchy on a GLB:** Edit the `.stowmeta` for the GLB container, set `"preserveHierarchy": true`, then `stowkit build`
549
+ - **Change compression quality:** Edit the **existing** `.stowmeta` file's quality/resize fields (after it was generated by a build/scan), then `stowkit build`
550
+ - **Create a material:** Run `stowkit create-material materials/MyMat` (creates `assets/materials/MyMat.stowmat` with PBR template). Use `--schema unlit` for unlit materials, or `--schema <name>` for a custom schema. Then run `stowkit build`.
407
551
  - **Assign material to mesh:** Edit the mesh's **existing** `.stowmeta` to add `materialOverrides`
408
- - **Rename an asset:** `npx stowkit rename textures/old_name.png new_name` (extension preserved automatically, sidecars renamed too)
409
- - **Move an asset:** `npx stowkit move textures/hero.png characters` (moves to `characters/hero.png`, updates GLB child refs if container)
410
- - **Delete an asset:** `npx stowkit delete textures/unused.png` (removes source + .stowmeta + .stowcache, cascades for GLB containers)
411
- - **Change an asset's stringId:** `npx stowkit set-id textures/hero.png hero_diffuse`
412
- - **Check project health:** Run `npx stowkit status`
413
- - **Full rebuild:** `npx stowkit build --force`
414
- - **Clean orphaned files:** `npx stowkit clean`
552
+ - **Rename an asset:** `stowkit rename textures/old_name.png new_name` (extension preserved automatically, sidecars renamed too)
553
+ - **Move an asset:** `stowkit move textures/hero.png characters` (moves to `characters/hero.png`, updates GLB child refs if container)
554
+ - **Delete an asset:** `stowkit delete textures/unused.png` (removes source + .stowmeta + .stowcache, cascades for GLB containers)
555
+ - **Change an asset's stringId:** `stowkit set-id textures/hero.png hero_diffuse`
556
+ - **Check project health:** Run `stowkit status`
557
+ - **Full rebuild:** `stowkit build --force`
558
+ - **Clean orphaned files:** `stowkit clean`