X Tutup
Skip to content

Releases: itchio/butler

v15.26.1

26 Feb 19:25

Choose a tag to compare

Version identity bug in v15.25.0 and v15.26.0

v15.25.0 and v15.26.0 were shipped with an incorrect version string: they identified themselves as head instead of their actual version. Butler uses its built-in version to determine which update channel to check: builds marked as head check the development channel, while stable builds check the stable channel. Because v15.25.0 and v15.26.0 incorrectly identified as head, running butler upgrade on either of these versions would switch you to the development line instead of staying on stable releases.

If you are currently on v15.25.0 or v15.26.0, we recommend re-downloading butler from https://broth.itch.zone/butler to ensure you are back on the stable update channel. You can verify your version with butler version, it should show v15.26.1 with a commit hash, not head.

Bug Fixes

  • Fix version string in builds: CI builds were always reporting version as "head" regardless of the git tag. Build scripts now correctly use GitHub Actions native environment variables to inject version, commit hash, and build timestamp into the binary.
  • Fix Wine launch failures: Fixed an issue where launching .exe files through Wine could fail when the {{EXT}} template action couldn't locate the executable path.

v15.26.0

21 Feb 03:35

Choose a tag to compare

This feature release primarily contains updates for butlerd, the part of butler that services the itchio app. CLI updates below.

butlerd (daemon)

New Features

  • Stdio transport mode (--transport stdio) — reads JSON-RPC from stdin, writes to stdout, logs to stderr. No authentication required (inherently secure via parent process pipe). Supports single connection only.
  • Install.GetUploads — fast endpoint returning available uploads for a game (~100ms, no file I/O). Returns game object and filtered upload list.
  • Install.PlanUpload — cancelable planning for a specific upload. Accepts optional id parameter for cancellation via Install.Cancel. Performs network I/O and file inspection.
  • Caves.GetSettings / Caves.SetSettings — per-cave configuration stored as JSON in the database. Settings include sandbox overrides (Sandbox, SandboxType, SandboxNoNetwork, SandboxAllowEnv) and extra launch arguments (ExtraArgs).
  • SandboxOptions in Launch — fine-grained sandbox configuration per launch: Type (auto/bubblewrap/firejail/flatpak/fuji), NoNetwork, AllowEnv.
  • CaveSettings.ExtraArgs — per-cave extra command-line arguments appended after manifest args at launch.

Improvements

  • Hard limits on lazy fetches to prevent excessive resource consumption: collection games capped at 2000 items, owned keys at 5000 items. Warns when limits are reached.
  • Fix quadratic operation for collection and library sync, which could cause butlerd to lock up when synchronizing larger collections
  • Structured logging (slog) for database queries, HTTP requests, and DB migrations. New slogHandler converts slog records to comm's JSON message format. Enable HTTP debug logging with BUTLER_HTTP_DEBUG=1.
  • butlerd.json spec now includes result types, precise enum values (int, bool, string), and @deprecated tags on endpoints and types.
  • Thread-safe cancellation with new MakeCancelable helper on RequestContext. Mutex protection on cancel funcs map.
  • Prefer system-installed firejail over prereqs version when available.

Deprecations

  • Install.Plan — use Install.GetUploads + Install.PlanUpload for cancellation support. Install.Plan still works but internally delegates to the new endpoints.

Bug Fixes

  • Fixed install plan not actually being cancelable (was using wrong context).
  • Prevented non-JSON logging from being sent to stdout when in stdio mode (redirected to stderr).

butler CLI

Improvements

  • Fixed context/goroutine leaks in push, fetch, login, status commands (DefaultCtx now returns a cancel func that must be called).
  • Pointer semantics for CompressionSettings in diff and sign commands.

Bug Fixes

  • Fixed variable shadowing bug in push finalize that could report the wrong error.

Dependency Updates

smaug (sandboxing)

  • New: Bubblewrap Linux sandbox backend with persistent per-game home directory ({InstallFolder}/.itch/home), GPU/audio/display support, PID/UTS namespace isolation, and controller input device access.
  • New: Flatpak-spawn sandbox for running inside Flatpak containers. Auto-detected via /.flatpak-info. Uses flatpak-spawn --sandbox with optional network isolation.
  • New: Centralized SandboxConfig struct with type selector replacing scattered per-platform parameters. Auto-selection priority on Linux: Flatpak-spawn → Bubblewrap → Firejail.
  • New: macOS sandbox policy modes — balanced (strict, default) restricts /dev access; legacy allows broader compatibility for problematic games.
  • New: Rosetta 2 support — x86 games can now run sandboxed on Apple Silicon Macs.
  • Improved: Cryptographically secure Windows sandbox account passwords using crypto/rand.
  • Improved: Unified network control (NoNetwork) across all sandbox backends (bubblewrap: --unshare-net, flatpak-spawn: --no-network, firejail: --net=none, macOS: conditional policy rules).
  • Improved: Centralized environment variable allowlists per platform prevent accidental info leaks.
  • Fixed: Windows fuji sandbox "access denied" error on first launch — ACL permission propagation may not be immediate, so process start now retries on ErrPermission (up to 7 attempts with 1s delay).

