wlr-break-timer

A fully automated break timer for wlroots-based desktop environments (SwayWM, etc.) that helps maintain healthy work habits by tracking work duration and break periods.

Features

  • Zero user interaction required - Automatically tracks work/break cycles.
  • Dual break timers - Independent short breaks (20m work → 20s break) and long breaks (45m work → 5m break).
  • Automatic idle detection - Uses swayidle to detect when you're away from the computer.
  • Pause/Unpause - Manually pause the timer when needed (paused time doesn't count toward work duration).
  • Self-managing log - Automatically trims old events to keep log size minimal.
  • Waybar integration - Shows countdown timers in your status bar with context menu.
  • No dependencies - Only requires Python 3 (pre-installed on most Linux systems).
  • No daemon process - Swaylock is the only long-running process. Other scripts are executed to modify or read the log file.

How It Works

  1. swayidle monitors keyboard/mouse activity via Wayland protocols
  2. When idle timeout is reached, break-event logs an idle_start event
  3. When you return, break-event logs an idle_end event
  4. break-status parses the log to calculate active time and break status
  5. Waybar polls break-status every second to display current timers

Timer Logic

  • Short breaks: After 20 minutes of active work, you need a 20 second break
  • Long breaks: After 45 minutes of active work, you need a 5 minute break
  • Automatic credit: Idle periods ≥ break duration automatically count as breaks taken
  • Smart reset: Long breaks also reset the short break timer (since they encompass it)
  • Auto-trim: When a long break is completed, all log entries before it are deleted

Installation

  1. Copy scripts to your PATH:

    chmod +x break-event break-status
    cp break-event break-status ~/.local/bin/
    
  2. Create configuration directory:

    mkdir -p ~/.config/break-timer
    cp config.example.json ~/.config/break-timer/config.json
    
  3. Edit configuration (optional):

    nano ~/.config/break-timer/config.json
    
  4. Add to Sway config (~/.config/sway/config):

    exec swayidle -w \
        timeout 5 'break-event idle_start' \
        resume 'break-event idle_end' \
        before-sleep 'break-event idle_start' \
        after-resume 'break-event idle_end'
    
  5. Add to Waybar config (~/.config/waybar/config):

    {
      "modules-right": ["custom/break-timer"],
    
      "custom/break-timer": {
        "exec": "break-status",
        "return-type": "json",
        "interval": 1,
        "format": "🕐 {}",
        "tooltip": true,
        "menu": "on-click",
        "menu-file": "/path/to/menu.xml",
        "menu-actions": {
           "skip-long": "break-event skip_long",
           "toggle-pause": "break-event toggle-pause"
        }
      }
    }
    
  6. Add Waybar styling (~/.config/waybar/style.css):

    #custom-break-timer.normal {
      color: #a6e3a1;
    }
    
    #custom-break-timer.warning {
      color: #f9e2af;
    }
    
    #custom-break-timer.overdue {
      color: #f38ba8;
      font-weight: bold;
    }
    
    #custom-break-timer.break {
      color: #89b4fa;
    }
    
    #custom-break-timer.paused {
      color: #cba6f7;
      font-style: italic;
    }
    
  7. Reload Sway and Waybar:

    swaymsg reload
    killall waybar && waybar &
    

Configuration

Edit ~/.config/break-timer/config.json:

{
  "short_break": {
    "interval": "20m",    // Work duration before short break
    "duration": "20s"     // Required short break length
  },
  "long_break": {
    "interval": "45",     // Work duration before long break
    "duration": "5m"      // Required long break length
  },
}

Status Display

The Waybar module shows:

  • Working: 15:30 / 45:20 - Time until short break (15min 30sec) and long break (45min 20sec)
  • Short break: SB 1:45 - Time remaining in short break
  • Long break: LB 8:30 - Time remaining in long break
  • Overdue: BREAK! -2:30 / 5:00 - You've exceeded a break time
  • Paused: ⏸ PAUSED - Timer is paused, no activity is being tracked

Color Coding

  • Green (normal): Plenty of time until next break
  • Yellow (warning): Break due in less than 5 minutes
  • Red (overdue): Break time has passed, you should take a break!
  • Blue (break): Currently in a break period
  • Purple (paused): Timer is paused

Using the Context Menu

Right-click the break timer widget in Waybar to access the context menu:

  • Skip Long Break: Reset all timers (useful if you just returned from a break not tracked by the timer)
  • ** Toggle Pause**: Pause or unpause the timer. While paused:
    • No activity is tracked
    • Idle detection is disabled (idle events are not logged)
    • The widget shows "⏸ PAUSED" in purple
    • Only the "Unpause Timer" menu option is shown

Log Management

  • Location: $XDG_RUNTIME_DIR/break-timer/activity.log (usually /run/user/1000/break-timer/)
  • Format: Simple text - <timestamp> <event_type>
  • Auto-trim: Automatically cleaned when long breaks complete
  • Size: Typically <10KB, contains only relevant recent events
  • Persistence: Cleared on logout/reboot (starts fresh each session)

Troubleshooting

Waybar shows "???"

  • Check if break-status is executable: chmod +x ~/.local/bin/break-status
  • Test manually: break-status should output JSON
  • Check log exists: ls $XDG_RUNTIME_DIR/break-timer/

Timers don't update

  • Verify swayidle is running: ps aux | grep swayidle
  • Check if events are being logged: cat $XDG_RUNTIME_DIR/break-timer/activity.log
  • Test event logging: break-event idle_start then break-event idle_end

Timers seem wrong

  • Check your configuration: cat ~/.config/break-timer/config.json
  • View raw log: cat $XDG_RUNTIME_DIR/break-timer/activity.log
  • Delete log to reset: rm $XDG_RUNTIME_DIR/break-timer/activity.log

Architecture

┌─────────────┐
│  swayidle   │  Monitors compositor for keyboard/mouse activity
└──────┬──────┘
       │ timeout → idle_start
       │ resume  → idle_end
       ▼
┌─────────────────────┐         ┌──────────────────────┐
│  break-event        │────────▶│  activity.log        │
│  - Append timestamp │  writes │  (event log)         │
│  - Auto-trim old    │         │                      │
└─────────────────────┘         └──────────────────────┘
                                         ▲
                                         │ reads
                                         │
┌─────────────┐         ┌───────────────┴──────┐
│   Waybar    │────────▶│  break-status        │
│  (polls 1s) │  calls  │  - Parse log         │
│             │         │  - Calculate timers  │
└─────────────┘         │  - Output JSON       │
                        └──────────────────────┘

Similar Projects

  • Workrave - The original, and a great app, but does not have very robust Wayland support at the time this tool was created.
  • BreakTimer - Very nice interface, but only supports a single timer.
  • ianny - Supports Wayland, but otherwise I have not explored deeply.

License

MIT

Description
An automatic break timer for use in wl-roots desktop environments. Seamlessly integration as a Waybar module.
Readme 127 KiB
Languages
Python 100%