A smart break reminder for macOS that monitors your activity and enforces healthy work habits.
Work 50 minutes → Rest 10 minutes → Repeat!
- 🖱️ Activity Detection — Monitors keyboard/mouse idle time via
ioreg - ⏰ Smart Timer — 50 min work / 10 min break cycle (configurable)
- 🖥️ Fullscreen Break Screen — Swift AppKit overlay with multi-monitor support
- 📊 TUI Dashboard — Real-time progress bars and daily statistics (Bubbletea)
- 🖼️ Native GUI Dashboard — macOS native window with circular progress bar
- 🍎 Menu Bar App — Native macOS status item with quick controls and live session status
- 🧘 Guided Break Activities — Eye exercise, stretching, box breathing, walk timer
- 🤖 AI Integration — Productivity analysis via Claude/Codex CLI
- 🗓️ Smart Scheduling — Only active during configured working hours/days
- 📈 Daily Stats — Track work/break time with gap detection for accurate tracking
- 🔔 Notifications — Visual + voice alerts (
say, KittenTTS, Supertonic, or Gemini 3.1 Flash TTS) - 🚀 Auto-start — LaunchAgent timer with 60-second check interval plus optional menu bar auto-start
- 🏥 Diagnostics —
doctorcommand to verify all components
- ☁️ Gemini 3.1 Flash TTS — New cloud TTS engine with 30 expressive voices (Zephyr, Puck, Kore, ...) and native 70+ language support, no local install required
- 🔑 API Key Config —
tts_api_keyYAML field orGEMINI_API_KEYenv var powers the new engine - 🎙️ Engine Parity —
tts test,doctor, and runtime break alerts all speak through Gemini when configured
brew install devlikebear/tap/break-remindergit clone https://github.com/devlikebear/break-reminder.git
cd break-reminder
make build # Build Go binary + Swift helpers (break-screen, break-dashboard, break-menubar)
make install # Install to ~/.local/bin/ + register timer/menu bar LaunchAgents# Core
break-reminder check # Single timer tick (used by launchd)
break-reminder daemon # Foreground loop
break-reminder status # Current state overview
break-reminder reset # Reset timer
break-reminder pause # Pause the timer (default mode: meeting; paused time is not counted as work)
break-reminder pause --mode=focus # Pause but count the paused time as work (e.g., off-screen focus block)
break-reminder pause --mode=afk --duration=30m # External absence; resets work cycle; auto-resumes in 30 min
break-reminder resume # Resume the previous work/break mode
break-reminder snooze # End the current break early and postpone the next one by 5 min
break-reminder snooze --for 10m # Postpone the next break by a custom duration
# Dashboard
break-reminder dashboard # TUI dashboard
break-reminder dashboard --gui # Native macOS GUI
break-reminder menubar # Native macOS menu bar app
# Service Management
break-reminder service install # Register timer LaunchAgent + menu bar auto-start when helper is installed
break-reminder service uninstall # Remove LaunchAgents
break-reminder service start # Start service
break-reminder service stop # Stop service
break-reminder service status # Check service status
# Guided Break Activities
break-reminder break eye # 20-20-20 eye exercise (2 min)
break-reminder break stretch # Stretching guide (5 min)
break-reminder break breathe # Box breathing (4 min)
break-reminder break walk # Walk timer (5 min)
# AI (requires claude or codex CLI)
break-reminder ai summary # Daily productivity report
break-reminder ai summary --weekly # Weekly report
break-reminder ai suggest # Optimal timing suggestions
break-reminder ai configure "25분 작업, 5분 휴식" # Natural language config
# Configuration
break-reminder config show # Show current config
break-reminder config edit # Open in $EDITOR
break-reminder config get work_duration_min # Print a single value
break-reminder config set work_duration_min=45 break_duration_min=15 # Validated atomic write
break-reminder config set notifications_enabled=false # Booleans
break-reminder config set work_days=[1,2,3,4,5] # Flow-style arrays
# Optional TTS backends
break-reminder tts install kittentts # Install KittenTTS into a managed venv
break-reminder tts install supertonic # Install Supertonic into a managed venv
break-reminder tts test "안녕하세요" # Speak a phrase with the current TTS config
break-reminder tts uninstall kittentts # Remove the managed KittenTTS venv
break-reminder tts uninstall supertonic # Remove the managed Supertonic venv
# Gemini 3.1 Flash TTS (no install — just config + API key)
export GEMINI_API_KEY=your_api_key
break-reminder tts set-api-key $GEMINI_API_KEY # save to config with 0600 perms
break-reminder config edit # set tts_engine: gemini, voice: Zephyr
break-reminder config path # Show config file path
# Diagnostics
break-reminder doctor # Check all components
break-reminder version # Show version🐹 Break Reminder Dashboard (q:quit r:reset b:break)
══════════════════════════════════════════════════
System: Installed & Running
Menu Bar: Installed & Running
Status: WORKING
Idle: 3s / Limit: 120s
Session Work: [████████████████░░░░░░░░░░░░░░] 53% (26 / 50 min)
Daily Statistics:
Work: 2h 5m
Rest: 30m
Ratio: [████████████████████░░░░] 80%
Recent Logs:
──────────────────────────────────────────────────
[2026-03-19 14:30:00] work mode, session 26min
──────────────────────────────────────────────────
The native menu bar app shows live mode/progress in the title (🐹 31% · 34m left, ☕ 25% · 7m left) and exposes today's work/break totals inside the menu. After break-reminder service install, it is auto-registered as a separate LaunchAgent when the break-menubar helper is available, so it stays running after the launching terminal exits.
🐹 Break Reminder Status
========================
System: Installed & Running
Menu Bar: Installed & Running
State: Active (Within working hours)
------------------------
Mode: paused (work)
Session Work: 32min / 50min
Daily Stats: Work 2h 5m / Break 30m
Current idle: 3sec
Paused for: 4m12s
Use break-reminder snooze during an active break to return to work mode immediately and postpone the next break without losing the postponement if the daemon updates state at the same time.
break-reminder snooze
break-reminder snooze --for 10msnoozeis only valid while a break is active.- It ends the current break early, resumes work immediately, and suppresses break reminders until the requested snooze window expires.
- The default postpone duration is 5 minutes.
- If the app is paused in a future state file,
snoozeexits safely instead of guessing.
Edit ~/.config/break-reminder/config.yaml:
# Timer Settings
work_duration_min: 50 # Work duration (default: 50 min)
break_duration_min: 10 # Break duration (default: 10 min)
idle_threshold_sec: 120 # Idle threshold (default: 2 min)
natural_break_sec: 300 # Auto-reset threshold (default: 5 min)
# Smart Scheduling
work_days: [1, 2, 3, 4, 5] # ISO weekdays (1=Mon, 7=Sun)
work_start_hour: 9
work_start_minute: 0 # Optional minute precision for the work start boundary (0-59)
work_end_hour: 18
work_end_minute: 0 # Optional minute precision for the work end boundary (0-59)
# Note: work windows stay within the same day; overnight schedules are not supported.
# Break Screen
break_screen_mode: "ask" # "ask" (choose once), "block" (fullscreen), "notify" (notification only)
break_activities_enabled: true # Show guided activity menu on break
# Voice & Notifications
voice: "Yuna" # Voice name for the selected TTS engine
tts_engine: "say" # "say", "kittentts", "supertonic", or "gemini"
tts_model: "KittenML/kitten-tts-nano-0.8" # KittenTTS model; Supertonic uses a fixed bundle; Gemini uses "gemini-3.1-flash-tts-preview"
tts_python_cmd: "python3" # Python with the selected optional TTS package installed (not used by gemini)
tts_api_key: "" # Gemini API key (or export GEMINI_API_KEY env instead)
tts_enabled: true
notifications_enabled: true
# AI
ai_enabled: true # Enable AI features
ai_cli: "claude" # "claude" or "codex"Or use natural language:
break-reminder ai configure "25분 작업, 5분 휴식으로 바꿔줘"cmd/break-reminder/ # Cobra CLI commands
internal/ # Go internal packages
timer/ # Pure function timer logic (Tick)
config/ # YAML config with smart boolean merge
state/ # Key-value state file persistence
idle/ # Idle detection (ioreg on macOS)
notify/ # macOS notifications (osascript)
tts/ # Text-to-speech (say / KittenTTS / Supertonic / Gemini)
breakscreen/ # Break screen orchestration
dashboard/ # TUI dashboard + break activities
ai/ # AI CLI wrapper + history
doctor/ # System diagnostics
schedule/ # Working hours check
launchd/ # LaunchAgent management
logging/ # File-based logging with rotation
helpers/ # Swift SPM package
Sources/BreakScreenApp/ # Fullscreen break screen (multi-monitor)
Sources/DashboardApp/ # Native GUI dashboard
Sources/HelperCore/ # Shared pure logic (parsing, formatting)
Tests/HelperCoreTests/ # Swift unit tests
Formula/ # Homebrew formula
.github/workflows/ # CI + Release pipelines
| File | Location |
|---|---|
| Config | ~/.config/break-reminder/config.yaml |
| State file | ~/.break-reminder-state |
| Log file | ~/.break-reminder.log |
| History | ~/.break-reminder-history.json |
| Timer LaunchAgent | ~/Library/LaunchAgents/com.devlikebear.break-reminder.plist |
| Menu bar LaunchAgent | ~/Library/LaunchAgents/com.devlikebear.break-reminder.menubar.plist |
The default voice uses macOS Yuna (Korean). To change:
# List available voices
say -v '?'
# Update config
break-reminder config edit
# Change: voice: "Samantha"To use KittenTTS instead:
break-reminder tts install kittenttsThe installer auto-selects a compatible Python 3.8-3.12 interpreter when possible. Use --bootstrap-python to override it explicitly.
KittenTTS currently provides these built-in voices: Bella, Jasper, Luna, Bruno, Rosie, Hugo, Kiki, Leo.
You can customize the activated model or voice during install:
break-reminder tts install kittentts --voice Bella --model KittenML/kitten-tts-micro-0.8To remove the managed KittenTTS environment and restore say defaults:
break-reminder tts uninstall kittenttsTo use Supertonic instead:
break-reminder tts install supertonicSupertonic currently provides these built-in voices: F1, F2, F3, F4, F5, M1, M2, M3, M4, M5.
The first Supertonic playback downloads the ONNX model bundle automatically (roughly 300MB). After that, Korean and English phrases run locally on-device.
You can customize the activated voice during install:
break-reminder tts install supertonic --voice F3tts_model is still stored in config for Supertonic, but the runtime currently uses the built-in Supertone/supertonic-2 bundle.
To remove the managed Supertonic environment and restore say defaults:
break-reminder tts uninstall supertonicTo use Gemini 3.1 Flash TTS (cloud, no install required):
# Save the API key to config (sets 0600 permissions automatically)
export GEMINI_API_KEY=your_api_key
break-reminder tts set-api-key $GEMINI_API_KEY
# or read from stdin: echo $GEMINI_API_KEY | break-reminder tts set-api-key
# or pass directly: break-reminder tts set-api-key AIzaSy...
# Switch engine
break-reminder config edit
# tts_engine: "gemini"
# tts_model: "gemini-3.1-flash-tts-preview"
# voice: "Zephyr"
break-reminder tts test "안녕하세요"💡 launchd note: background timer checks don't inherit your shell env, so
export GEMINI_API_KEY=...alone is not enough for the scheduled break alerts to speak.tts set-api-keypersists the key into the config file, which is read by both interactive commands and the LaunchAgent.
Supported Gemini voices: Zephyr, Puck, Charon, Kore, Fenrir, Leda, Orus, Aoede, Callirrhoe, Autonoe, Enceladus, Iapetus, Umbriel, Algieba, Despina, Erinome, Algenib, Rasalgethi, Laomedeia, Achernar, Alnilam, Schedar, Gacrux, Pulcherrima, Achird, Zubenelgenubi, Vindemiatrix, Sadachbia, Sadaltager, Sulafat (70+ languages, model selects automatically).
⚠️ Privacy note: Gemini is a cloud service. Break reminder text ("Time for a break!" etc.) is sent to Google's servers on each playback. Choose a local engine (say/ KittenTTS / Supertonic) if this is a concern.
Contributions are welcome! Feel free to:
- 🐛 Report bugs
- 💡 Suggest features
- 🔧 Submit pull requests
MIT License - see LICENSE for details.
- Inspired by the Pomodoro Technique®
- Built with ❤️ for healthier work habits
Remember: Your health is more important than any deadline! 🐹💪