No description
Find a file
2026-08-07 22:19:51 -03:00
assets Initial commit 2026-08-05 17:27:43 -03:00
core Hide games with no platform info while the platform filter is on (v0.1.10) 2026-08-07 22:19:51 -03:00
.gitignore Add option to filter games not available on the current platform 2026-08-07 18:41:39 -03:00
export_presets.cfg Initial commit 2026-08-05 17:27:43 -03:00
LICENSE Initial commit 2026-08-05 17:27:43 -03:00
Makefile Initial commit 2026-08-05 17:27:43 -03:00
plugin.gd Initial commit 2026-08-05 17:27:43 -03:00
plugin.json Hide games with no platform info while the platform filter is on (v0.1.10) 2026-08-07 22:19:51 -03:00
README.md Initial commit 2026-08-05 17:27:43 -03:00

OpenGamepadUI-itch

An itch.io library plugin for OpenGamepadUI, built against itch's official butlerd JSON-RPC launcher daemon (the same integration path the official itch.io app uses under the hood) rather than screen-scraping the itch desktop app.

Owned games, install state, install/update/uninstall, and launching are all driven through butlerd. This plugin spawns butler daemon --json ... itself, so the itch.io desktop app doesn't need to be installed at all — only a butler binary, which this plugin downloads automatically on first run from itch's own broth distribution channel.

Setup

  1. Build and install the plugin (see below).
  2. Generate an API key at https://itch.io/user/settings/api-keys.
  3. Open the plugin's settings screen in OpenGamepadUI and paste it in.

API key login was chosen over the OAuth + PKCE flow butlerd also supports, because OAuth requires registering a redirect URI / custom URL scheme with itch.io for a specific app, which doesn't make sense for a self-built, unpublished plugin. If you're distributing this plugin publicly, switching to OAuth is worth doing — see Profile.LoginWithOAuthCode in the butlerd launcher guide.

Requirements

See the OpenGamepadUI requirements. This plugin additionally needs unzip on the host (used to unpack the downloaded butler binary).

Building

Same as any other OpenGamepadUI plugin:

make help
make build
make install

Known limitations / good next steps

This was put together from butlerd's public spec rather than against a running instance, so a few corners are simplifications rather than the "real" solution. If you pick this up:

  • Launch target discovery. butlerd's Launch call is the "correct" way to start a game (it handles prerequisites, manifest actions, sandboxing, etc.), but OpenGamepadUI's library items launch via a plain command + args OS exec, not an RPC call. This plugin currently side-steps that by scanning each installed game's folder for an executable file and pointing command directly at it (library_itch.gd::_find_executable). That works for straightforward native builds but skips prerequisite installation and manifest-declared launch actions. Parsing .itch/receipt.json.gz in the install folder would give the authoritative answer.
  • Field names. The JSON-RPC field names used in itch_client.gd follow butlerd's documented camelCase convention, cross-checked against the butlerd Go package docs for the calls that matter most (Install.Queue/Install.Perform, Uninstall.Perform). A couple of the less-central ones (Launch, Profile.LoginWithAPIKey, Fetch.ProfileOwnedKeys) were written from the documented naming convention rather than a byte-for-byte spec check — worth diffing against your butler's actual behavior (run with --log to see the raw JSON-RPC traffic) if a call comes back with an unexpected error shape.
  • Install location picker. _ensure_install_location() silently picks the first existing install location, or creates one under the plugin's own data directory. No UI for choosing/managing install locations yet.
  • Settings screen. Uses plain Godot Control nodes rather than OpenGamepadUI's themed widget set (the one the built-in Steam plugin's settings scene uses), since this was written without editor access to those theme resources.
  • has_update() always returns false — wiring up CheckUpdate (and periodic background polling) is a natural next step.
  • No progress→UI wiring. install_progressed is re-emitted from raw butlerd notifications but not yet mapped back to a LibraryLaunchItem through LibraryManager (see the TODO in library_itch.gd).

How it fits together

plugin.gd            entrypoint; wires client + library + settings menu
core/itch_client.gd   spawns butlerd, speaks JSON-RPC 2.0 over TCP to it
core/library_itch.gd  extends Library; turns butlerd data into LibraryLaunchItems
core/itch_settings.*  API key entry screen