Skip to content

Development Setup

ChiFungHillmanChan edited this page Sep 16, 2026 · 6 revisions

Development Setup

Prerequisites

  • macOS 14 (Sonoma) or later
  • Xcode 16+ (free on the Mac App Store) — installs the Swift 5.9 toolchain and Command Line Tools
  • Git 2.30+
  • Optional: gh CLI for creating releases

No Apple Developer account needed. Ad-hoc signing works for local builds and the distributable DMG.

Clone and build

git clone https://github.com/ChiFungHillmanChan/setpiece.git
cd setpiece

Run the core test suite (no Xcode required)

swift test

You should see Executed 157 tests, with 0 failures. The V0.1 → V0.4 progression: 26 (V0.1) → 92 (V0.2) → 116 (V0.3) → 157 (V0.4).

  • V0.1 (26): Slot, Layout, LayoutEngine.plan/apply, Geometry.rectsApproxEqual, nearestSlot, Plan, WindowRef via MockWindow, AXPermission smoke.
  • V0.2 (+66): LayoutTemplate (slot math + sanitization), CustomLayout/PresetSeeds/LayoutStore (Codable + persistence + seed semantics + block-save hotkey conflicts), HotkeyBinding (Carbon bridge + display string), AnimationConfig/SettingsStore (defaults + clamping + observation), FrameInterpolator (curves + endpoint exactness), AnimationRunner (mock-clock interruption / cancellation / rapid retrigger).
  • V0.3 (+24): DragSwapController state machine (pickup / preview / swap / cancel), DragSwapConfig (threshold clamping + persistence), nearest-slot math for drag detection.
  • V0.4 (+41): Workspace / WorkspaceTrigger / FocusModeReference Codable round-trips, WorkspaceSeeds (4 seeds, stable UUIDs, ⌘⌥1–4 defaults), WorkspaceStore (CRUD + persistence + observation + cross-store hotkey conflict), vertical seed migration via applyFutureSeeds, WeekdayMask OptionSet encoding.

Open the app in Xcode

open SceneApp/SceneApp.xcodeproj

Select the SceneApp scheme and press ⌘R. The app runs as a menu bar extra (no Dock icon).

Command-line app build

xcodebuild -project SceneApp/SceneApp.xcodeproj \
           -scheme SceneApp \
           -configuration Debug \
           CODE_SIGNING_REQUIRED=NO \
           build

CODE_SIGNING_REQUIRED=NO dodges a local keychain quirk that sometimes throws errSecInternalComponent. Does not affect behavior.

Build a distributable DMG

./scripts/build-dmg.sh 0.4.0              # dist/Scene-0.4.0.dmg

Produces an Apple Silicon (arm64) ad-hoc signed app packaged with an /Applications drop shortcut. macOS 14+ machines are overwhelmingly Apple Silicon; to re-include Intel, add ARCHS="arm64 x86_64" back to the build script. See Release Process for the full version-bump workflow.

Accessibility permission during development

Setpiece needs Accessibility access to move other apps' windows. macOS ties that permission to the app's code signature and path:

  • When you run under Xcode, the app is rebuilt into ~/Library/Developer/Xcode/DerivedData/... each time. macOS sees this as the same identity between runs, so you grant permission once and it persists.
  • When you switch between Debug / Release builds, macOS may treat them as different apps and re-prompt.
  • V0.4 TCC cdhash quirk: ad-hoc signed builds have the AX grant tied to the binary's cdhash. Every rebuild invalidates the grant even though the toggle in System Settings still looks ON. Symptom: hotkeys silently stop working after a rebuild. Fix: toggle the Setpiece entry OFF then ON again in System Settings → Privacy & Security → Accessibility, or run tccutil reset Accessibility com.hillman.SceneApp to force the prompt fresh.
  • If Setpiece stops seeing permission after a rebuild, open System Settings → Privacy & Security → Accessibility, remove all SceneApp entries, grant fresh.

Repository layout

Package.swift                 SceneCore library manifest
Sources/SceneCore/            pure library (V0.4: AX/Animation/Display/Interaction/Layout/Settings/Workspace)
Tests/SceneCoreTests/         XCTest, 157 cases
SceneApp/SceneApp.xcodeproj   Xcode project
SceneApp/SceneApp/            app-shell code (V0.4: Settings/, Stores/, Animation/, Interaction/, Workspace/Triggers/, Resources/)
scripts/build-dmg.sh          DMG packager
docs/                         INSTALL.md, TESTING.md (V0.1–V0.4 smoke sections)
.gitignore                    covers build/, dist/, xcuserdata, AI tool files

.gitignore excludes local AI-session files (CLAUDE.md, .claude/, etc.) so they never leak into commits.

Common dev commands

Task Command
Run core tests swift test
Run one test swift test --filter LayoutEnginePlanTests
Compile without running swift build
Xcode debug build xcodebuild … CODE_SIGNING_REQUIRED=NO build
Universal DMG ./scripts/build-dmg.sh <version>
Clean everything rm -rf .build build dist SceneApp/build

Clone this wiki locally