Prism Window is a macOS menu bar app that moves the focused window to the correct display using user-defined rules.
- Rule-based window placement per app
- Fullscreen or windowed placement rules
- Auto-apply when an app becomes frontmost
- Multiple named setup profiles for the same physical display arrangement
- Manual move UI in the menu bar
- Visual display layout picker
- Settings UI for editing rules, profiles, and display setups
Run the app from source:
swift build
swift run PrismWindowBuild a distributable .app bundle:
./scripts/build-app.shOutput:
.build/release/Prism Window.appThe executable inside the bundle remains:
PrismWindowThe app icon source image is stored at:
Resources/AppIcon.pngThe build script converts it into an .icns file and places it in the app bundle.
The app version is read from:
Resources/Info.plistCurrent app version:
1.0.0GitHub Actions workflow:
.github/workflows/release-macos-app.ymlThe workflow:
- resolves the release version from
workflow_dispatchinput orResources/Info.plist - creates a
v<version>git tag if it does not already exist - builds
Prism Window.app - signs and notarizes the app
- uploads a zip archive and sha256 checksum to GitHub Releases
Required GitHub secrets:
APPLE_CERT_BASE64APPLE_CERT_PASSWORDAPPLE_API_PRIVATE_KEYAPPLE_API_KEY_IDAPPLE_API_ISSUER_ID
- Accessibility: required for reading and moving windows
- Screen Recording: not required
Prism Window uses the macOS Accessibility API to move windows between displays.
For normal windows, Prism Window updates the window position and size directly.
For fullscreen windows, Prism Window uses a public-API fallback flow:
- Exit fullscreen
- Move the window to the target display
- Re-enter fullscreen if required
This keeps the app compatible with direct distribution and avoids private CGS APIs, but it is not a true Space-to-Space transfer.
Rules are organized in two layers:
- Physical display setup: the currently connected monitor arrangement
- Setup profile: a named rule set for that arrangement, such as
Work,Home, orPresentation
You can keep multiple profiles for the same display setup and switch which one auto-applies.
- Some apps refuse
AXFullScreentoggling or window resize operations - Fullscreen moves use a fallback flow, so stale snapshots or residual animations can sometimes remain on the source display
- Stage Manager, Mission Control, and Space transitions can affect perceived behavior
- Public APIs do not provide a true Space-to-Space fullscreen move