External sensory input can incorporate into dreams. Totem utilizes this by attempting to detect REM sleep and delivering a tactile cue (vibration). If you condition yourself to associate this specific vibration with questioning your reality, the watch acts as an external trigger for lucidity, replacing the need for spontaneous habit-based reality checks.
Annoyingly, Garmin's native sleep algorithms run either post-processing on the server or in a closed firmware layer that the SDK cannot touch live -- I'm not sure which. So this is my attempt to apply some probably dumb heuristics to guess when you're in REM. It's a WIP.
Named after the "totem" from Inception, a movie about lucid dreaming written by an avid lucid dreamer.
All four gates must be open to trigger a vibration:
- Gate 1: Time Lock - Waits 4 hours (REM is rare in the first half of the night)
- Gate 2: Motion Atonia - Movement-based confidence score of REM correlated motion
- Gate 3: HR Volatility - Erratic HR coincides with REM
- Gate 4: Wake Guard - Rejects elevated heart rate indicating wakefulness, unless volatility suggests intense dreaming
- Fenix 7 Series: fenix7pro, fenix7s, fenix7spro, fenix7x, fenix7xpro
- Fenix 8 Series: fenix843mm, fenix847mm, fenix8pro47mm, fenix8solar47mm/51mm, fenixe
- Forerunner: fr255/255m/255s/255sm, fr265/265s, fr955, fr965
- Vivoactive: vivoactive5
-
Java JDK 17
# Check if installed java -version # Install via Homebrew if needed brew install openjdk@17
-
VS Code
-
Monkey C Extension
-
Connect IQ SDK
Cmd + Shift + P→Monkey C: Open SDK Manager- Download the latest SDK
- Switch to Devices tab, download device definitions for your watch
-
Developer Key
# Generate a key # Cmd + Shift + P → "Monkey C: Generate Developer Key" # Move it to a safe location mkdir -p ~/.garmin mv developer_key.der ~/.garmin/
./run.shThis script builds the app and launches the simulator automatically.
./run-tests.shUnder the hood this uses monkeyc -t (compile tests) and monkeydo -t (run tests).
- Build:
Cmd + Shift + P→Monkey C: Build for Device→ Select your device - Connect watch via USB
- I use OpenMTP to access the watch
- Copy
bin/Totem.prgto/GARMIN/APPS/
totem/
├── manifest.xml # Permissions & supported devices
├── monkey.jungle # Build configuration
├── run.sh # Quick build & run script
├── resources/
│ ├── drawables/ # App icon
│ ├── settings/ # User-configurable settings
│ └── strings/ # Copy
└── source/
├── app.mc # Entry point & configuration
├── mainView.mc # Multi-page UI
├── inputDelegate.mc # Input handling & menus
├── theme.mc # Color constants
└── logic/
├── sleepService.mc # Core algorithm (Four Gates)
├── mathUtil.mc # Motion & HR calculations
├── sessionManager.mc # ActivityRecording wrapper
└── settings.mc # User preferences
In debug mode (DEBUG_MODE = true):
- Time gate: 60 seconds (instead of 4 hours)
- Stillness required: 30 seconds (instead of 15 minutes)
- Cooldown: 60 seconds (instead of 20 minutes)
- Screen stays on showing real-time gate status and sensor values
- Press SELECT button to manually trigger a test cue