A lightweight, privacy-friendly eye strain prevention tool for Linux, written in Rust.
Eye Guard follows the 20-20-20 rule: every 20 minutes, it reminds you to look at something 20 feet away for 20 seconds. It runs quietly in the background and shows a fullscreen break screen when it's time to rest your eyes.
- 20-20-20 rule — short breaks every 20 minutes, long breaks every 60 minutes
- Fullscreen break screen — dark, calming UI with a countdown timer
- Eye exercise tips — rotates through 8 relaxation exercises
- Skip & Postpone — press Escape to skip, or postpone for 5 minutes
- System tray — StatusNotifierItem with quick actions
- Desktop notifications — get warned before each break starts
- CLI control — take breaks, check status, enable/disable from the terminal
- Smart pause — skips breaks when you're away (X11 idle detection)
- Autostart — one flag to start at login
- TOML config — everything is customizable in
~/.config/eye-guard/config.toml - Zero telemetry — no network, no data collection, no accounts
cargo install eye-guardgit clone https://github.com/atheerium/eye-guard.git
cd eye-guard
cargo build --releaseDependencies (for building):
- GTK 4 development libraries (
libgtk-4-dev) - GLib development libraries (
libglib2.0-dev) - pkg-config
Runtime dependencies:
- GTK 4
- A notification daemon (for pre-break warnings)
- A StatusNotifierItem host (for the system tray)
# Start the daemon (runs in the background)
eye-guard
# Take a break right now
eye-guard --take-break
# Check status
eye-guard --status
# Enable / disable breaks
eye-guard --enable
eye-guard --disable
# Quit
eye-guard --quit
# Install / remove autostart
eye-guard --autostart
eye-guard --no-autostart
# Print the config
eye-guard --print-configEye Guard reads ~/.config/eye-guard/config.toml. If the file doesn't exist, an example is created on first run. If it's malformed, it's backed up and defaults are used.
# Minutes between short breaks (default: 20)
short_break_interval = 20
# Seconds each short break lasts (default: 20)
short_break_duration = 20
# Minutes between long breaks (default: 60)
long_break_interval = 60
# Seconds each long break lasts (default: 60)
long_break_duration = 60
# Seconds before a break to show a notification (default: 10)
pre_break_warning = 10
# Minutes to postpone a break (default: 5)
postpone_duration = 5
# Minutes after startup before the first break (default: 20)
first_break_delay = 20
# Skip breaks when the system is idle (X11 only, default: false)
smart_pause = falseEye Guard uses a pure Rust scheduler with no GTK dependency. The scheduler is a small state machine that produces renderer directives (Actions), which the GTK layer then renders. This separation means the core logic is fully unit-testable without a display server.
The system tray uses ksni (StatusNotifierItem), desktop notifications use notify-rust, and smart pause uses the XScreenSaver extension via x11rb.
eye-guard
├── model.rs # Domain types (BreakKind, BreakInfo, AppState, Mailbox)
├── config.rs # TOML config loading, validation, defaults
├── scheduler.rs # Pure state machine — no GTK, no I/O, fully testable
├── app.rs # GTK application glue: wires everything together
├── control.rs # UNIX socket for single-instance + CLI control
├── idle.rs # X11 idle detection (XScreenSaver extension)
├── autostart.rs # .desktop autostart entry management
└── ui/
├── break_screen.rs # Fullscreen break overlay
├── notify.rs # Desktop notifications
└── tray.rs # System tray icon (StatusNotifierItem)
| Feature | Eye Guard (Rust) | SafeEyes (Python) |
|---|---|---|
| Language | Rust | Python 3 |
| GUI toolkit | GTK 4 | GTK 4 (via PyGObject) |
| Memory usage | ~5 MB | ~30 MB |
| Startup time | Instant | ~1s |
| Config format | TOML | JSON |
| Smart pause | X11 (XScreenSaver) | X11 / Wayland |
| Tray icon | StatusNotifierItem | StatusNotifierItem |
| License | MIT | GPL-3.0 |
Built by Atheer (@atheerium).
If you find Eye Guard useful, consider buying me a coffee!
MIT