Skip to content
Development
Skill

/itch-publish

Publish and update a game on itch.io: create the project page and upload builds with the butler CLI (butler push) to named channels. Use for itch.io publishing, butler push, channel naming for Windows/macOS/Linux/HTML5, versioning uploads, or shipping a jam or release build to

From plugin
awesome-gamedev-agent-skills
6.3k77 skills

Claude Code

$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill itch-publish --agent claude-code

SKILL.md

itch-publish.SKILL.md
name: itch-publish
description: >
  Publishes and updates games on itch.io with the butler CLI: butler push to user/game:channel,
  channel platform tags, HTML5 builds, --userversion and CI uploads. Use for "upload to itch", an
  HTML5 game that downloads instead of playing, a blank or 403 web build, or "invalid target". Not
  for Steam (`steam-publish`) or jam scope (`game-jam`).

itch.io Publish (butler)

Get a build onto an itch.io page and keep it updated. The page is created in the browser by the user; every upload goes through **butler**, itch.io's CLI, with one command: `butler push`. butler diffs against the channel's previous build and uploads only what changed. CI and the full flag list live in `references/butler-ci.md`; limits and dated rules are in Version notes.

When to use

  • Creating or updating an itch.io page, installing or logging in to butler, pushing a build,

choosing channel names, versioning uploads, shipping a jam, demo or release build.

  • Project signals: `butler` in scripts or CI, `BUTLER_API_KEY`, a `.itch.toml` manifest.

**Not for:** Steam (use `steam-publish`); jam scope and schedule (use `game-jam`; this skill is only the upload); building or exporting the game (engine skills).

Workflow

1. **The page must exist first.** butler pushes only to an existing page. Ask the user to create it at `itch.io/game/new` and report the page URL. Settings to ask for: *Kind of project* stays **Downloadable** for native builds or becomes **HTML** for a browser game; visibility stays **Draft** (or Restricted, with a password, for testers) until the page is finished, because the first public publish puts it on Most Recent once and never again. 2. **Work out the target.** `<user>/<game>` is the lowercase page address: `finji.itch.io/overland` is `finji/overland`. Pick channel names now (Pattern 2) and reuse them forever. 3. **Install butler.** Locally from `itchio.itch.io/butler` or the itch app; in CI use the pinned, checksum-verified install in the reference. Check with `butler version`. 4. **Prepare a portable build folder:** exactly the files a player runs. Push a folder (or one `.zip` of that folder), never an installer or a pre-compressed pack (Gotchas). 5. **Dry-run the push** and read the file list (Verify, step 1). This needs no login. 6. **Log in.** `butler login` opens a browser, so ask the user to run it and approve. In CI, set `BUTLER_API_KEY` from a secret instead. 7. **Push:** `butler push <dir> <user>/<game>:<channel> --userversion <version>`. The first push uploads everything; later pushes to the same channel upload the diff. 8. **Finish the page.** Ask the user, on *Edit game*, to fix platform tags (tick only platforms the build was run on), tick *This file will be played in the browser* for an HTML channel, answer the **AI generation disclosure**, set adult content under *Metadata → Classification*, and Save. 9. **Update later** by pushing to the same channel. `butler push-preview` shows what will change first.

Patterns

1. Push one channel per platform

# butler push <directory-or-zip> <user>/<game>:<channel>
butler push ./build/windows leafy/my-game:windows --userversion 1.2.0
butler push ./build/mac     leafy/my-game:osx     --userversion 1.2.0
butler push ./build/linux   leafy/my-game:linux   --userversion 1.2.0
butler push ./web           leafy/my-game:html    --userversion 1.2.0  # page Kind = HTML

`--userversion-file build.txt` reads the version from a file instead. Without either flag, itch numbers builds with an auto-incrementing integer, and the update API (reference) has no version to report.

2. Channel names set the initial platform tag

Substring in channel name -> tag:  win / windows -> Windows   mac / osx -> macOS
                                   linux -> Linux             android -> Android
Several platforms in one channel:  butler push ./jar leafy/my-game:win-linux-mac
Convention: lowercase, dash-separated (windows-beta, osx-demo, soundtrack).
No CPU-architecture tag: name the channel (windows-arm64) if you ship several.
Tags are only the first guess; fix them on Edit game.

3. Filtered, hidden and conditional pushes

butler push ./build leafy/my-game:windows --ignore '*.pdb' --ignore '*.dSYM'   # repeatable
butler push ./build leafy/my-game:windows-beta --hidden    # only when CREATING a channel
butler push ./build leafy/my-game:windows --if-changed     # skip an empty patch (CI reruns)
butler status leafy/my-game                                # channels, builds, versions

Verify

Run these yourself and report the result:

1. `butler push <dir> <user>/<game>:<channel> --dry-run` (plus the same `--ignore` flags) lists every file and ends with `Would push <size> (<n> files, ...)`. It needs no credentials. Check that the executable (or `index.html` at the root for HTML) is there and that symbols, editor files and installers are not. For HTML, also check the file count and sizes against the limits in Version notes. 2. `butler validate <dir>` (offline) exits 0. Without a `.itch.toml` it lists the file the itch app would launch; with one, it fails on a parse error or an action whose path is missing. 3. After a real push, `butler status <user>/<game>` shows the channel with the new build and user-version. Processing finishes in the background; the build is already downloadable. 4. Ask the user to open the page logged out (or in a private window), download or play the build, and report that it starts.

Gotchas

  • **Pushing an installer.** itch patches portable builds; an `.exe`/`.msi` installer defeats

patching and the itch app's auto-update, and may need admin rights players lack.

  • **Pre-compressed builds.** A compressed archive, or an archive of archives, makes every patch

huge because a tiny change rewrites the whole blob. Push plain files; butler compresses.

  • **A folder holding only one `.zip`.**
Read more
@gamedev-skills
Ships withawesome-gamedev-agent-skills

<img src="docs/assets/awesome-gamedev-agent-skills-banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.

Stars on GitHub

Momentum

stars in total
6.3k
Star history of gamedev-skills/awesome-gamedev-agent-skills on GitHub, a chart by star-history.com

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc13d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react3d252k
@facebook@facebookInstall Skill

Questions about itch-publish.

Which coding agents can use itch-publish?
itch-publish installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.