What the director actually changes
The interesting part isn't that threejs-game-director routes work — it's how it decides what work exists at all. When a task arrives, the director first inspects two artifacts: whether artifacts/game-progress.md exists, and whether the repo already has src/Scene.ts with a mounting point. That's the whole fork. No fancy intent classification, no embedding of the user's prompt into a semantic space. It's a filesystem check that tells the director whether this is a fresh production run or a scoped patch to a codebase that already has a heartbeat.
A fresh run means the director emits a phase roadmap — prototype first, then core gameplay loop, then art direction, then QA — and schedules the 10-category visual scorecard as a baseline. It then invokes the gameplay specialist first, deliberately, because art polish on a scene that doesn't yet have a game loop is wasted tokens. The scorecard isn't just a rubric; it's a concrete gate with a target average score that the director will enforce across the roadmap's phases.
A patch, by contrast, skips the scorecard entirely and the roadmap. The director inspects what file the task touches — a HUD component, a physics callback, a shader file — and invokes exactly the specialist that owns that file, then mandates a single smoke test. One verification round, not the multi-phase QA pipeline. This is the band-aid for the failure where a generic coding agent treats game code like ordinary DOM work: writing event handlers without a tick loop, spawning meshes without a render loop, or treating delta-time as an afterthought. By making the phase explicit, the director ensures the loop exists before anyone tunes the bloom.
The art-direction constraint is subtle and worth calling out. The skill instructions carry an explicit brevity constraint on art guidance — a short, dense directive rather than a verbose description. That's not because the author is frugal with tokens; it's because long art descriptions get mangled in long context windows, and the agent ends up building the color palette you wrote rather than the vibe you meant. A tight constraint with concrete references survives the journey through routing, specialist invocation, and asset generation without becoming a caricature.
flowchart TD
A[Task Received] --> B{artifacts/game-progress.md exists<br/>AND src/Scene.ts in repo?}
B -- Yes, patch path --> C[Inspect task file scope<br/>HUD, physics, shader, or gameplay]
C --> D[Invoke only relevant specialist]
D --> E[One smoke test via Playwright]
E --> F[Return diff to repo]
B -- No, fresh path --> G[Emit phase roadmap<br/>prototype to core loop to art to QA]
G --> H[Schedule 10-category visual scorecard baseline]
H --> I[Invoke gameplay specialist first]
I --> J[Core loop verified]
J --> K[Art direction specialist with scorecard gate]
K --> L[QA rounds with seeded PRNG and headless bot]
Integrating the pack into both agent runtimes
There are two install mechanisms and they're not interchangeable. The skills CLI path — npx skills add majidmanzarpour/threejs-game-skills --skill '*' -a codex -g -y — pulls the whole pack through the standard package manager and places each skill's SKILL.md, reference material, and helper scripts into the runner's expected skill directory. The -g flag matters here; it installs globally rather than into a project-local directory, which means the skills are available across repos. The --skill '*' wildcard grabs all nine, and -a targets the agent runtime.
The shell installer is the more surgical option. install.sh accepts --codex, --claude, --all, --force, and --prune-managed. The flags map directly to where files land: --force overwrites existing copies of a skill if you've already got a version installed, and --prune-managed removes the directory entries the installer manages so you don't end up with stale skill definitions shadowing the current ones. If you're switching between agent runtimes, --prune-managed is the cleanup tool you want before re-installing.
The operational divider between the two runtimes isn't file placement — it's the delegation model. Claude Code supports native subagents, so the director can spawn the gameplay specialist and the art specialist as parallel workers, each with its own context window, and let them edit separate files before the director reconciles. Codex environments, in many configurations, don't provide that background task primitive. The director falls back to sequential, single-threaded execution: one specialist at a time, one file at a time, with the director waiting for each to finish before it dispatches the next.
That difference has a concrete consequence for artifacts/game-progress.md. In Claude Code, if two subagents update the progress file concurrently, you get write races — one specialist's checkpoint overwrites the other's, and the director re-runs a completed phase or loses track of an asset already generated. The progress file needs to be owned by the director, with subagents writing only their own phase results to it. In Codex's sequential mode, the race never happens because only one writer is active, but you lose the concurrency benefit — a large, multi-specialist build takes longer wall-clock time.
Before you start a serious build in Codex, you need to know whether your environment actually supports subagent spawning. If it doesn't, plan the roadmap as a strict linear sequence and accept the longer clock. If you're in Claude Code, you need to write the progress file with atomic updates or accept that the director's checkpoint state can drift.
| Dimension | Claude Code | Codex |
|---|---|---|
| Target directory | ~/.claude/skills/ (per-user, global via -g) |
~/.codex/skills/ (per-user, global via -g) |
| Subagent support | Native subagents, spawnable as background workers | May lack background task primitives; falls back to sequential |
| Delegation concurrency | Parallel specialists possible, races on progress file | Single-threaded, ordered execution; no race |
| Progress file owner | Director must write atomically; subagents only report phase results | Director is sole writer by default |
| Pre-flight reshuffles | Ensure subagent manifest allows file writes outside its own context; plan progress-file locking | Confirm subagent support; if absent, linearize roadmap and reduce context loading per phase |
The verification loop, and where the loop snaps
The QA loop is the most interesting thing about this pack precisely because it's deterministic in a domain that isn't. When a specialist writes gameplay code, it embeds a seeded PRNG into the simulation — the same seed produces the same sequence of positions, velocities, and object states on every run. Combined with deterministic test hooks, the agent can replay the same game frame sequence and compare the rendered output against a reference. That's the foundation.
The Playwright templates are not just smoke tests. They load the Vite page, capture a baseline render, then drive a headless bot through a scripted sequence of frames — movement input, physics interactions, UI clicks. The bot's motion is driven by the seeded PRNG, so the frames it visits are reproducible. Visual regression baselines store the reference image per scenario. On a subsequent run, the test captures the same frames and compares against that reference.
The comparison metric matters. Pixel-by-pixel equality breaks under any GPU variance — anti-aliasing differences, shader compilation nondeterminism, float precision across architectures. The practical threshold is Delta-E, a perceptual color difference metric that tolerates small variations in the same way a human eye would. Match within a Delta-E threshold and you pass; outside it and the test fails. The pack's templates support this by default; teams that swap in strict pixel equality get false failures every time.
The first snap point is physics determinism. Rapier compiles to WebAssembly and behaves differently for the same timeline of inputs if the integration step drifts. The agent must enforce a fixed-timestep accumulator — the physics world steps at a constant rate, decoupled from the render frame rate — or the seeded PRNG produces different trajectories on a machine that renders at 144Hz versus one at 60Hz. When the accumulator isn't there or is written incorrectly, the test harness doesn't error; it just silently produces a different frame sequence, and the visual comparison fails in ways that look like rendering bugs but are really physics drift. Names like "the bot moved differently this run" are the tell.
The second snap is the headless environment itself. Playwright running on a standard GitHub Actions runner without GPU acceleration falls back to software rendering — swiftshader or lavapipe. Software GL can fail to create a WebGL context entirely, or it creates one that stalls on shader compilation. The practical fix is running the tests under xvfb with --use-gl=angle --use-angle=swiftshader so the browser gets a stable software GL path. But even then, shader compilation under software rasterizers is slower and more memory-hungry, so timeouts creep in on complex scenes.
The third snap is WebGPU. The director selects WebGPURenderer with a WebGL fallback, but the fallback path doesn't always behave. If a specialist writes a compute shader in WGSL for the WebGPU renderer and the runtime falls back to WebGL, that shader is discarded — the scene silently loses its custom post-processing. Uniform buffer layouts differ between the two APIs, and a specialist that validates only one path ships code that breaks in the other. Strict dual-path validation is the fix, and it needs to be called out in the specialist instructions.
sequenceDiagram
participant S as Specialist
participant P as Playwright Bot
participant V as Vite Dev Server
participant T as Test Runner
participant D as Director
S->>S: Write code with seeded PRNG and test hooks
S->>V: Serve the game bundle
P->>T: Launch under xvfb with ANGLE/swiftshader
T->>V: Load page, wait for WebGL context
V-->>T: Context created (or fails - shader timeout)
T->>T: Capture baseline render with seeded PRNG
T->>P: Drive bot through scripted frames
P-->>T: Frame sequence complete
T->>T: Compare frames against reference snapshot using Delta-E
alt Delta-E below threshold
T-->>D: Pass - emit test report
D->>D: Accept phase, move to next
else Delta-E above threshold
T-->>D: Fail - emit artifact with seed and frame delta
D->>D: Decide re-run specialist or adjust visual scorecard
D-->>S: Request re-generation with new deterministic seed or shader fix
S->>T: Rewrite code, re-run loop
end
Physics tick coupling and the Wasm memory leak
The determinism story looks airtight until you run the same seeded test on two machines with different refresh rates. Rapier compiles to WebAssembly and steps its simulation in fixed increments; cannon-es is pure JavaScript and integrates on whatever delta the render loop hands it. Under a frame drop, cannon-es rolls forward with a larger delta, the physics state advances further than the deterministic hooks expect, and the bot's trajectory diverges from the baseline. The test fails with a visual regression that looks like a rendering artifact when it's really a timing problem.
Rapier has the opposite issue. It's actually too deterministic when you step it correctly — but only if your loop uses a constant timestep accumulator that decouples physics from the render frame rate. Without that accumulator, Rapier still advances during frame drops, but at an irregular cadence, and the seeded PRNG produces positions that don't match the reference frames the test harness captured. The loop doesn't error; it just silently produces a different world state. The failure mode I'd watch for is a specialist that writes player.position.x += velocity * delta in the render loop instead of stepping physics inside an accumulator. That code will pass smoke tests on a fast machine and fail them on CI.
The other silent failure is memory growth in the Wasm heap. Rapier allocates rigid body handles and colliders in its own memory space. JavaScript's garbage collector has no visibility into those allocations — an object can be fully unreferenced from JS and still hold a rigid body alive in the Wasm heap. When a specialist re-instantiates a scene or swaps out a physics collider during an iteration loop, the old handles never get freed. I've seen agent debug sessions grow the Wasm heap dozens of megabytes over a long build, and the browser only crashes when the allocation crosses the 4GB boundary — long after the agent has moved on to the next phase.
The practical guardrail is to enforce a fixed-timestep accumulator in the scaffold's template code, so the specialist never has to reconstruct it. And when the director transitions a phase — say, from gameplay polish to art direction — it should call a cleanup that explicitly destroys all rigid body handles and colliders from the previous phase. Finally, cap how many scene rebuilds an agent can do in a single session. If a specialist starts over five times, the Wasm heap is almost certainly accumulating leaked handles, and the next iteration should start from a fresh boot rather than another in-place rewrite.
Context window management through a multi-phase build
The real cost of this pack isn't the code it generates — it's the context it consumes before a single file gets written. Each specialist directory carries its own SKILL.md instructions, domain-specific reference material, and helper scripts. The director loads the physics selection guide, the 10-category visual scorecard, the asset generation prompt templates, and the full phase roadmap upfront. That's thousands of tokens, and in a multi-phase build with several specialists active, the remaining context window shrinks rapidly. On a large codebase, file diffs and updated asset buffers compete for the same space, and the agent either truncates a diff or forgets the scoring threshold — both are silent quality failures.
The pack's mitigation is artifacts/game-progress.md, a checkpoint file the director reads at the start of each phase to know what's already been completed. The problem is that it's a file, and subagents writing to it in parallel — when the runtime supports them — can overwrite each other's increments. One specialist finishes the core loop and writes PHASE: CORE_LOOP_DONE. Another specialist, still working on prototype refinement, writes PHASE: PROTOTYPE_DONE with a stale timestamp. The director now thinks the build has regressed to a completed phase, and it re-runs the core loop work that was already done, burning tokens and potentially overwriting new assets with old ones.
The operational fix is to treat the progress file as a state machine owned exclusively by the director, not as a shared scratchpad. The director is the only actor that mutates the state string. Specialists write their output into separate, append-only artifact files — a shader draft, a physics tuning log, a scorecard assessment — and the director polls those artifacts at the end of a phase, then advances the state. Append-only means a specialist can add a new line but never rewrite an existing one, so concurrent writes don't clobber each other's progress. The director's state string stays monotonic, moving forward through the phases and only ever reverting when the scorecard threshold fails.
stateDiagram-v2
[*] --> PROTO_DONE
PROTO_DONE --> CORE_LOOP_DONE
CORE_LOOP_DONE --> ART_GUIDANCE_DONE
ART_GUIDANCE_DONE --> POLISH_DONE
POLISH_DONE --> QA_RELEASED
POLISH_DONE --> ART_GUIDANCE_DONE: scorecard < 2.3
note right of PROTO_DONE
Director is only actor
that changes state string.
Specialists append artifacts
(write-only), never overwrite state.
end note
There's a second context cost worth naming. The scorecard's 10 categories, each with its own scoring criteria, is a lot of prose to hold in the active window while also reasoning about shader code. The directive's brevity constraint on art guidance helps, but the scorecard itself is verbose. If you're running a long build, I'd load the scorecard only after the core loop is confirmed, not upfront. Let the director hold the roadmap and the phase state; load the specialist's reference material right before that specialist runs, then release it. That keeps the average context footprint down and the full-file diffs intact.
Where the scaffold gets in the way on mobile and streaming
The scaffold that ships with this pack is tuned for desktop at launch, and it shows. The demo games — the ones the pack generates as reference implementations — are desktop pointer-and-keyboard experiences. There's no touch input layer, no virtual joystick, no consideration of mobile thermal throttling. The director enforces a lil-gui overlay on the scene as a default, which is a debugging artifact. If you ship a game with lil-gui visible, you're shipping a manual QA console to players. In a production build, that panel has to be stripped out entirely, and its controls replaced with either programmatic bindings or nothing.
The Playwright test templates have the same bias. They drive a bot through keyboard events and mouse clicks. If you need to verify a multi-touch virtual joystick, those templates won't exercise it — the bot has no concept of two simultaneous touch points, and the coordinate system it uses is based on pointer positions, not touch targets on a mobile viewport. Mobile verification requires a different test harness: either a device-emulation mode with touch events, or a separate Playwright project that runs on an actual device via WebDriver.
The larger gap is asset streaming. The pack generates assets — procedural or via external generators — and mounts them into the scene at build time. There's no LOD streaming, no KTX2/Basis texture compression, no memory unloading for distant meshes. As the player moves through a larger world, the browser retains every loaded texture and geometry in GPU memory until the page is closed. On a desktop with a discrete GPU that's tolerable. On a mobile device with a shared memory budget, the browser will kill the tab before the player reaches the third area. The agent won't see this in a headless test; it'll only surface as a crash after a minute of actual play on a phone.
The practical fix is proactive. In the Vite build step, I'd add gltf-transform with Draco or Open3D compression on all .glb assets, so geometry ships as compressed buffers rather than raw vertex data. Establish explicit asset budgets upfront — a cap on draw calls per scene, a polygon budget per enemy, a maximum texture dimension — and encode those budgets into the director's instructions as a gate, not a suggestion. If the agent generates a city block with 60 unique textures at 2048×2048, the budget check should fail the phase and require level-of-detail or texture atlas batching before it proceeds.
The mobile conversion itself is straightforward once the scaffold is unshackled. Remove lil-gui from the production bundle, map the test hooks to touch events and on-screen controls, and add a mobile-specific QA pass to the director's roadmap that verifies frame rate, memory usage, and thermal behavior under sustained play. The pack's deterministic groundwork — seeded PRNG, headless bot, visual regression — transfers cleanly; it just needs a touch-input agent defined for the bot to drive.
Limits of the skill pack for multiplayer and authoritative simulation
There's a hard line around what this pack isn't, and it's worth drawing before you reach for it. The director, the specialists, the seeded PRNG, the Playwright bot — all of it is built assuming a single-player, self-contained simulation. There is no authoritative server session concept, no WebSocket receive loop, no rollback netcode, no client-side prediction. If you ask the pack to build a multiplayer game, it will happily generate two independent single-player loops that happen to broadcast state over WebRTC, and the result will look correct in a headless test. The bot only checks one client's frame sequence — it has no way to catch the desync that happens when two clients apply inputs with different round-trip latencies.
The tricky parts of multiplayer aren't the raw networking primitives, they're the abstractions around them — input queues with timestamps, reconciliation, rollback buffers, state interpolation. Those are exactly the sort of things the pack's specialists don't know to build and its QA harness can't verify. When you need those, the pack's value shrinks to only the asset generation part. Procedural textures, a low-poly model, a synthesized audio cue — that's still useful. But the runtime and the verification loop are dead weight.
Where the pack does work well is complex single-player state machines. That said, even here I'd caution against free-styling a massive actor with dozens of boolean flags. The directors and specialists will happily generate that, and the seeded PRNG will make it deterministic enough to pass the tests — but the result is a flag-driven mess that no human can reason about after three phases of polish. I'd steer the pack toward small statecharts instead. Let the director's phase roadmap embody the machine, and let each specialist's code operate inside an explicitly scoped state. That's where the deterministic verification actually pays off rather than just confirming that a chaotic system happens to reproduce itself.
Resources
Updated 2026-09-04 by Mehran Mozaffari.
Related posts
10 September 2026
Unbundling the Hype: How Prompt-to-3D, MCP, and Collaborative Generative Workflows Actually Fit Together
5 September 2026
Shot Composer Deep Dive: Browser-Based 3D Blocking with an MCP Spine
30 August 2026
Monid: The OpenRouter for Agent Tools – A Deep Dive into Dynamic Tool Discovery, Unified Billing, and the Hidden Costs of Abstraction
8 June 2026
Code-as-Room: Thirteen Stages From a Top-Down Photo to a Render-Ready Blender Scene
15 September 2026
From Static Mesh to Walking Character: A Technical Operator's Manual for the 3D Vibe Coding Pipeline
15 September 2026
Designing Physical Objects with Gemini Canvas: From Prompt to Printable STL
