A scaffolder to start the development of Playdate apps and games written in Swift, built on the playdate-kit bindings, for both the Playdate Simulator and real Playdate hardware.
The quickest way — nothing to clone, the init script fetches the template by itself:
curl -fsSL https://raw.githubusercontent.com/rock-n-code/playdate/main/init.sh | sh -s -- MyGameOr from a checkout of the template repository:
git clone https://github.com/rock-n-code/playdate.git
playdate/init.sh MyGame # creates the game ./MyGame next to the checkout
playdate/init.sh MyGame ~/Projects/MyGame # creates a game with explicit destination
playdate/init.sh MyApp --type app --author "John Doe" # creates the app ./MyApp with specific optionsThe initialization script accepts the following arguments and options:
./init.sh <AppName> [destination-dir] [options]
| Argument | Meaning | Default |
|---|---|---|
AppName |
The game's name; it becomes the Swift module name, so letters and digits only, starting with a letter | required |
destination-dir |
Where the project is created | ../<AppName> beside the checkout, or ./<AppName> when run via curl |
--type <app|game> |
What kind of project this is; names the root class App or Game accordingly |
game |
--display-name <name> |
Launcher name in pdxinfo |
AppName |
--bundle-id <id> |
Reverse-DNS identifier in pdxinfo |
com.example.<appname> |
--author <name> |
Author in pdxinfo |
git config user.name |
--no-git |
Skip git init and the initial commit |
new projects start as a git repository |
The generated project has the placeholder name substituted everywhere it matters: the package and target names, the sources folder, the pdxinfo metadata, and the build tooling.
⛔️ A few names are refused because they collide with modules the project depends on:
PlaydateKit,CPlaydate, andSwift.
- Copies the template's git-tracked files (so build artifacts and editor droppings never end up in a new project); when run standalone, it first fetches the template into a temporary clone. The script itself is not copied.
- Renames the
Templateplaceholder to your project's name across the sources, manifest, and build tooling — and, with--type app, renames theGameclass and file toApp. - Fills in
pdxinfowith the display name, bundle identifier, and author. - Replaces this README with a fresh one titled after the app/game.
- Initializes a git repository with an initial commit (unless
--no-git).
If anything fails or the run is interrupted, the half-created destination is removed — you never end up with a broken project.
cd MyGame
make build # first build: resolves playdate-kit, packages MyGame.pdx
open -a "$HOME/Developer/PlaydateSDK/bin/Playdate Simulator.app" MyGame.pdxTo work in Xcode, open the project folder (or its Package.swift) — editing, code completion, and host builds all work there, while .pdx packaging and device builds go through make in the terminal.
This scaffolder is macOS-only: the build tooling depends on Xcode's toolchain discovery (xcrun, plutil) and BSD utilities. The Playdate SDK itself supports other platforms, but this script does not unfortunately.
For Simulator builds:
- Playdate SDK 3.1.1 or later, installed at
~/Developer/PlaydateSDKor pointed to byPLAYDATE_SDK_PATH - Swift 6.3 tools or later (recent Xcode is fine)
- The
playdatepkg-config module, generated once per machine by runningmake setupin a playdate-kit checkout
Additionally, for device builds:
- A swift.org development snapshot toolchain, since Xcode's toolchain lacks the Embedded Swift stdlib for
armv7em-none-none-eabi. The easiest route is to install this snapshot toolchain with Swiftly:swiftly install main-snapshot - The Arm GNU toolchain (
arm-none-eabi-gcc) on yourPATH
Package.swift SwiftPM manifest; the product must stay named "pdex"
Sources/
Template/
EventHandler.swift @_cdecl("eventHandler") C entry point
Game.swift minimal game loop — build from here
(named App.swift in projects created with --type app)
Source/
pdxinfo bundle metadata (name, bundleID, version)
init.sh creates a renamed project from this template
Makefile provide tasks to assist in the development lifecycle of an app or game
make build
open -a "$HOME/Developer/PlaydateSDK/bin/Playdate Simulator.app" Template.pdxThe build target compiles the game as pdex.dylib with SwiftPM, drops it into Source/ next to pdxinfo, and packages Template.pdx with the SDK's pdc. It only needs Xcode's Swift and the Playdate SDK — none of the device prerequisites above.
make all # device binary + simulator dylib in one pdx
make device # device binary only
make simulator # simulator dylib only
make run # simulator flavor, then open in the Playdate Simulator
make clean # remove build folders, the pdx, and copied binariesBare make (or make help) prints this list of targets without building anything.
The Makefile cross-compiles the game and the playdate-kit wrapper with Embedded Swift for the device's ARM Cortex-M7, reusing the swift.mk build logic from the SwiftPM checkout of playdate-kit (so it always matches the pinned dependency version). Sideload the resulting Template.pdx via the Playdate Simulator (Device ▸ Upload Game to Device) or the SDK's pdutil.
If make picks the wrong Swift toolchain, select one explicitly, e.g.:
TOOLCHAINS=$(plutil -extract CFBundleIdentifier raw -o - \
~/Library/Developer/Toolchains/swift-latest.xctoolchain/Info.plist) makeThe Playdate firmware (and the Simulator) loads the game and calls the C entry point exported in EventHandler.swift with lifecycle events. On initialize, the handler stores the Playdate API pointer — this must happen before any other PlaydateKit call — and hands control to Game.shared.start() (or App in app-type projects), which registers the update callback. From then on, update() runs once per frame: read input, advance state, draw. The playdate-kit README documents the API surface — System, Display, Graphics, Sprite, Sound, File, and other available types.
Everything in Source/ is packaged into the pdx by the SDK's pdc compiler, next to the compiled game code. Put images, audio, and fonts there and load them by path with the Graphics/Sound APIs. pdc converts known formats on the way in (for example .png to .pdi); consult the Playdate SDK docs for the supported formats.
Run make outdated to see whether newer versions are available within the manifest's ranges, and make update to move to them. For a new major version, bump the range in Package.swift first. The device build reuses swift.mk from the resolved checkout, so its build logic follows the pinned version automatically — no other files to touch.
Playdate SDK not foundorno pdc at "…/bin"(frommake) — install the Playdate SDK or pointPLAYDATE_SDK_PATHat it.swift buildcannot findCPlaydate/pd_api.h— theplaydatepkg-config module is missing; runmake setupin a playdate-kit checkout once per machine.Swift toolchain not found; set ENV value TOOLCHAINS— device builds need a swift.org snapshot toolchain:swiftly install main-snapshot. If the wrong toolchain gets picked, see theTOOLCHAINSoverride under Building.arm-none-eabi C headers not found— install the Arm GNU toolchain and make surearm-none-eabi-gccis onPATH.- First
makein a fresh project printsResolving Swift package dependencies…— that's normal; the checkout of playdate-kit is created on demand. - The Simulator shows a blank screen — make sure the update callback returns
true, otherwise the display is not redrawn.
⚠️ The source of the app/game code must stay within the Embedded Swift subset — no Foundation, no reflection, no untyped throws — or device builds will fail even though the simulator build succeeds.