How to Build a Tiny Python App That Reminds Me to Take Breaks


Spending all day at a screen is brutal on the eyes, the back, and the brain. So I decided to whip up a desktop toast that nudges me every hour to stand, stretch, sip water anything except keep slouch-coding. What started as seven lines of Python turned into a surprisingly fun mini-project that now lives in my toolbox.

  • “I only intended to write one quick script… then I fell down the rabbit-hole.”

Below is the journey, the full code, and a handful of ideas you can riff on.

Define Code

from plyer import notification

if __name__ == "__main__":
while True:
notification.notify(
title="ALERT!!!",
message="Take a break! It has been an hour!",
)
time.sleep(3600)

Install the only dependency:

pip install plyer

and run:

python break.py

Your OS pops up a toast every 60 minutes. Job done kind of.

What each line is doing

#CodeWhy it matters
1import timeGives me time.sleep() so the script can nap between alerts.
2from plyer import notificationplyer wraps each platform’s native “toast” API—works on Windows, macOS, Linux.
4if __name__ == "__main__":Runs the loop only when I execute the file directly, not when I import it elsewhere.
5while True:Endless loop until I hit Ctrl +C.
6-8notification.notify(...)Fires the visual reminder.
10time.sleep(3600)Waits one hour (3 600 s) before the next pass.

Great for a proof-of-concept; painful in real life. I wanted:

  • Flexible intervals (--interval 20m, 2h, 90s…)
  • Custom titles/messages
  • A finite number of pings (helpful in pomodoro workflows)
  • Random healthy-habit tips if I’m lazy
  • A gentle console beep (toast may be hidden)
  • Tidy logging with timestamps
  • Graceful shutdown no ugly tracebacks when I quit

Level-up: the extended script

Below is break_timer.py in full, then read on for usage examples.

#!/usr/bin/env python3
"""
break_timer.py – flexible desktop break-reminder
"""
import argparse
import datetime as dt
import random
import sys
import time
from plyer import notification

# ---------- tiny knowledge base ----------
_TIPS = [
"Stand up and stretch your legs 🦵",
"Look away from the screen for 20 seconds 👀",
"Roll your shoulders a few times 🙆‍♂️",
"Drink a glass of water 💧",
"Take three slow, deep breaths 😮‍💨",
]

def parse_interval(text: str) -> int:
"""Turn '45m', '2h', '30s' into seconds (int)."""
units = {'s': 1, 'm': 60, 'h': 3600}
if text[-1].isdigit(): # default to minutes
return int(text) * 60
value, unit = int(text[:-1]), text[-1].lower()
if unit not in units:
raise ValueError("Use s, m or h as units.")
return value * units[unit]

def beep() -> None:
"""Cross-platform console bell."""
print('\a', end='', flush=True)

# ---------- main ----------
def main():
p = argparse.ArgumentParser(description="Desktop break reminder")
p.add_argument('-i', '--interval', default='60m',
help='Time between reminders (e.g. 20m, 2h, 45s).')
p.add_argument('-c', '--count', type=int, default=0,
help='Number of reminders then exit (0 = unlimited).')
p.add_argument('-t', '--title', default='ALERT!!!',
help='Notification title text.')
p.add_argument('-m', '--message',
help='Notification body; omit → random tip.')
args = p.parse_args()

wait = parse_interval(args.interval)
remaining = args.count

print(f"[{dt.datetime.now():%H:%M:%S}] Timer started – every "
f"{wait//60 if wait>=60 else wait} "
f"{'min' if wait>=60 else 'sec'} "
f"({ '∞' if remaining==0 else remaining} alerts). Ctrl-C to quit.")

try:
while remaining != -1: # -1 means we hit the limit
body = args.message or random.choice(_TIPS)
notification.notify(title=args.title,
message=body,
app_name="Break Timer")
beep()
print(f"[{dt.datetime.now():%H:%M:%S}] Notified: {body}")

if remaining > 0:
remaining -= 1
if remaining == 0:
break
time.sleep(wait)
except KeyboardInterrupt:
print("\nStopped by user. Have a healthy day! 👋")
sys.exit(0)

if __name__ == "__main__":
main()

Running the upgraded version

install plyer           # one-time
python break_timer.py -i 45m # ping every 45 min
python break_timer.py -i 20m -c 6 # six pings then exit
python break_timer.py -i 90s -t "Hydrate" \
-m "Sip some water 🚰" # custom text

Quick flag reference

FlagExamplePurpose
-i, --interval-i 90sHow often to remind (supports s/m/h suffix).
-c, --count-c 4Quit after N reminders.
-t, --title-t "Hydrate"Notification headline.
-m, --message-m "Drink water"Body text (skip for a random tip).

Stretch goals I’m tinkering with

  1. System-tray icon with pause/resume for meetings.
  2. Work-hours window so it only nags 09:00-18:00.
  3. CSV/JSON logging to track how often I actually moved.
  4. Tkinter GUI so colleagues can set it up without CLI knowledge.
  5. GIF micro-exercises—imagine a shoulder-roll animation popping up.
  6. Voice alert via pyttsx3 for the perpetually alt-tabbed.

Final thought

Writing this tiny utility reminded me why I love Python:
a couple of imports + the right library = instant quality-of-life boost.

Feel free to fork, tweak, and ship your own flavour. Just remember: the best code you’ll ever write might be the one that literally tells you to stop coding for a minute.

Related blog posts