Package a playtest
scripts/package_game.py packages a saved project with a release build of the player for a local
playtest. It builds optimised binaries, verifies every asset against its recorded hash, produces a
macOS app on Macs, and writes a release manifest and checksums.
Build a package
Section titled “Build a package”You need Python 3.12 and the native build prerequisites. On macOS this includes the Xcode Command
Line Tools, which provide codesign. Run from the engine repository root:
python3 scripts/package_game.py \ --project path/to/my-game/project.feather.json \ --output dist/my-game-playtest- The script builds
feather-playerandfeather-cliwithcargo build --release --locked --no-default-features, unless you supply existing binaries. - It stages the project and only the models, textures, sounds and fonts it declares.
- It checks each file’s size, SHA-256 name and file type, then validates the staged project with
feather-cliandproject.validate. - It writes the package and prints the output folder.
Packaging never launches the game, and it never overwrites an existing output: an existing folder,
even an empty one, is refused. Without --output, a uniquely named folder is created under dist/.
On failure, the staging folder is removed.
Choose the asset source
Section titled “Choose the asset source”| Priority | Source |
|---|---|
| 1 | --assets DIR, if given. It is authoritative |
| 2 | The assets/ folder beside the project, if it exists |
| 3 | --cache-assets DIR, an absolute FEATHER_ASSET_ROOT, or the per-user asset cache |
Point these options at the folder that contains imported/, not at imported/ itself. An incomplete
or corrupt assets/ folder fails verification; it is not filled in from another source.
Package contents
Section titled “Package contents”On macOS the output folder contains <name>.app:
<name>.app/Contents/Info.plist<name>.app/Contents/MacOS/feather-player<name>.app/Contents/Resources/game/project.feather.json<name>.app/Contents/Resources/game/assets/imported/...On other platforms, feather-player (or feather-player.exe), project.feather.json and assets/
sit together in the output folder.
Every package also contains:
| File | Purpose |
|---|---|
README.txt |
Launch instructions |
release-manifest.json |
Release metadata and file hashes |
SHA256SUMS |
Checksums for the whole package |
licenses/Inter-OFL.txt |
Licence of the font embedded in the player |
PLAYTEST.txt |
Copied from the project folder when present |
licenses/project/ |
The project’s own licenses/*.txt notices, when present |
These records sit outside the app bundle, so they can be written after signing. To verify a package,
run shasum -a 256 -c SHA256SUMS on macOS or sha256sum -c SHA256SUMS on Linux from inside the
output folder.
Options
Section titled “Options”| Option | Description |
|---|---|
--project FILE |
The project to package |
--assets DIR |
Authoritative asset folder |
--cache-assets DIR |
Fallback asset folder, used only if the project has no sibling assets/ |
--output DIR |
A new output folder |
--player FILE, --cli FILE |
Reuse existing binaries instead of building them |
--name |
Package and app name; defaults to the project name |
--version |
Version as x.y.z; defaults to the engine’s Cargo version |
--bundle-id |
macOS bundle identifier. Keep it stable between builds of the same game |
--build-number |
macOS build number; default 1 |
--sign-identity |
macOS signing identity. - (default) signs ad hoc; pass a Developer ID Application identity to use it |
--target-platform |
macos, linux or windows. A different platform requires a matching --player; there is no cross-compilation |
When you pass your own binaries, you are responsible for their source revision, release flags and architecture.
Signing
Section titled “Signing”Signing runs offline with --timestamp=none. A named Developer ID identity also enables the hardened
runtime:
python3 scripts/package_game.py \ --project path/to/my-game/project.feather.json \ --sign-identity 'Developer ID Application: Your Name (TEAMID)'Neither mode notarises the app. Review content licences, notices and platform requirements before sharing a package beyond your intended testers.
Player data
Section titled “Player data”The packaged game is read-only. Settings, key bindings, language, saves and crash reports are written to a per-game folder in the Feather data folder; see Saves and settings. Keep the project name stable between builds, because the folder name is derived from it.
Package the editor
Section titled “Package the editor”To package the editor itself as a macOS app, use scripts/package_macos.py; see
Install. The app registers the .feather project type, so
double-clicking a project in Finder opens it in the editor.
Automate it
Section titled “Automate it”The packaging tests use temporary fixtures and need neither licensed content nor a Rust build:
python3 -m unittest discover -s scripts/tests -p 'test_package_game.py'