Skip to main content
multiplayer-publish is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Ship a hosted Summer multiplayer game: the bundle, server preset, pre-upload checks, a new Build.

When your agent uses it

  • Publishing a hosted Summer multiplayer game online so other players can join it
  • Making the summer.games bundle of a hosted game: client.pck, server.pck and the Linux server preset
  • A summer.games export error mentions summer.build.json, WorldDefinitions, the server preset, the composition or the source graph

Install

summer setup installs every skill for your agent. To add only this one:
Swap claude-code for your agent, such as codex or cursor. See Skills for every option.

The skill

Step 5 of the multiplayer sequence. It assumes the layout from multiplayer-project: summer.build.json, world.json, runtime-manifest.json, source-domains.json, and the client/, authority/ and network/ folders.

1. What gets built

Project > Export, preset summer.games, Export Project to a .zip gives one file, the bundle, which becomes one Build: Players get client.pck on iOS, macOS or Windows (targetPlatforms in summer.build.json). Summer runs server.pck on Linux for every World.

2. The two export presets

Every project has a built-in summer.games preset. The server needs a second, Linux dedicated-server preset, named exactly as server.exportPreset in summer.build.json. export_presets.cfg:
To make the same in the Export dialog:
  • summer.games: tick the platforms the game supports; leave encryption off. It needs no exclude filters, because the source graph decides what stays out of client.pck.
  • Server: Add… > Linux, named exactly as server.exportPreset. Resources: Export Mode Export as dedicated server, and exclude the client folder (client/*). Features: Custom summer_authority.
Both presets must include the composition; each must include its entry scene. The summer_authority custom feature is what makes the server start the authority. Summer starts server.pck with no scene argument, so the pack’s own main scene decides what runs: run/main_scene.summer_authority from project.godot (multiplayer-project), which applies only to a pack whose preset carries that feature. Without it, the server runs the client’s main scene, usually the title. It never restores the World or reports ready, and every online join fails with world_start_timeout. Local Play and the upload checks name the scene themselves, so they can’t catch this; step 4d can. Textures: iOS and macOS read ETC2/ASTC (textures/vram_compression/import_etc2_astc=true in project.godot), and Windows reads S3TC/BPTC (import_s3tc_bptc=true). Enable the ones for the platforms you tick. The exporter’s Fix Import button does it.

3. Export

In the editor: Project > Export, select summer.games, Export Project, save as build/<game>.summer.zip. Or from a terminal (<summer> is the Summer editor executable):
A good export ends like this:
Check that server.pck and your config/ files are listed, and that the “Left N server-only files” count covers your authority/ files. The Server: … mainScene … line names the scene the Build declares, not the scene the pack will start; step 4d checks that. The Exported by Summer line must name a released Summer: export with the released editor from the download page, never a development build, and export again after you update Summer. Players’ apps run the packs on the released Summer of that version; step 4e checks it. The Summer Games apps for iPhone and Android start only exports on their own MAJOR.MINOR, so export with the current Summer release (release-readiness check 9). Every result message and every export error, with its fix, is in export-errors.md.

4. Check before uploading

Do all five. Each catches problems the export doesn’t. Run them on the .zip you will upload, not on a pack exported separately with the server preset (--export-pack): that pack differs from the bundle’s server.pck, for example it keeps gameId, and can pass where the upload fails. a. Local Play passes (multiplayer-testing): every process has script_errors 0, there’s no cannot attach, and your ready lines appear. b. The source graph is clean. Save this script outside the project, for example as ~/check_graph.gd:
Both lines must say ok=true. SUMMER_COMPOSITION_DOMAIN_LEAK means a client file loads a server file; move the shared part into network/. SUMMER_COMPOSITION_DYNAMIC_PATH_UNDECLARED flags any call whose name ends in load( without a string literal inside. That includes request.get_payload(): read request.payload instead. For a file that really loads a computed path, add a { "from": "<file>", "to": "<loaded file>" } entry to dependencies in source-domains.json. c. Both packs load the way Summer loads them. In a scratch folder outside the project:
Paths must be absolute. Pass: both reports say "sceneLoaded": true, and their compositionManifest objects are identical. On failure the probe writes rejection.json; its codes are in export-errors.md. The probe names the scene to load, so it does not show which scene the server starts on its own. d. The server pack starts the authority scene. Start the bundle’s server.pck the way Summer does, with no scene argument, and stop it after a few seconds:
The first Completed load for: 'res://….tscn' line must be the authority scene (res://authority/main.tscn here). If it is the client or title scene, add summer_authority to the server preset’s custom features and export again. Later lines may complain that there is no hosted World; that is expected locally. e. The client compiles on the released Summer. Run the bundle’s client.pck with the released Summer of the version the export names (see release-readiness check 7 for how to confirm the stamp), and fail on any compile error:
The grep must print nothing; the run itself exits normally even when a script fails. A failure here, such as Static function "party_queue()" not found, means the scripts use an API the released version lacks, usually because a development build made the export. Every player would see an empty window. Re-export with the current Summer release.

5. Upload the Build

  1. The game must exist in Summer Studio, and gameId in summer.build.json must be its id. The export leaves gameId out of the bundle, and the game code calls Summer.initialize() with no ID: a literal or fallback ID fails hosted with game_identity_mismatch.
  2. Open the game’s Builds page: studio.open with target game, gameId and section builds, or summerengine.com → Studio → your game → Builds.
  3. Upload the .zip as a new Build. Summer checks it again: unknown fields, queue rules, both packs, and the composition match. From an agent: summer_export_game, then store.upload_file with gameId and clientVersion; it asks for confirmation first and needs summer login --store. If the store refuses this machine’s sign-in, upload in Studio.
  4. Release the Build to an environment (store.release releases the Build the owner approved with store.publish). Its queues go live there, and clients join them with Summer.client.join(SummerJoinTarget.queue(...)). The code is the same as in Local Play.
For a client-only fix to an existing Build, export to a .pck path instead of .zip. That writes client.pck alone.

6. Join it for real

Right after the Build is released, open the game in a Summer Games app, join online and play until you are in the game, before players hear about the update. A wrong Game ID only fails under a real hosted launch, so nothing before this step catches it. Keep playing, signed in, for at least 3 minutes: the game must not close and the player must stay signed in (release-readiness check 10). An agent can’t do this; ask the user and record the result. The whole list of checks before a release is release-readiness, and the creator docs have it at https://docs.summerengine.com/publishing/release-readiness.

When online joins fail

Every join ends in world_start_timeout, but Local Play works:
  1. The server starts the wrong scene: run step 4d.
  2. The game passes a fixed Game ID to Summer.initialize: pass none.
Then export, upload and release a new Build, and join again. An empty game server log is not proof that the server hung: a release server holds back what the game prints until it exits when it isn’t attached to a terminal. Use step 4d to see which scene runs.

Checklist

  • summer.build.json: gameId, targetPlatforms, server.exportPreset, every WorldDefinition selected by a queue.
  • world.json: every field from multiplayer-project, including network_compositions and source_graph.
  • Two presets: summer.games (platforms ticked, no encryption) and the Linux dedicated server named in server.exportPreset.
  • The export ends with Publish uploads this one file as a new Build.
  • The analyzer prints ok=true twice.
  • Both probes load their scene, with identical composition manifests.
  • The bundle’s server.pck, run with no scene, loads the authority scene first.
  • Exported by Summer names a released Summer, and the bundle’s client.pck run on that release prints no SCRIPT ERROR, Parse Error or Failed to load script.
  • Every Summer.initialize call passes no Game ID.
  • After release: a real online join reaches the game, and a signed-in player keeps playing for 3 minutes (release-readiness checks 2 and 10).
  • Local Play passed with the same project.

Common mistakes

From a shell

No Summer MCP tools in this session? Run each one as a command; when summer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.

Files in this skill

  • multiplayer: Start here for Summer multiplayer: how authority, clients, Worlds and Sessions fit, and what comes next.
  • multiplayer-project: Set up a Summer multiplayer project: entry scenes, World and queue files, joining, a first Local Play.
  • multiplayer-testing: Test a Summer multiplayer game with Local Play: several players, bad network, bots, a passing run.
  • release-readiness: Before releasing a Summer game version, prove players can play it: server, online join, progress, files.

Source: library/skills/multiplayer-publish/SKILL.md, rendered from summer-engine@4.3.0 on npm.