The Spacetile field guide

Setup

Building, signing, permissions, macOS settings, developer commands and limits.

On this page

Build and run

app/scripts/bundle.sh
open app/build/Spacetile.app

app/scripts/bundle.sh does five things:

  1. Builds the release binary.
  2. Wraps it in app/build/Spacetile.app, stamped with a build number from the date and time.
  3. Compiles the app icon, app/Resources/AppIcon.icon (an Icon Composer file; open it in Icon Composer to edit), with actool.
  4. Generates the App Intents metadata that the Focus filter needs. Xcode normally does this; the script runs Apple’s processor on SwiftPM’s output.
  5. Signs the app with the first “Apple Development” identity in your keychain.

That signature ties the Accessibility permission to the certificate, so it survives rebuilds. Check it with codesign -d -r- app/build/Spacetile.app: it should show a certificate requirement, not a cdhash. If signing fails with “unable to build chain”, add Apple’s WWDR G3 intermediate certificate to the login keychain.

Run the tests for the tiling logic with swift test --package-path app.

Permissions

  • Accessibility (System Settings → Privacy & Security → Accessibility). Needed to see, move, resize and focus other apps’ windows, for the mouse event tap, and for instant Space switching. The Welcome window asks for it on first launch, then checks your macOS settings and offers another window manager’s shortcuts to start from (see Commands), and Spacetile starts within a second of it being granted. If it’s turned off while Spacetile runs, tiling pauses, the menu-bar item shows ⚠︎ with a Grant Accessibility… row, and Spacetile relaunches itself once it’s back on.
  • Screen Recording (optional; System Settings → Privacy & Security → Screen & System Audio Recording). Only for Settings → General → Show window previews, which draws windows’ content in the mini-map and profile editor. Turning the setting on asks for it. Without it, or with the setting off, windows show their app’s icon and Spacetile never reads their content. Pictures stay in memory and are never saved.
  • Open at login is a toggle in Settings → General.

macOS settings

Settings → Setup checks these and links to each one:

Setting Needed Why
Automatically rearrange Spaces based on most recent use Off Otherwise Space numbers shuffle
Stage Manager Off It moves windows itself
Drag windows to screen edges to tile Off Its preview competes with Spacetile’s drop zones. The rest of macOS tiling works with Spacetile (see macOS tiling)
Trackpad swipe between full-screen apps On macOS 27 only accepts instant switching with this gesture enabled
More than one Space Suggested Spacetile can’t create Spaces; add them in Mission Control (⌃↑, then +)

“When switching to an application, switch to a Space with open windows” can stay however you like it. With it on, arriving on an empty Desktop makes macOS activate another app and follow it to its Space. Spacetile switches back when its own switch bounces like this; a trackpad swipe or ⌃→ to an empty Desktop can still bounce.

Developer commands

app/scripts/spacetile-ctl sends any command from Commands to the running app, like the app binary does for other key binders. It also takes these:

Command What it does
frames Prints the windows on the current Space with their frames

app/scripts/fullscreen-probe prints what the window server says about full-screen Spaces and Split View, the windows on them, and the macOS tiling settings; --menu <App> also lists that app’s Window menu items. It’s for checking how a new macOS release reports these.

The rest are development aids. They only work in a build made with app/scripts/bundle.sh --dev:

Command What it does
settings-shot <tab> <path> Saves a tab as a PNG; <tab>@<height> captures a taller window
minimap-shot <path> Saves the mini-map as a PNG
min-size <window id> Asks a window for 300 × 300 pt, logs the size it actually takes after 0.1 s and 0.5 s, then puts it back in its tile
minimap Opens or closes the mini-map, as clicking the menu-bar item does
welcome-shot <page> <path> Saves a Welcome page (permission, macOS, presets or keys) as a PNG. Scrolling lists don’t render
menubar-shot <path> Saves the menu-bar item’s image
overlay-preview <path> Saves every drop-overlay style side by side
hover <x> <y> Runs focus follows mouse for that point
show <window id> What clicking a window in the mini-map does: switches to its Space, on whichever display, and focuses it. Window ids come from frames
wake Runs what Spacetile does after the Mac wakes: settle, check displays, lay out again
fullscreen <app> Toggles native full screen on that app’s focused window
spaces-override <n> Settings acts as if there were n Spaces (0 clears)
login on Registers open at login

Spacetile logs to the unified log under the com.kodehort.spacetile subsystem:

log show --last 5m --predicate 'subsystem == "com.kodehort.spacetile"' --style compact

It also marks layout passes, Space changes, Space switches and profile loads as signpost intervals in the performance category. Record Spacetile with Instruments’ os_signpost (or Logging) template to see how long each takes.

How it works without SIP

These private window-server calls work with SIP on, and were checked on macOS 27.0:

Job How
Moving a window to another Space SLSBridgedMoveWindowsToManagedSpaceOperation
Instant Space switching Synthetic dock-swipe events carrying an IOHID payload
Focusing a window, with or without raising _SLPSSetFrontProcessWithOptions and key-window event records, as yabai does
Reading Spaces and window membership SLSCopyManagedDisplaySpaces and SLSCopySpacesForWindows
Full screen and Split View The public AXFullScreen attribute, the app’s own Window ▸ Full-Screen Tile menu items through Accessibility, and a synthetic click in the Split View picker. TileLayoutManager in SLSCopyManagedDisplaySpaces says which windows are a full-screen Space’s

A macOS update could break any of these; each one is isolated, so Spacetile degrades rather than failing outright.

Limits

  • Spacetile can’t create, delete or reorder Spaces.
  • No window opacity, layers or sticky windows; those need SIP off.
  • Clicking a tile, or focusing it with the keyboard, can bring it above a floating window from another app.
  • Private APIs rule out the Mac App Store. Public distribution needs a paid developer account for notarization.