screw (file operations)

  • Fixed: macOS memory leak in TrueBaseName — C string from GetCanonicalPath was not being freed.
  • Improved: Rollback error handling now reports both the rollback error and original error together via errors.Join.

wharf (patching)

  • Updated: Regenerated protobuf definitions with modern protobuf toolchain.

hades (database ORM)

  • Breaking: Query logging migrated from headway Consumer to slog.Logger. Context struct now uses Logger *slog.Logger instead of Consumer *state.Consumer.
  • NewContext no longer requires a Consumer argument.

boar (archive extraction)

  • Updated to libc7zip 1.9.0.
  • Added Windows ARM64 (windows-arm64) builds, removed 32-bit Linux (linux-386).

go-itchio (API client)

  • Added slog.Logger support for structured HTTP request logging, used by butler's BUTLER_HTTP_DEBUG flag.

httpkit (HTTP file transport)

  • Made debug logging more granular.

ox (Windows process launching)

  • Fixed Windows game launching (fuji sandbox and simple runner) broken by Go 1.24 os.Process internals change. Replaced unsafe reflection hack with os.FindProcess.
  • Fixed thread handle leak in process launching when SysProcAttr is nil.

lake (protocol buffers)

  • Migrated from github.com/golang/protobuf to google.golang.org/protobuf. Regenerated .pb.go files with modern protoc toolchain. Replaced copystructure deep-clone with proto.Clone.

v15.25.0

06 Feb 07:23

Choose a tag to compare

New Builds

Linux ARM64 (aarch64)

Butler now builds natively for Linux ARM64, and those builds are published to broth.

macOS ARM64 (Apple Silicon) + Universal Binary

Butler now builds natively for macOS ARM64. A universal binary (x86_64 + arm64 via lipo) is also produced and code-signed. The ox dependency was updated to support ARM architecture detection.

Note: we may stop generated universal builds in the future, testing it out to see if it's useful to anyone

Breaking Changes

Linux minimum glibc raised from 2.28 to 2.31

Linux binaries are now built on Debian Bullseye, raising the minimum required glibc from 2.28 to 2.31. Users on older Linux distributions (e.g. Debian Buster) may need to upgrade.

Build & CI/CD

New GitHub Actions Build & Release Workflow

We have migrating building and releasing binaries of butler to GitHub actions. The new workflow includes all new job pipelines for signing and notarizing builds. Builds are published to broth directly from GitHub actions.

Windows executables are now signed with Azure Trusted Signing.

CI Modernization

  • Go version: Upgraded from Go 1.14/1.23 to Go 1.24.0. All CI workflows now use go-version-file: 'go.mod' instead of hardcoding versions.

Helper Makefile

New Makefile with build, install, test, and clean targets for local development convenience.

Dependency Updates

Major dependency upgrades across the board. Many itchio dependencies were bumped to modern Go with enhancements and cleanups.

Dependency Old New Highlights
itchio/arkive 2020 2026-01-29 Proper error handling for password protected zips
itchio/boar 2024-12-12 2026-01-29 Support for libc7zip arm on linux and macOS
itchio/dash 2020 2026-01-28
itchio/go-itchio 2020-08-26 2025-12-29 Includes new OAuth login API methods
itchio/headway 2020 2025-12-29
itchio/httpkit 2020 2025-12-31
itchio/hush 2020 2026-01-23 Updated extensions for naked apps
itchio/ox 2020 2026-02-04 Ability to detect arm architecture from host machine
itchio/savior 2020 2026-01-28
BurntSushi/toml 0.3.1 1.6.0
mitchellh/mapstructure 1.3.2 1.5.0
golang.org/x/crypto 0.31.0 0.47.0
golang.org/x/sync 0.10.0 0.19.0
golang.org/x/sys 0.28.0 0.40.0
golang.org/x/text 0.21.0 0.33.0
golang.org/x/time 2020 0.14.0
klauspost/compress 1.10.9 1.18.3
stretchr/testify 1.6.1 1.11.1

Documentation

Migrated from gitbook to honkit for documentation building. Docs deployed from master into GitHub pages.

Expanded Installation Guide

The docs/installing.md was completely rewritten with:

  • Platform-specific step-by-step installation instructions (Windows, Linux, macOS)
  • Verification steps for each platform
  • Clarified broth URLs as permanent (vs expiring itch.io download links)
  • New appendix: "Using butler from the itch app" with paths for each platform and how to find the current version

New Troubleshooting Page

Added docs/troubleshooting.md covering common issues: PATH errors, incorrect directory paths, spaces in file paths, invalid target errors, authentication problems, project page requirements, and firewall/antivirus issues.

butlerd

OAuth Login with PKCE Support

New Profile.LoginWithOAuthCode butlerd endpoint that allows the itch.io desktop app to authenticate users via OAuth authorization code exchange with PKCE. This accepts an authorization code, PKCE code verifier, redirect URI, and client ID — and returns the user profile along with a website cookie. The OAuth client ID is no longer hardcoded; it is provided as a parameter by the caller.

