A macOS menubar app that helps you stay focused during LeetCode sessions by tracking when you look away from the screen or switch to other apps.
Solving LeetCode problems effectively means staying focused without reaching for AI helpers or other distractions. LeetWatcher uses an honor-system approach: it doesn't block anything, but tracks your focus so you can reflect on your session afterward.
- Window monitoring: Detects when you switch away from a browser with LeetCode open
- Gaze detection: Uses your webcam + MediaPipe to detect when you're looking away from the screen
- Session summary: After each session, shows your focus percentage and prompts reflection on your approach
Violations are recorded after 5 seconds of looking away or switching windows, giving you time for natural glances.
- macOS (uses Quartz for window detection)
- Python 3.13+
- Webcam access (for gaze detection)
LeetWatcher requires these macOS permissions to function properly:
| Permission | Why | How to Grant |
|---|---|---|
| Camera | Gaze detection via webcam | System Settings → Privacy & Security → Camera → Enable for Terminal/Python |
| Screen Recording | Reading browser window titles to detect LeetCode | System Settings → Privacy & Security → Screen Recording → Enable for Terminal/Python |
| Automation | Getting browser URL via AppleScript | Prompted automatically when first accessing browser URL |
-
Camera: You'll be prompted on first run. Click "OK" to allow.
-
Screen Recording:
- Go to System Settings → Privacy & Security → Screen Recording
- Enable the app running LeetWatcher (usually "Terminal" or "Python")
- Restart the app after granting
-
Automation (for URL capture):
- When you start a session with a browser open, macOS will ask to allow control
- Click "OK" to let LeetWatcher read the current URL
Note: Without Screen Recording permission, LeetWatcher can still detect app switches but cannot see window titles. It will assume any browser is on LeetCode to avoid false violations.
# Clone and install
git clone <repo-url>
cd LeetWatcher
# Download the MediaPipe model
curl -L -o leetwatcher/models/face_landmarker.task \
"https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task"
# Install dependencies
uv sync# Run the menubar app
uv run leetwatcher
# Preview gaze detection (calibration)
uv run python -m leetwatcher.previewIn the menubar:
- Start Session: Begin tracking focus
- End Session: Stop and see your summary
- Gaze Preview: Test what movements trigger violations
- View History: See past sessions
The preview window shows:
- GREEN: Focused (looking at screen)
- RED: Looking away (would trigger violation after 5s)
- ORANGE: No face detected
Use this to calibrate your setup and understand what counts as "looking away."