A deliberately annoying macOS menu-bar app: on an interval it throws an unmissable overlay across your screen and won't let you back to work until you get up, fetch a real object (a fork, a mug, a shoe…) and scan it with the webcam. On-device ML, no cloud. Calendar-aware so it won't crash your meetings.
Status: Core loop + calendar gate + ship-ready shell all working. On-device classifier is Apple Vision (built-in); MobileCLIP upgrade is the next big rock.
./Scripts/fetch_models.sh # one-time: download MobileCLIP-S0 (gitignored)
./Scripts/make_app.sh # build + assemble the signed .app
open get-up.app # settings window opens; app lives in the menu barIt lives in the menu bar as an orange up-arrow. The settings window opens on launch so you can grant camera access (required) and connect Google Calendar (optional, one click — the OAuth client is bundled).
./Scripts/package.sh # → dist/get-up-<version>.zipTesters: unzip → drag to /Applications → right-click → Open on first launch (ad-hoc signed) → grant camera → menu bar arrow → START.
- Connect Google first (required) — one click with your @why.de account. It's what protects your meetings (live calendar check before every nag) and signs your scans in the team analytics. No connection → no nagging, by design.
- Menu bar orange arrow → START — arm the schedule: fires at a random moment every 15–30 minutes (unpredictable by design; the UI never reveals the next time). Meeting-aware with a ±5 min safety window, call-aware (mic/camera busy → postpone 5 min and re-check).
- Nag me now — trigger a challenge immediately (bypasses the calendar/call gates).
- Settings… (from the panel): alarm test, launch-at-login, camera permission, Google account.
- Analytics (internal testing): completions/skips are sent to the team PostHog, attributed to your Google account. Disclosed in Settings → Internal testing.
- Scan the requested object to unblock (hold it ~1s).
- Shuffle re-rolls the object if you genuinely don't have it — you still have to scan whatever comes next. 5 per day (resets at midnight); the button shows what's left.
- Out of shuffles? An "Arms up instead" button appears: stand up, step back so your knees are in frame, raise both arms, hold it. Body-pose detection requires wrists above your nose and a visible knee — you can't do it from a chair.
- Mute silences the alarm but keeps the challenge running.
- Esc skips — spike-only hatch while we tune; production gates it behind the give-up timer.
- Cmd+Q quits. The kill switch stays available by design.
| Piece | Behaviour |
|---|---|
| Blocker | Borderless window per display at .screenSaver level, covers all Spaces incl. fullscreen apps, resists click-away |
| Scan | Webcam → on-device MobileCLIP-S0 (CLIP) ~4 fps → softmax over baked prompts → 3-frame debounce → unblock; fails open if no camera/model |
| Vocabulary | CLIP text prompts (Vocabulary.swift) — off-desk "go fetch" objects incl. stapler/keys/remote + open-vocab curveballs |
| Schedule | Random 15–30 min interval, re-rolled after each fire and on wake from sleep; next fire time never shown |
| Work hours | Mon–Fri 9:00–17:00 only, lunch grace 11:30–13:30; off-hours fires drop silently |
| Call gate | Defers a scheduled nag if the mic or any camera is in use (CoreAudio + CoreMediaIO) — catches ad-hoc calls the calendar misses |
| Calendar gate | Google free/busy (EventKit fallback) with a ±5 min safety window around meetings; blocked → retry in 5 min |
| Shell | Menu-bar-only, Settings window, launch-at-login (SMAppService), persisted prefs |
- Home/office/mixed vocab profiles.
- Distribution — notarized build installed to
/Applications(needed for the login item to register reliably; an ad-hoc dev build may report an error there).
Sources/GetUp/
GetUpApp.swift app entry, menu bar, Settings UI, Coordinator
Blocker.swift overlay windows + challenge UI + camera preview
CameraScanner.swift webcam capture + classifier + match logic
CalendarGate.swift EventKit meeting gate (soft, optional)
Vocabulary.swift the "get up and fetch" object list (exact Vision labels)
Support.swift prefs, login-item, alarm, interval scheduler
Scripts/make_app.sh build + bundle + ad-hoc sign
Scripts/dump_labels.swift dump the Vision taxonomy to curate the vocabulary
Resources/Info.plist bundle id, LSUIElement, camera/calendar usage strings