A hydration reminder triggered by Claude Code hooks. When a prompt runs longer than 45 seconds, it reminds you to drink water — with optional webcam-based sip detection or a macOS notification.
Claude Code has hooks — shell commands that run automatically at certain points in a conversation. This project installs two hooks that attach to two hook events:
UserPromptSubmit— a hook starts a background timer when you send a prompt.Stop— a hook kills that timer when Claude finishes responding.
If Claude is still thinking after 45 seconds (configurable), the timer fires and launches the hydration reminder. The reminder itself is not a hook — it's the program (water_check/) that the hooks trigger. Short turns never fire the reminder.
The reminder comes in one of two modes:
- Webcam mode (default): A small window pops up in the corner showing your camera feed. It uses Google MediaPipe to track your hands and face — when it sees you raise a bottle or cup to your mouth and hold it there for half a second, it confirms the sip and dismisses itself. You can also press
dto dismiss manually. - Notification mode: A macOS banner notification with a Glass sound.
-
Clone the repo and create a virtualenv:
cd hydrate-hook python3 -m venv .venv .venv/bin/pip install -r requirements.txt -
Install
terminal-notifier(only needed fornotificationorbothmodes):brew install terminal-notifier -
Install the hooks into
~/.claude/settings.json(also downloads the MediaPipe model on first run):python3 install.py -
If using notification mode, send a test notification so macOS registers the app:
terminal-notifier -title "Hydrate" -message "Test" -sound GlassThen go to System Settings > Notifications > terminal-notifier and set Allow Notifications: ON, style: Banners.
-
Restart Claude Code.
python3 water_check/toggle.py on
python3 water_check/toggle.py off
python3 water_check/toggle.py status
Takes effect on your next prompt. No Claude Code restart needed.
Choose how the hydration reminder is delivered:
python3 water_check/toggle.py mode webcam
python3 water_check/toggle.py mode notification
| Mode | What happens |
|---|---|
webcam |
Webcam sip-detection window with Glass sound (default) |
notification |
macOS banner notification with Glass sound |
Check the current mode:
python3 water_check/toggle.py mode
Change how long a prompt must run before the reminder fires (default: 45s):
python3 water_check/toggle.py delay 30
python3 water_check/toggle.py delay
Enable logging to save frame-by-frame landmark data and snapshots for debugging detection:
python3 water_check/toggle.py logging on
python3 water_check/toggle.py logging off
python3 water_check/toggle.py logging
When enabled:
~/.hydrate-hook/sip_log.jsonl— one JSON line per frame with detection state, wrist distances, and landmark positions~/.hydrate-hook/snapshots/— a JPEG saved on each confirmed sip
While the webcam window is open, press f to flag a false negative (saves a snapshot and log entry for that frame). Useful for tuning detection thresholds.
- macOS (uses AVFoundation for camera, AppKit for window positioning)
- Python 3.10+
terminal-notifier(for notification mode) —brew install terminal-notifier- Dependencies installed via
requirements.txt:mediapipe— hand/face tracking for sip detectionopencv-python— webcam capture and displaypyobjc-framework-Cocoa— precise window positioning on Retina displays
Straw bottles not detected: The sip detector works by tracking your wrist moving near your face. Drinking from a straw (where the bottle stays on the desk) won't be detected. Press d to dismiss manually in this case.
Webcam opens on iPhone instead of MacBook camera: If your iPhone is nearby, macOS Continuity Camera can make it appear as a webcam. To disable this, on your iPhone go to Settings > General > AirPlay & Continuity > Continuity Camera and turn it off.
Edit ~/.claude/settings.json and remove the two entries pointing at hydrate-hook/hooks/. A backup was saved to settings.json.bak when you installed.