Unlike the existing LoginWithPassword and LoginWithAPIKey endpoints, the OAuth result also returns a Cookie map, enabling the desktop app to synchronize website login state after authentication.

butlerd NPM Package Rename

The butlerd npm package has moved to https://www.npmjs.com/package/@itchio/butlerd

The generous support path changed from butlerd/lib/support to @itchio/butlerd/lib/support.

butlerd Spec Updates

  • Added Profile.LoginWithOAuthCode request to butlerd.json spec
  • Added metadata field (type { [key: string]: any }) to Candidate type in spec

v15.24.0

13 Dec 01:16

Choose a tag to compare

  • Fix bug where numbered releases didn't have the version number baked in the executable (only affected v15.23.0)
  • Build across all platforms with most recent version of go (1.23.4)
  • Update some go dependencies
  • Fix outdated .itch.ovh domain in utility library (boar)

v15.23.0

13 Dec 01:13

Choose a tag to compare

  • Remove all references to .itch.ovh domain. Only the .itch.zone domain should be used.

v15.21.0

12 May 00:27

Choose a tag to compare

  • Bump up default context deadline to 15 seconds to help with slower connections not allowing builds to be pushed
  • Add flag "--context-timeout" for setting the timeout to any value
  • Butler is now signed with itch corp. certificate on macOS and Windows

v1.0.1

22 Oct 10:41

Choose a tag to compare

Because of a flawed resume check, the unzip command in v1.0.0 skipped over the first file of the zip archive. v1.0.1 fixes this.

v1.0.0

22 Oct 10:40

Choose a tag to compare

v1.0.0 introduces many new concepts in butler, @elisee asked me what was new so, here it goes:

Manifests (intro)

One big feature is dividing containers in blocks. Up till then we had "archives" (containers compressed as a .zip file), "signatures" (MD5 hashes of <=16KB blocks), and "patches" (list of instructions).

This release introduces a new file format, "manifests", which contains SHAKE256 32-bit hashes of 4MB blocks. They're supported by the "ls" and "file" command, and most of the code writing or reading it is available in the blockpool package of wharf.

There are no new user-facing commands in butler allowing the creation of manifests, this will come in later releases, more details in the later sections.

Healing

Another big feature is healing: given a signature and a heal source, the verify command can now redownload parts of files that were corrupted. It'll also restore missing directories and missing/corrupted symlinks.

Note that when --heal is used, the exit code behavior of verify is modified: it'll now return 0 if it healed everything successfully, whereas without --heal it would've returned 1.

Plans: The apply command will also get a --heal parameter, so that if patch application fails for a reason or another, it'll be able to heal the result, instead of forcing the butler user to fall back to a full re-download.

itchfs

For healing to be interesting, the heal source must be remote — and yet verify's --heal parameter accepts a local path.

However, butler now accepts, for all path arguments, itchfs:///XXX urls. All valid URLs can be devised from the sources.go file of go-itchio.

Note that the API key is passed as a query parameter.

  • Example URL: itchfs:///upload/3/download?api_key=XXX

(Yes, that's three slashes - the third is the root, much like file:///etc/hosts)

This means, when an itchfs is passed to the --heal parameter of the verify command, butler will only download the parts of the remote .zip file it needs to heal the local container. Due to the structure of the .zip format, this is relatively efficient:

  • First request establishes the size of the file
  • Second request to seek to the end and read the Central directory
  • Then, reading from any files is just an additional request. If files are read in-order, the same request is re-used throughout.

The itch.io-specific parts are in go-itchio, the io.ReaderAt interface for remote files can be found in httpkit.

Note that the remote server must support the Range HTTP header and respond with a 206 partial content, otherwise an error is thrown.

itchfs is implemented in a pluggable way, which means other vendors are welcome to come up with their own URL schemes and build a version of butler that supports them (for example, for building their own launcher/updater system).

Resumable unzip

The unzip command now accepts a --resume-file parameter. With itchfs URLs, it can be used to download and extract a file at the same time (and resume at the beginning of the last file it was working on, using the resume file's info).

BPS / ETA

All progress-emitting commands now output eta (estimated time remaining, in seconds) in json output mode. They also now emit progress (floating number between 0.0 and 1.0) in addition to percent (floating number between 0.0 and 100.0, kept for backwards compatibility for now).

A few commands (like unzip, cp) are also getting bps (bytes per second processed). This is useful to show download/processing speed graphs:

screen shot 2016-10-11 at 19 58 37

Manifests (plans)

The big idea for manifests is for them to be usable as a heal source for verify, apply, and as an argument to a new command unsplit. Since manifests are only a list of hashes, access control is left as an exercise to the user — for itch.io, it'll be implemented in the form of download sessions tied to a certain set of blocks, expiring, and started with a valid itch.io API key, which allows for monitoring of abuse and prevents Dropshipping blocks.

v0.1.4

23 Oct 12:57

Choose a tag to compare

v0.1.4 Pre-release
Pre-release

Better release support on travis+S3

v0.1.3

23 Oct 12:32

Choose a tag to compare

v0.1.3 Pre-release
Pre-release

Auto S3 deployment fiddling

X Tutup