Remixing games

Every published game is readable, so a new game rarely starts from an empty tree. Point copy_files at another game's path (/games/<id>/source/**) to take its whole tree, a subtree, or one file, then adapt. Covers the path grammar, when to bulk-copy versus borrow one idea, what you can see (your own games live, everyone else's at their published version), keeping the comments you inherit, and crediting what you reuse with inspiredBy.

Making a game from scratch should almost never be the first move. Every published game on the site is readable through the same file tools you use on your own — so "snakes and ladders, but with the hidden-information mechanic from The Sommelier" is a real instruction, not a wish. Start from what already works and spend your effort on what is new.

Paths

Three forms, one grammar:

frontend/Meter.tsx                                   this game
/games/k3Pz9Q/source/frontend/Meter.tsx              a game on this site
https://host/games/k3Pz9Q/source/frontend/Meter.tsx  a game on another host

An absolute path is the URL of the public source endpoint — the same string works in a browser. Drop the trailing /<file> and it names the game's whole tree.

list_files, read_file and copy_files accept all three forms. Writes — write_file, delete_file, and copy_files's destination — are relative only: your working copy is the only tree you can change.

A directory path narrows a listing to that subtree — list_files({ path: "frontend" }), or list_files({ path: "/games/k3Pz9Q/source/frontend" }) for someone else's. delete_file takes a directory (frontend/) or a glob to remove a whole set at once.

What you can see: your own games as they stand right now (uncommitted work included), and everyone else's at their published version only. Never anyone's conversation history or unpublished drafts. If a game reads as out of date, its author simply hasn't published since.

Copy the tree, or borrow an idea

Bulk-copy when the other game is the starting shape of this one — a variant, a re-skin, a sequel, "the same but for two players". Take the whole tree and edit down; deleting what you don't need is far cheaper than rebuilding what you do.

copy_files({ from: "/games/k3Pz9Q/source/**", to: "." })

Borrow when you want one part of it — a frontend, a mechanic, a prompt. Copy just that part, or read it and write your own version informed by it.

copy_files({ from: "/games/k3Pz9Q/source/frontend/**", to: "frontend/" })
copy_files({ from: "/games/k3Pz9Q/source/tension.ts", to: "pacing.ts" })
copy_files({ from: "/games/k3Pz9Q/source/assets/Narrator Portrait", to: "assets/Narrator" })

Read before you adapt. list_files the game, read_file the parts you took. Copied code you haven't read is code you can't change safely — and its comments are where the previous author recorded what they learned.

copy_files({ from, to })

  • from is one file or a glob (* and ? within a path segment, ** across segments).
  • One file: to is its new path — or a directory if it ends in /.
  • A glob: to is a directory, and each match keeps the path below the glob's fixed prefix (frontend/**to/…). . is the game root.
  • Assets are files like any other: assets/<name> copies across too, image bindings included. An image asset must land under assets/.

Everything is read before anything is written, so a copy that can't complete changes nothing.

Assets are files

Assets live in the same tree as source, under assets/<name>, so the file tools are all you need for them — the four asset-specific tools are gone:

  • list_assetslist_files; assets appear in the tree under assets/.
  • read_text_assetread_file("assets/<name>").
  • upsert_text_assetwrite_file("assets/<name>", …). A fresh assets/<name> write makes a text asset — a path carries no type.
  • delete_assetdelete_file("assets/<name>").

Images keep their own tools, because bytes are bound rather than written: create_image_asset, set_image_asset and generate_image are unchanged. write_file onto a name an image is already bound to is refused.

If you reach this platform over MCP, re-list the tools — a client still holding the old list will call tools that no longer exist.

Keep the comments; write your own

The comments in a game are its accumulated learnings — why a number is what it is, which prompt phrasing the model kept ignoring, what was tried and abandoned. Preserve them when you reuse a snippet. Deleting them throws away the most valuable part of what you copied.

Then add yours, for whoever remixes this game next. Record what the code alone doesn't say.

Credit what you reuse

Attribution is metadata you maintain, like the title and thumbnail — the inspiredBy list on update_game_details:

update_game_details({ inspiredBy: [
  { game: "/games/k3Pz9Q", role: "remixed", note: "took its meter and tick loop" },
  { game: "https://games.example/games/fgn001", role: "inspired" },
] })
  • game — a game's page URL, a /games/<id> path, or any /source path of one; another host's full URL works the same way. The server resolves it and records where that game came from too, so a chain of remixes stays visible.
  • roleremixed when you copied code or assets, inspired when you took only the idea.
  • note — your own reason for the credit. Stored for the maintainer, never shown to players.

Two things to remember: the list replaces whatever is stored (read read_game_details first and include the credits already there), and one unusable link rejects the whole call, naming it. Players see the credits as an "Inspired by" row on the game's page; the game's own author can edit the list in Details.

Crediting is the norm here rather than a formality — published means remixable, and the same courtesy comes back the other way when someone builds on yours.