217 lines
7.7 KiB
Markdown
217 lines
7.7 KiB
Markdown
# 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:**
|
|
```bash
|
|
chmod +x break-event break-status
|
|
cp break-event break-status ~/.local/bin/
|
|
```
|
|
|
|
2. **Create configuration directory:**
|
|
```bash
|
|
mkdir -p ~/.config/break-timer
|
|
cp config.example.json ~/.config/break-timer/config.json
|
|
```
|
|
|
|
3. **Edit configuration** (optional):
|
|
```bash
|
|
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`):
|
|
```json
|
|
{
|
|
"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`):
|
|
```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:**
|
|
```bash
|
|
swaymsg reload
|
|
killall waybar && waybar &
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Edit `~/.config/break-timer/config.json`:
|
|
|
|
```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](https://workrave.org/) - The original, and a great app, but does not have very robust Wayland support at the time this tool was created.
|
|
- [BreakTimer](https://breaktimer.app/) - Very nice interface, but only supports a single timer.
|
|
- [ianny](https://github.com/zefr0x/ianny) - Supports Wayland, but otherwise I have not explored deeply.
|
|
|
|
## License
|
|
|
|
MIT
|