← ThrixelCONTENT HISTORY

Update to Thrixel

Snapshot Oct 24, 2026 · 13:23 UTC · version 1.2.2

Collection source: downloaded plugin package.

WHAT CHANGED

First saved snapshot

No earlier snapshot is available to establish a change.

Save Thrixel and check future changes in Following.

Up to 10 plugins free · no card required.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Builds polished, fully playable 3D browser games in three.js, with high-quality .glb models from the Thrixel API, and publishes each finished game to a public thrixel.world link that anyone can play. Use when the user wants to make a game, build a playable prototype, or generate 3D assets, and also when they want to publish or host a game folder they already have, share a playable link, or list, rename, update, unpublish or find the link for a game they published earlier.",
  "included_files": [
    {
      "relative_path": "engines/threejs/PITFALLS.md",
      "size_in_bytes": 12135
    },
    {
      "relative_path": "engines/threejs/example/index.html",
      "size_in_bytes": 2392
    },
    {
      "relative_path": "engines/threejs/example/main.js",
      "size_in_bytes": 2470
    },
    {
      "relative_path": "engines/threejs/example/shots.js",
      "size_in_bytes": 2989
    },
    {
      "relative_path": "engines/threejs/example/systems/fx.js",
      "size_in_bytes": 9212
    },
    {
      "relative_path": "engines/threejs/example/systems/player.js",
      "size_in_bytes": 6172
    },
    {
      "relative_path": "engines/threejs/example/systems/render.js",
      "size_in_bytes": 6423
    },
    {
      "relative_path": "engines/threejs/example/systems/ui.js",
      "size_in_bytes": 4364
    },
    {
      "relative_path": "engines/threejs/example/systems/world.js",
      "size_in_bytes": 8971
    },
    {
      "relative_path": "engines/threejs/lib/config.js",
      "size_in_bytes": 5479
    },
    {
      "relative_path": "engines/threejs/lib/dispose.js",
      "size_in_bytes": 3076
    },
    {
      "relative_path": "engines/threejs/lib/engine.js",
      "size_in_bytes": 7159
    },
    {
      "relative_path": "engines/threejs/lib/index.js",
      "size_in_bytes": 1128
    },
    {
      "relative_path": "engines/threejs/lib/input.js",
      "size_in_bytes": 17933
    },
    {
      "relative_path": "engines/threejs/lib/lights.js",
      "size_in_bytes": 4957
    },
    {
      "relative_path": "engines/threejs/lib/pool.js",
      "size_in_bytes": 7152
    },
    {
      "relative_path": "engines/threejs/lib/prewarm.js",
      "size_in_bytes": 8669
    },
    {
      "relative_path": "engines/threejs/lib/registry.js",
      "size_in_bytes": 3950
    },
    {
      "relative_path": "engines/threejs/lib/rng.js",
      "size_in_bytes": 5057
    },
    {
      "relative_path": "engines/threejs/lib/selftest.js",
      "size_in_bytes": 3668
    },
    {
      "relative_path": "engines/threejs/lib/shots.js",
      "size_in_bytes": 12877
    },
    {
      "relative_path": "engines/threejs/lib/touchui.js",
      "size_in_bytes": 5816
    },
    {
      "relative_path": "engines/threejs/templates/ARCHITECTURE.md",
      "size_in_bytes": 6338
    },
    {
      "relative_path": "engines/threejs/templates/subsystem.js",
      "size_in_bytes": 3722
    },
    {
      "relative_path": "engines/threejs/threejs.md",
      "size_in_bytes": 5216
    }
  ],
  "name": "build-world",
  "skill_md_contents": "---\nname: build-world\ndescription: Builds polished, fully playable 3D browser games in three.js, with high-quality .glb models from the Thrixel API, and publishes each finished game to a public thrixel.world link that anyone can play. Use when the user wants to make a game, build a playable prototype, or generate 3D assets, and also when they want to publish or host a game folder they already have, share a playable link, or list, rename, update, unpublish or find the link for a game they published earlier.\n---\n\n# This is the ChatGPT build - read this section first\n\nThis copy of the skill runs in ChatGPT, not on the user's computer. The Thrixel connector\nis Thrixel's hosted server, and there is no local machine, terminal, GPU or browser for you\nto use. **Where anything below conflicts with this section, this section wins.**\n\n- **three.js only.** Unity, Unreal and Roblox need an engine installed on a computer. If the\n  user asks for one of them, say this build makes three.js games and offer that, or point\n  them to the Claude Code or Codex version of Thrixel on their own machine.\n- **Nothing to set up.** Sign-in happened when the connector was added.\n- **Static files, no build step.** Write plain HTML and ES modules. Load three.js from a CDN\n  with an import map, for example:\n  `<script type=\"importmap\">{\"imports\":{\"three\":\"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js\",\"three/addons/\":\"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/\"}}</script>`.\n  No bundler and no build step.\n- **Models stay on Thrixel.** Generation tools return a download link and a `submission_id`\n  instead of saving a file. Do not paste model data into your files. In the game, load each\n  model from a path of your choosing (`models/boat.glb`), and remember which `submission_id`\n  belongs to each path: publishing packs them in for you.\n- **Never hand out a localhost address.** Nothing is served locally, so a `localhost` link\n  leads nowhere. The user's link is the one publishing returns.\n- **You cannot run the game here.** There is no browser or GPU, so there is no preview\n  video either: leave `cold_open` off. Check the game by reading your own code carefully instead: every model\n  path you load appears in `assets`, every control you describe is wired up.\n- **Publish automatically when the game plays end to end.** This replaces the serve-and-ask\n  step of asking first. Call:\n\n  ```\n  thrixel_publish_game(\n      files={\"index.html\": \"...\", \"js/main.js\": \"...\", \"css/style.css\": \"...\"},\n      assets={\"models/boat.glb\": \"<submission_id>\", \"models/dock.glb\": \"<submission_id>\"},\n      title=\"...\", controls=\"...\", controls_touch=\"...\",\n      description=\"...\", engine=\"threejs\", genre=\"...\", tags=\"...\",\n  )\n  ```\n\n  `files` holds every file except the models (text; a data URI for a binary such as\n  `cover.png`), with `index.html` at the root. Everything in \"Publish\" about `controls`,\n  `description`, `genre` and `tags` applies.\n- **Then give the user the link.** The publish result carries the game's public\n  `https://<slug>.thrixel.world` URL; put it on the first line of your closing message.\n  To change the game later, publish again with the same `game_id`: the link stays the same.\n\n# Cubes in this build\n\nGenerating models spends the Cubes on the user's Thrixel account. This build never talks about\nmoney beyond that:\n\n- **Never offer, recommend or describe plans, upgrades, top-ups, prices or promotions,** and\n  never send a payment or checkout link. There is no money question to ask at any point.\n- **Before generating,** call `thrixel_account_status`, and say in one line where the balance\n  runs out in the ranked asset list (see \"Draw the line through the list\"). Then carry on\n  without waiting.\n- **If the Cubes run out,** finish the game with what exists (unbuilt assets stay as simple\n  blocks), publish it, and say plainly which assets are still blocks and that they can be\n  generated once the account has Cubes again. Their Cubes and plan are managed in their\n  Thrixel account at https://thrixel.com, which is the only place to point them.\n\n# What is being asked for - route before you read further\n\nThis skill covers three jobs, and only one of them is a build. Decide which one\nyou are on now, because the wrong route wastes a lot of the user's time: an agent\nasked to publish a folder that starts planning an asset list and calling\n`thrixel_account_status` looks like it did not read the request.\n\n**1. Build a game** (\"make me a game\", \"build a X prototype\"). The default, and\nthe rest of this file. Continue below.\n\n**2. Publish a game the user pastes or uploads here.** Collect its files into `files`\n(index.html at the root) and publish, as in **Publishing to thrixel.world**. No assets are\ngenerated, so skip the asset list and every generation step.\n\n**3. Manage what is already published** (\"what have I published?\", \"what was the\nlink for my racing game?\", \"take the golf one down\", \"rename it\", \"hide it from\nthe directory\"). One or two tool calls and an answer. Go straight to **Managing\npublished games**. Do not read the rest of this file.\n\nJobs 2 and 3 need no Thrixel plan, no cubes and no account balance - publishing is\nfree. The only requirement is a signed-in account, which the MCP server handles;\nif it is not signed in, the tool says so.\n\n# Overview\n\nUse Thrixel for 3D assets. Use the target engine to orchestrate game logic, UI, effects, and sounds.\nThe game MUST be polished and visually stunning. The game should do everything thats\ndone in a AAA game, anything from high quality models and environment polish, to physics, including:\n- UI (HUD, health bars, etc.)\n- A mix of Architect and Architect -> Detailer meshes from Thrixel\n- Visually stunning environments (atmosphere, terrain if relevant, set and background dressing, shaders)\n- Rigorously playtested gameplay with intuitive keyboard controls\n- **Playable on a phone**, with touch controls and a HUD that fits a small screen\n- Optimized framerate of at least 30 FPS\n\n## Mobile is a requirement, not a port\n\n**Build every game to be playable on a phone from the start.** The finished game\nbecomes a public link (see Publishing, below), the user sends that link to\nsomeone, and that someone opens it on a phone. A game that needs WASD is dead on\narrival for most of the people who will ever see it.\n\nThis is a design constraint before it is a technical one, so decide it while you\nare deciding the controls, not afterwards:\n\n- Every action needs a touch equivalent. A scheme built on a modifier key, a\n  scroll wheel, or four simultaneous keys cannot be retrofitted onto two thumbs.\n- On-screen controls have to be visible. Touch input with no visible controls is\n  the most common mobile failure and it does not read as a bug to the player:\n  they see a 3D scene, tap once, and leave.\n- HUD text and buttons have to work at 390 px wide, with 44 px as the floor for\n  anything pressable.\n- A phone reports `devicePixelRatio` 3, so an uncapped renderer asks a phone GPU\n  for several times the pixels of a laptop. Cap it.\n\nThe three.js kit does most of this for you: `lib/input.js` feeds touch into the\nsame input snapshot the keyboard feeds (so gameplay code needs no touch branch), and\n`lib/touchui.js` draws the on-screen controls. Read the Mobile section of\n[engines/threejs/threejs.md](engines/threejs/threejs.md).\n\n**Never report a property you did not measure.** You cannot run the game in this build,\nso do not say it \"works perfectly\" or runs at 60 FPS. Say what you built and checked in the\ncode, and that the user can try it at the link.\n\nPay special attention to mesh quality, realism, character quality, and UI to ensure it looks AAA.\nWork alone, do NOT launch subagents to do work - subagents will interfere with each other and make\neverything more difficult. However, frequently launch subagents as harsh critic agents to inspect\nyour work. If the subagent determines the game doesn't look absolutely AAA, you must continue the\nbuild until the subagent decides the game looks good enough.\n\n## Player Guidance and UI Design\n\nTeach and guide the player primarily through the **game itself**, not through HUD explanations.\n\nThe first question should not be “what UI should explain this?” but **“how can the game design communicate this?”** Use level layout, encounters, environmental cues, animation, sound, object behavior, NPC dialogue, diegetic signs/displays, pacing, and player experimentation to convey mechanics and objectives whenever practical.\n\nA mechanic can be introduced by creating a safe situation where the player naturally discovers it. A required action can be taught by designing an obstacle that makes that action necessary. A control can appear on a sign, device, NPC prompt, or other element that belongs in the world. Sightlines, lighting, landmarks, contrast, recurring colors/materials, and spatial composition can guide attention without explicitly telling the player where to go.\n\nThe player does **not** need to understand everything immediately. It is often better to let them experiment, notice patterns, and build an understanding through play. Introduce complexity progressively and make cause and effect clear enough that the player can learn from what happens.\n\n### Use Non-Diegetic UI Sparingly\n\nHUD space and player attention are scarce. Treat **all onscreen text—persistent or temporary—as something that must justify interrupting the game**.\n\nPersistent UI should primarily show information the player genuinely needs during play, such as health, resources, time, score, or other important state. Temporary text should not become a substitute for good teaching or level design.\n\nGenerally avoid:\n\n- persistent chapter, area, or scene titles that are not useful during play;\n- prose explaining mechanics or controls;\n- repeated reminders of basic actions;\n- text that merely narrates what just happened;\n- decorative or poetic flavor popups attached to ordinary interactions or collectibles;\n- labels that restate information the world already communicates.\n\nFor example, collecting an important item can usually be communicated through animation, sound, effects, and a visible state change rather than a flavor text popup on the screen. Likewise, a mechanic such as rolling or dashing should preferably be taught through play rather than a popup explaining how the player can roll.\n\nIf explicit instruction is genuinely needed, keep it **brief, contextual, and integrated into the experience**. Showing `Shift - Roll` beside the first obstacle that requires rolling is very different from repeatedly explaining the mechanic in the HUD.\n\n### Design Hierarchy\n\nWhen deciding how to communicate something to the player, prefer roughly this order:\n\n1. **Game and level design** — let the player learn by doing.\n2. **Environmental/diegetic communication** — world design, NPCs, signs, objects, animation, audio, and feedback.\n3. **Minimal contextual UI** — only when the first two approaches would be unclear or impractical.\n4. **Persistent explanatory UI** — use only when the game genuinely requires it.\n\nDo not add text simply to make the game completely self-explanatory. Some uncertainty, experimentation, and discovery are part of good gameplay.\n\nThe UI that does exist should also feel like part of the game's **visual identity**. Typography, shapes, iconography, spacing, motion, and materials should fit the game's art direction and tone rather than feeling like a generic overlay.\n\nThese are principles, not rigid rules. Different games communicate differently. The goal is to make the **game itself do as much of the teaching and guiding as possible**, with UI supporting the experience rather than explaining it.\n\n# Plan the asset list - REQUIRED first step when BUILDING a game\n**\"Required\" means required on the build path.** If the user asked you to publish a folder\nthey already have, or asked about games they published earlier, none of this section applies -\nno assets are being generated, so there is nothing to plan or to spend. Go to Publishing or to\nManaging published games.\n\nOtherwise, once the user has asked for a game, do this FIRST. It applies to every game, whether\nthis is the user's first game or their tenth.\n\n**Size the asset list to the game, never to the balance.** Write out every 3D asset the game\nneeds in order to be good, then rank that list by how much the player will notice each item.\nBuild in that order. The balance decides how far down that list this session gets; it does not\ndecide how big the idea is. Do not shorten the list, downgrade a tier, or cut a feature because\nof what the balance says - a game planned around a cube budget is a smaller, duller game, and\nthe game is the point. Not before the user has had a chance to say how ambitious they want this\nbuild to be, either.\n\n\n**Call `thrixel_account_status` and read the real numbers.** Do not assume a plan. It returns the\nuser's plan, cube balance and concurrent-job cap. The cap is the number that changes what you\n*do*: it limits how many jobs may run at once. The balance does not change the plan, it only\ntells you how far down the ranked list you will get before you have to ask.\n\n**Never state a cap or cost from memory, including from this file.** `thrixel_account_status`\nreads live from Thrixel. Numbers written into this file eventually are not.\n\n## Draw the line through the list before you generate anything\n\nYou have the list the game wants and the balance that exists. Work out where one meets the\nother now, at the desk, rather than discovering it later when a call fails.\n\n1. **Rank the whole list as if cubes were unlimited.** A chicken farm wants twenty things.\n   Write all twenty, then order them by how much a player would miss each one.\n2. **Estimate how far the balance reaches, costing the list by subject.** Architect is\n   metered on object complexity, so one average across a mixed list is the wrong tool: a\n   character costs the better part of two props, and a list that is mostly characters and\n   buildings runs out at half the count a flat average predicts. `thrixel_create_model`\n   publishes a typical cost per subject; take the absolute numbers from there and from\n   `thrixel_account_status`, and add the flat price for every asset you also intend to detail or\n   sculpt. Cost the ranked list row by row and stop where the balance does.\n\n   Approximate is still the point. You are looking for \"about eight of these\", not a figure\n   to defend.\n3. **Say where the line falls, in one line, before the first generation call.** \"Twenty things\n   would make this farm properly. Your balance covers roughly the first eight, so the coop, the\n   hens and the feed trough get built and the tractor, the silo and the scarecrow start as\n   blocks.\" Then start. It is a statement, not a question - do not wait for an answer.\n4. **Build above the line, block out below it, then finish the game.** Everything under the line\n   goes into the scene as a labelled placeholder at the right size and in the right place, and\n   the game logic is written against the FULL list. What ships is a complete game with some of\n   its art still grey, which is playable, rather than a fraction of a game, which is not.\n\n**Do this on every account.** A plan name is not a balance: the allowance arrives\nonce a billing month and spends down from there, so an account on the largest plan, late in its\ncycle, can be holding less than a brand-new free one. Reading the plan name instead of the\nnumber is how a paying user ends up starting a twenty-asset game with seven assets' worth of\ncubes.\n\n**If the balance reaches the whole list, there is nothing to say.** No line, no news.\n\n**Re-check `thrixel_account_status` every few assets.** Estimates drift, and a balance that\njumped means Cubes were added: move the line down and carry on in the same ranked order.\n\n### The line is a forecast, not a quota\n\nIt exists so the user knows what to expect, and it is deliberately approximate. Treating it as a\nbudget to stop at leaves cubes unspent and the game thinner than the balance was good for, so\nkeep working down the ranked list until the service says no. Whether the balance covers the next\nitem is something it will tell you, at no cost, more accurately than an estimate can.\n\nTwo kinds of operation, gated differently, so \"no\" arrives in two shapes:\n\n- **Create and Edit are priced after the run**, so the only question is whether\n  anything is left. Any positive balance buys one more, and a single overrun past zero is\n  absorbed rather than refused mid-job. Worth attempting even when what remains looks small\n  for it.\n- **Detailer, Sculptor and Texture cost a flat price** the balance has to cover up front. Once\n  it no longer does, those are finished for the session while a Create may still go through.\n  That is a reason to reorder rather than to stop; a plain Architect asset is still worth having.\n\nSo the build ends when the service refuses, or when `thrixel_account_status` reports nothing\nleft, rather than at a number estimated earlier.\n\n## What things cost\n\nRead the current costs from `thrixel_account_status` and the generation tools' own\ndescriptions. The shape is what matters here, and it is stable even when the numbers are not:\n\n- **Detailer, Sculptor, Texture: a flat price per run, plus a reference image when you give\n  them only a prompt.** The flat part buys the GPU run. Handed just text, the service also has\n  to generate the image the run works from, and that is billed on its own - roughly a third\n  again on top. Passing an image, or reusing one with `reference_image_id`, skips it. Budget\n  the prompt-only case or your arithmetic is short on every one of them.\n- **Reduce triangles, rebake: free.** Always use `thrixel_reduce_triangles` to hit a triangle\n  budget; never re-run the detailer at a lower target to make something lighter.\n- **Architect: metered on real usage and charged after the run**, so it varies by what the\n  object is. Props are the cheap end, vehicles a little more, buildings more again, and\n  characters and creatures the expensive end at roughly two props each. The tail is long:\n  about one asset in ten costs double its subject's typical figure, which is why a plan\n  costed at the typical figure needs headroom rather than exactness. `thrixel_create_model`\n  carries the current per-subject numbers; take the balance from `thrixel_account_status`.\n\n  **Object complexity moves the cost far more than any setting you control.** There is no\n  tier-shopping decision to make here - the numbers are for planning the order of work, not\n  for finding a cheaper way to build the same asset.\n\n## Quality tier - always Plus\n\n**Always use `plus`. It is the default when you omit `quality`, so the correct action is to\nomit it.**\n\nDo not pass `balanced` on your own initiative - not to save cubes, not because the balance\nlooks low, not because the asset seems simple, and not because the user said something\ngeneral like \"keep it cheap\". The only time you pass it is when the user explicitly names a\nlower tier and asks you to use it. That is an advanced override, and it is never the default.\n\n- `plus` - the default, and the right answer for essentially everything.\n- `balanced` - only if the user explicitly asks for it.\n\nThe two tiers are a flat 2x apart on price, so a set built entirely on Plus does cost about\ntwice a set built entirely on Balanced. That is a known and accepted cost: the balance buys\nfewer assets and every one of them is the better version. Where the balance is the binding\nconstraint, cut the asset list rather than the tier - a shorter list of assets that look\nright beats a longer one that does not, and the ranking in \"Draw the line\" already says\nwhich ones to cut.\n\nInstancing is a *scene-dressing* technique, not a savings technique: rotating, scaling and\nrecoloring one mesh into a row of crates is good level design, and retexturing against a shared\n`reference_image_id` gets variants cheaply. Use it where it makes the scene better. Do not use\nit to avoid generating an asset the game actually needs.\n\nDo not downgrade the *generation type* to save money either. Sculptor vs architect vs\narchitect+detailer is a correctness choice, made by the rules below.\n\n\n# Target engine\n\nthree.js, always, in this build. Read [engines/threejs/threejs.md](engines/threejs/threejs.md)\n**in full** before writing the game; its kit in `engines/threejs/lib/` is plain browser modules\nyou can copy into `files`.\n\n# Thrixel asset generation\n\nThrixel turns text or image prompts into meshes, downloadable as `.glb`, `.fbx`,\n`.obj`, `.stl`, or `.usdz`. Thrixel provides three main paths, depending on the user's need:\n- \"Architect\" path: Generate low poly assets with smart hierarchy\n- \"Architect -> Detailer\" path: Generate low poly assets, then run \"detailer\" to add high\nquality high poly detail, retaining smart hierarchy\n- \"Sculptor\" path: Immediately generate detailed high poly assets, no hierarchy\n\nThrixel also provides other utilities/sub-features:\n- A  \"Texture\" follow-up can be run on ANY completed submission, regardless of type. Applies fresh materials\nand preserves geometry exactly.\n\n## Choosing a path per asset - ask this first\n\n**Does any part of this asset have to move on its own?**\n\nWheels that spin, sails that turn, a turret that rotates, a door that opens, a lid, a limb,\na propeller. That single question decides the path, because **only Architect produces named,\nseparately addressable parts**, and it is the only property you cannot add later. Polygon\ncount and realism you can always change; a merged mesh can never be un-merged.\n\n| Need | Path | Why |\n|---|---|---|\n| **Moving parts, lower poly, more stylized look** | Architect | Named part hierarchy, cheapest option |\n| **Moving parts AND high poly, high quality, or organic/complex details** | Architect -> Detailer | The detailer mostly keeps the hierarchy, but see the caveat below: thin parts can still be lost |\n| **Moving parts, and the shape is already right** | Architect -> Texture | Geometry is untouched, so every part and name survives exactly. Same price as the detailer |\n| **Static, organic** (creature, character, plant, rock, food) | Sculptor | Best organic shapes, and cheaper than Architect -> Detailer |\n| **Static, man-made, high poly, high quality, or organic and/or complex** | Sculptor | Nothing moves, so the part hierarchy buys you nothing and costs ~1.5x |\n| **Static, stylized / low-poly, instanced a lot** (trees, rocks, crates) | Architect | Keeps triangle counts sane when placed hundreds of times |\n\n**`adherence_level` runs 0 to 12, and 9 is the DEFAULT, not the maximum.** 9 keeps\n`preserve_parts` on. **Below 9 the server merges the parts by default**, because holding a part\nsplit together while the silhouette is being reshaped is what produced the remesh artifacts. So\nif you chose Architect *for the parts*, do not lower adherence. If you truly need both, pass\n`preserve_parts: true` explicitly and inspect the result.\n\n**`preserve_parts: true` is best effort, not a guarantee, and thin parts are what it loses.**\nThe survivors are the thick parts. A propeller blade is thin, and thinness is what predicts\ndestruction, so the parts most likely to be destroyed are exactly the moving parts you chose\nArchitect to get.\n\n**If parts must survive, set `adherence_level: 12`.** The default 9 is not enough. Measured on\none 78-part quadcopter blockout, same seed and same reference image, only adherence changed:\n\n| | `adherence_level: 9` (default) | `adherence_level: 12` |\n|---|---|---|\n| parts returned | 28 of 78 | **35 of 78** |\n| propellers | one gone, two returned as slivers | **all four, at full size** |\n\n12 still drops very small decorative sub-parts (cooling slots, indicator rings), so it improves\nthe odds rather than guaranteeing anything.\n\n**So: if the blockout's shape is already what you want, do not run the detailer at all.** Use\n`thrixel_retexture_model` instead. It costs the same, gives the asset a finished look, and never\ntouches geometry, so every part and name survives exactly. The detailer is for when you want the\n*shape itself* to gain detail. Always `thrixel_inspect_model` a detailer result and confirm the\nparts you need are still there.\n\n**Proportions matter too.** An asset whose bounding box is far from a cube - a building, a roof,\na floor plane, anything long and thin - comes back noticeably worse from both the Detailer and\nthe Sculptor, because the object fills only a small part of the working volume. For buildings,\ntexture rather than detail.\n\n**What the paths cost relative to each other** (absolute numbers from the tools' own descriptions):\n\n| Path | Cost | Note |\n|---|---|---|\n| Architect alone | Cheapest by a wide margin | Metered, so it varies with the object |\n| Sculptor | One flat operation, plus a reference image if you gave it only text | Cheaper from an image you already have |\n| Architect -> Detailer | Metered Architect **plus** one flat operation | The most expensive route. The detailer inherits the mesh, so no reference image is generated |\n\nSo **Architect -> Detailer costs roughly 1.5x a Sculptor**. That ratio is the decision;\nthe exact cube figures are not, and change without this file changing.\n\n**If the object will not be animated, reach for the Sculptor directly.** What Architect ->\nDetailer adds over a Sculptor is the named part hierarchy, and a static prop never uses it - so\non something that just sits there you are paying ~1.5x for articulation the game will not\ntouch. The Sculptor is built for exactly this case: static and organic subjects, one flat\nprice, the best organic shapes of the three paths. Pay the premium only where you need\narticulation *and* fidelity on the same asset: the hero vehicle, the main character, and little\nelse.\n\nDecide the moving-part list at planning time, not later. It is the same list you will pass to\n`thrixel_group_parts`'s `keep_groups` (see Mesh grouping below), so writing it down early makes both decisions\nat once.\n\n## Other asset rules\n\n- **Scale**: Thrixel is built for singular, well-defined objects (\"a cute chunky bike\"), and\n  that is where it is strongest. Terrain, mountains and very large buildings are the engine's\n  job - build the large-scale structure in engine code, use Architect for any blocked-out\n  massing, and spend Thrixel on the props the player walks up to.\n- **Complex visual features** (a dragon made of stained glass) need Sculptor or\n  Architect -> Detailer. Architect alone gives flat-colored low-poly, which is the right look\n  for a stylized set and the wrong one for a hero asset.\n- **Use all three paths in a project** - for variance, for performance, and because each one is\n  the right answer for a different kind of asset.\n- **Iterate with follow-up prompts.** `thrixel_edit_model` holds every part outside\n  `focus_on_node_names` bit-identical, so refining is cheap and safe. Place the asset, look at\n  it in the scene, and revise it until it fits.\n- **Never pass an `image`.** Text prompts only, on every endpoint. Thrixel generates and manages\n  its reference imagery internally.\n- **Every asset arrives at roughly the same size.** Scale is normalised, so a castle keep and\n  a peasant import into the same bounding box. Nothing warns you; the castle just turns out to\n  be a garden shed. Set relative scale explicitly at import - decide the real-world size of\n  each asset class when you write the asset list, not when the scene looks wrong.\n- **Up is always Y. Only FORWARD varies.** Thrixel exports Y-up on every asset, as glTF\n  requires, so never write per-asset up-axis detection or a Z-up correction branch. glTF does\n  not define a forward axis, though, so a long axis can land on X where you expected Z: read\n  the bounding box or look at the thumbnail, decide the facing per asset, and correct it once\n  at import rather than discovering it when a vehicle drives sideways. (If a pivot listing from\n  `thrixel_group_parts` looks Z-up, that is Thrixel's internal working space, not the file -\n  a real project once wrote \"these assets came back Z-up\" into a source comment on the strength\n  of that listing and carried the wrong belief for its whole life.)\n\nIf necessary, read thrixel api docs here: https://thrixel.com/docs/,\nbut the vast majority of thrixel information is contained within this skill and the mcp.\n\n## API Workflow\n\nUse the **Thrixel MCP tools** for every generation step. Each one submits the job, waits for it,\nreturns a download link plus a rendered thumbnail - the whole round trip, handled. Do not\nwrite your own polling loop or call the API any other way: across a build\nwith thirty assets, a hand-rolled loop is one dropped result away from a missing model that\nnobody notices until the scene is assembled.\n\n1. **Start a project, named after the game.** Free, one call, and it must come before the first\n   generation:\n\n   ```sh\n   thrixel_start_project(name=\"Submarine Explorer\")\n   ```\n\n   Everything generated afterwards is filed under it automatically. **Do not pass `project_id`\n   on any other tool** - it is already handled, and threading it through thirty calls is how it\n   ends up missing from three of them.\n\n   This is the difference between the user opening the web app and finding this game's assets\n   as a set, or finding every asset from every game they have ever built in one flat list. That\n   cannot be sorted out afterwards, so it has to be right at the start.\n\n   If the user is returning to a game they built earlier, call `thrixel_list_projects` and\n   resume it instead, so the new assets join the old ones:\n   `thrixel_start_project(project_id=\"<the id>\")`.\n\n   Each result tells you where it landed (`Filed under project: ...`). If that line is missing,\n   you skipped this step - fix it before generating anything else.\n\n   The project is also what a style guide attaches to (step 2a), and only generations inside\n   it are given that guide - another reason this call comes first.\n\n2. **Decide the shared style once, and put it somewhere the tools can apply for you.**\n   Thirty prompts that each restate the style is thirty chances to state it slightly\n   differently, and the set drifts. There are three places to put it, and they are not\n   interchangeable:\n\n   **a. Rules -> a project style guide.** Things you can state in words: polycount budgets,\n   \"flat colours, no gradients\", \"never add a ground plane\", \"a door is 2.1m tall\", in-world\n   naming. Write it once; it applies to every generation in the project from then on.\n\n   ```sh\n   thrixel_add_project_source(filename=\"style.md\", content=\"...art direction, budgets, scale...\")\n   ```\n\n   **b. Look -> a style reference.** How something should APPEAR: palette, material, finish,\n   how worn it is. A paragraph is bad at this and a finished model is good at it. Build one\n   asset you are happy with, then point the rest at it:\n\n   ```sh\n   hero = thrixel_create_model(prompt=\"a weathered wooden market stall\")\n   thrixel_create_model(prompt=\"a wooden barrel\",\n                        style_reference_submission_id=hero.submission_id)\n   ```\n\n   The reference contributes appearance ONLY - the subject always comes from your prompt.\n   `thrixel_sculpt_model` takes it too. Give that one an `image` as well and it restyles YOUR\n   image into that look, so what comes back is no longer the picture you passed in.\n\n   **c. One-off tweaks -> the prompt.** Anything that applies to this asset and no other.\n\n   Use a and b together. Text carries constraints, a picture carries appearance; asking\n   either to do the other's job is where a set starts drifting.\n\n3. **Generate base meshes** with `thrixel_create_model`, passing `quality` per the plan above.\n   Run them in waves that respect the concurrency cap from `thrixel_account_status`.\n\n   Generation runs in the background, so start it early and write systems while it runs, placing\n   real assets as they arrive.\n\n4. **Look at every thumbnail.** It comes back with the result, so there is no excuse to build on a\n   bad asset. If the shape is wrong, fix it with `thrixel_edit_model` (natural language, and it\n   holds every part outside `focus_on_node_names` bit-identical) rather than regenerating from\n   scratch, which costs more and throws away what was already right.\n\n   **Then refine it. This step is REQUIRED for every hero asset and it is the one agents skip.**\n   Editing is where Architect assets get good, and a first generation is a draft, not a result.\n   For anything the player sees up close, run at least one `thrixel_edit_model` pass and keep\n   going until you would ship it:\n\n   1. Place the asset in the scene and screenshot it **in context**, not in isolation. Wrong\n      proportions only show up next to a door, a character, or the ground.\n   2. Name the single worst thing about it. If you cannot, look harder - \"it's fine\" after one\n      generation means you have not compared it to the reference.\n   3. Fix exactly that with `thrixel_edit_model`, scoped with `focus_on_node_names` so the rest\n      stays bit-identical. Look again.\n\n   Editing is metered and cheap next to regenerating, so the loop costs far less than settling.\n   Stop when the asset is genuinely good, not after a fixed number of passes.\n\n5. **Detail pass (optional, animated assets only)** with `thrixel_detail_model` - one flat\n   operation. Turns a blockout into high-resolution geometry with a PBR texture. Only worth it when the asset needs\n   its part hierarchy *and* fidelity; for anything static, generate it with the Sculptor instead.\n   Pass a `prompt` describing the finished look, and set `adherence_level: 12` so your named\n   parts survive - the default of 9 loses thin ones. `texture_size` is 2048 or 4096;\n   `decimation_target` around 20000 is a good game target. **Skip this step entirely if the\n   blockout's shape is already right** - go straight to step 6, which costs the same and cannot\n   damage the geometry. After any detail pass, `thrixel_inspect_model` the result and confirm\n   your moving parts are still in the list; thin ones do get lost.\n\n6. **Texture pass (optional)** with `thrixel_retexture_model` - one flat operation, new\n   materials, geometry untouched. This is the cheap way to restyle a whole set: pass the same `reference_image_id` to\n   every asset and they come back visually consistent, and reusing an image is not re-charged.\n   `apply_to_node_names` restricts it to named parts.\n\n7. **Hit the triangle budget** with `thrixel_reduce_triangles`. **Free.** Never re-run the detailer\n   at a lower target to lighten something.\n\n8. **Group the meshes before importing into the engine** (see below), then:\n\n   ```sh\n   thrixel_group_parts(submission_id=..., keep_groups=[...])\n   ```\n\n## Mesh grouping - required, not an optimisation\n\nThrixel returns a *named part hierarchy*: one mesh node per part. That naming is the whole\npoint of the Architect path, but the node count is high (ie dozens or hundreds). In engine,\nthis gives each object its own draw call and kills fps.\n\n**`thrixel_group_parts` fixes this, and it is FREE.** It runs on Thrixel's servers. Run it on every model before importing into the engine.\n\n- **Everything that does not move becomes one mesh** (default name `Body`). Material slots\n  survive the join, so the semantic slots (`Paint`, `Glass`, `Chrome`, `Rubber`, `Rim`, ...)\n  stay addressable per-surface. Re-skinning those slots with authored PBR is what makes\n  independently generated assets look like one set. How the slots surface in your engine is\n  in the engine file.\n- **Named moving parts stay separate**, one mesh each, via `keep_groups`. Each gets its\n  origin set to its own geometric centre, so the engine can spin or steer it in place\n  instead of orbiting the model root. `FL` / `FR` / `RL` / `RR` auto-expand to the\n  wheel-corner spellings Thrixel actually emits, so you can omit their aliases.\n- **The result reports each group's pivot origin.** That is what you position and animate\n  against; it is not recoverable from the GLB without re-parsing it. Pivots always sit at the\n  group's geometric centre - right for a wheel, wrong for a turret or a head on a swivel,\n  where the real axis is the mount point. Fix those in-engine: parent the part under an empty\n  (Unity) or a `THREE.Group` placed at the mount point, and rotate the parent.\n- **Scattered props get a triangle budget** via `target_triangles`, applied to the merged\n  mesh only. Kept groups are left alone, because decimating a wheel to hit a whole-model\n  budget wrecks it. Sculptor output is deliberately dense - trees arrive at 90-160k triangles,\n  which is what you want for a hero close-up and far more than you want instanced hundreds of\n  times. `target_triangles` serves both, and it is free.\n\n```\nthrixel_group_parts(\n  submission_id = \"<the detailed car>\",\n  keep_groups   = [{\"name\": \"FL\"}, {\"name\": \"FR\"}, {\"name\": \"RL\"}, {\"name\": \"RR\"}],\n  target_triangles = 20000,\n)\n```\n\n**Call `thrixel_inspect_model` first to get the real part names.** A `keep_groups` entry\nthat matches nothing **fails the job on purpose**. Silently welding a moving part into the\nbody gives you a model that looks perfect and simply never animates, which is far more\nexpensive to debug than a failed job.\n\nTwo things it handles that are easy to get wrong by hand: matching part names requires\ntokenising the node path (regex `\\b` fails on `_`, so `\\bfl\\b` never matches `FL_spoke0`),\nand structural parts nested *inside* a moving group - `FL_arch`, `FL_Coil3` under\n`FL_Wheel_Group` - must be excluded or the wheel arch spins with the tyre.\n\n### If you decimate a GLB yourself, weld first\n\n`thrixel_reduce_triangles` already handles this, which is the main reason to use it. If you\nreduce a Thrixel GLB with your own tooling instead, **weld coincident vertices before you run\nthe decimator** (Merge by Distance in Blender, `mergeVertices` in three.js).\n\nglTF has no per-face UVs, so a textured GLB arrives with its vertices split along every UV\nisland boundary. Those duplicates sit in the same place but are not connected, so a collapse\ndecimator pulls them apart and the seams open into large visible cracks.\n`thrixel_reduce_triangles` welds first, which is why it does not. Welding does not disturb the\nUVs, which are stored per-corner, so each island keeps its own coordinates.\n\nBetter still, do not decimate by hand at all - `thrixel_reduce_triangles` is free and already\ncorrect.\n\n# Publishing to thrixel.world\n\nPublishing puts the game at a public `https://<name>.thrixel.world` address that anyone with\nthe link can play in a browser, phone included. It is free, and every later publish with the\nsame `game_id` updates the same address. In this build it is automatic: publish as soon as the\ngame plays end to end, as described at the top of this file.\n\n## Assemble the bundle\n\nThe bundle is what `files` and `assets` describe: `index.html` at the root, the JavaScript and\nCSS it loads, and the models by path. There is no build step, so what you write is what ships.\nInclude only what the game loads; leave out notes, drafts and anything else that is not part\nof the game.\n\n## Check it before it is public\n\nThe server refuses unsafe paths and skips junk files on its own, and it scans the bundle\nfor API keys and refuses to publish one it finds.\n\nWhat the server cannot judge is what the files MEAN, and that is your job, because\nyou are the only one who has read them. Four things, quickly:\n\n1. **Secrets.** Never put an API key, password or token in `files`. A game that calls\n   an API from the browser needs the key in the browser, where anyone can read it, so\n   the fix is a key that is safe to be public, or no such feature.\n2. **Private files that came along for the ride.** Notes, screenshots of other\n   things, documents, exports - a game folder often accumulates them. Name anything\n   that does not look like part of the game and let the user decide.\n3. **Content that is not theirs to publish.** Downloaded models, ripped audio,\n   someone else's game. Local play and a public URL under their name are different\n   things. If the folder is obviously somebody else's work, ask before publishing.\n4. **What it actually is.** Publish games. Do NOT publish a page that imitates a\n   real company's login, a payment form, a fake storefront, or anything built to\n   look like a service it is not - regardless of how it is described. That is\n   phishing infrastructure, and it is not a judgement call about the user's\n   intentions: the platform must not host it. If a folder is that, say plainly you\n   cannot publish it, and do not offer a workaround.\n\nAnd one fact that is not a problem but must be said out loud before the link\nexists: **a server component will be dead.** A multiplayer relay, an LLM proxy, a\nscore backend - only static files ship. Say which feature stops working, and make\nsure the game degrades gracefully rather than hanging on a failed fetch.\n\n## Publish\n\nUse `thrixel_publish_game`.\n\n```\nthrixel_publish_game(\n    files={\"index.html\": \"...\", \"js/main.js\": \"...\"},\n    assets={\"models/pan.glb\": \"<submission_id>\"},\n    title=\"Order Up!\",\n    controls=\"Arrow keys to move, Space to plate, Esc to pause\",\n    controls_touch=\"Drag a dish onto a plate, tap the bell to serve\",\n    description=\"A restaurant kitchen where the orders never stop and the timer always wins.\",\n    engine=\"threejs\",\n    genre=\"Simulation\",\n    tags=\"Cooking, Fast, Arcade\",\n)\n```\n\n**Pass every one of these. Nothing can recover them later.**\n\n- **`controls`** and **`controls_touch`** - one line each, and both must be what\n  you actually WIRED UP rather than what you meant to: read them off your own input\n  code, keyboard and touch both. A stranger who opens this from the gallery and presses the wrong\n  thing concludes the game is broken, which makes a wrong answer here worse than\n  none.\n\n  The page picks between them by POINTER TYPE, not screen size, so a phone gets\n  the touch line and a laptop gets the keyboard one even at the same width. Omit\n  `controls_touch` when the game plays the same either way - an absent line falls\n  back to `controls`, so leaving it out says \"no difference\" rather than \"no\n  phone support\".\n- **`description`** - one sentence about the GAME, for somebody who has never seen\n  it. This is the blurb a stranger reads on the game's card. Describe what the\n  game IS, not what you built or how. \"A restaurant kitchen where the orders never\n  stop\" - not \"I built a restaurant game with a timer\".\n- **`engine`** - `threejs`.\n- **`genre`** - ONE word, and it is the shelf the gallery files the game under:\n  `Action`, `Shooter`, `Platformer`, `Puzzle`, `Racing`, `Strategy`, `Simulation`,\n  `Adventure`, `Sandbox`, `Board`, `Tool`. Pick the closest one rather than the\n  most flattering one. Anything outside the list is dropped, so inventing\n  `Roguelike-lite` files the game nowhere.\n- **`tags`** - up to four, comma-separated, describing what the game is LIKE:\n  `Cozy`, `Relaxing`, `Fast`, `Atmospheric`, `Colorful`, `Retro`, `Neon`,\n  `Sci-fi`, `Fantasy`, `Space`, `Steampunk`, `Underwater`, `Post-apocalyptic`,\n  `Arcade`, `Story`, `Short`, `Endless`, `Creative`, `Turn-based`, `Realistic`,\n  `Physics`, `Roguelike`, `Idle`, `Exploration`, `Collectathon`, `Builder`,\n  `Tower defense`, `Stunts`, `Cooking`, `Time trial`, `Party`, `Two players`,\n  `Multiplayer`, `Sandbox-y`, `Data`, `Experimental`.\n\n  Describe the GAME, not the technology. `3d`, `browser` and `singleplayer` are\n  true of almost everything published here and are ignored. Common synonyms fold\n  in (`scifi` and `science fiction` both become `Sci-fi`), but a word the\n  vocabulary does not know is **not stored** - it comes back in the response, and\n  resending it will not make it work. Pick the nearest listed word instead.\n\n  **You are the only one who can supply these two.** Nothing downstream can look\n  at a zip of compiled JavaScript and work out that it is a cozy platformer. A\n  game published without them sits on no shelf in the gallery and can be found\n  only by scrolling past everything else.\n\nThe project is attached for you - the MCP server knows which one the assets came\nout of, so there is nothing to look up and nothing to pass.\n\nIt zips the directory, uploads it, waits for the deploy and returns the live URL.\nGive the user the URL as the first line of your reply - it is the thing they asked\nfor. A random address like `zesty-panda-14743.thrixel.world` is normal and is\ntheirs permanently.\n\n## After the first publish\n\n- **Updates:** republish with the same `game_id` - the link never changes, and the old\n  version keeps serving until the new one is fully deployed, so a failed republish never\n  takes a live game down. Offer this when the user makes further changes to a published game.\n- **Unpublish** takes the game offline immediately; the address stays theirs and\n  republishing revives it.\n- **Sharing is by link, and that is already the default.** The game's address is\n  public and anyone who has it can play; nothing else is needed for \"just for\n  friends\". A published game is NOT in the gallery unless somebody asked and staff\n  agreed, so do not call anything to keep it private - there is nothing to turn off.\n- **Discovery is opt-in and reviewed.** `thrixel.com/world` is a public gallery Thrixel\n  curates. `thrixel_update_game(game_id=..., listed=true)` asks to be in it; staff answer,\n  so it goes `pending` rather than straight in. **This is the ONLY thing here that waits\n  on a human, and it never touches the link** - the game is playable at its own address\n  before the request, during it, and after a refusal.\n\n  **Offer it once, when the game is finished** - not while they are still iterating. A\n  natural finish line looks like: they stop asking for changes, they say it is done, or\n  they ask about sharing it more widely. One sentence, and if they decline do not raise\n  it again this session:\n\n  > Want me to submit it to the Thrixel gallery? It stays playable at the same link\n  > either way - this just asks to have it featured where people browse.\n\n  Do not describe the wait as blocking anything, because it does not.\n\n# Managing published games\n\nThe user does not have to be building anything to ask about what they have already\npublished. Answer these directly, without touching the rest of this file.\n\n**If these tools are not in your tool list**, publishing has not reached your Thrixel\nMCP server version yet. Say so in one line, tell them upgrading the server brings it,\nand stop. Do not call the REST API by hand and do not guess at what they have\npublished - the user's own record of their links is better than a guess.\n\n| they ask | do this |\n|---|---|\n| \"what have I published?\" / \"list my games\" | `thrixel_list_games()` - returns title, status, URL and `game_id` for each |\n| \"what's the link for X?\" | `thrixel_list_games()`, then give them the URL for X. Do not make them scroll a table for one link. |\n| \"take X offline\" / \"unpublish X\" | Get the `game_id` from `thrixel_list_games()`, then `thrixel_unpublish_game(game_id=...)`. Tell them the address stays theirs and republishing revives it. |\n| \"take X out of the gallery\" | Only if it is actually in it. `thrixel_update_game(game_id=..., listed=false)` ASKS to be taken off; staff answer, and it stays listed until they do. On a game that was never listed this is a 409, so check `thrixel_list_games()` first. The link is unaffected either way. |\n| \"get X featured\" / \"put X in the gallery\" | `thrixel_update_game(game_id=..., listed=true)`. Tell them staff review it, and that the link keeps working regardless. Do not promise a timescale. |\n| \"rename X\" | `thrixel_update_game(game_id=..., title=\"...\")` |\n| \"update X with my changes\" | `thrixel_publish_game(files=..., assets=..., game_id=...)` with the whole updated game. Same URL, and the live version keeps serving until the new one is ready. Pass `controls` and `description` again only if they changed. |\n\nTwo rules for this whole set:\n\n- **Look up the `game_id`; never ask the user for it.** They know their game by its\n  name, and `thrixel_list_games` maps names to ids in one free call. Asking for an\n  id is asking them to do your lookup.\n- **Confirm before unpublishing.** It takes the game offline for everyone\n  immediately, and a link the user has already sent to people stops working. Name\n  the game and its URL and get a yes first. Renaming, relisting and republishing\n  need no confirmation - they are all reversible and none of them break a link.\n"
}

SHA-256 of public snapshot: ca87f34929f8e5405164a717e266a5e3e6d53e03a4168be77351d4f00352d5f8