Get visible pop-up alerts when your laptop battery:
- discharging and drops below a threshold
- charging and reaches a target level.
Popups appear centered at your mouse cursor (X11 only).
⚠️ Cursor-centering uses xdotool/wmctrl which require Xorg (X11). On Wayland, notifications will work but won’t be repositioned at the cursor.
- Set low battery and charging reached thresholds.
- Pops up near the cursor so you don’t miss it.
- Runs automatically via systemd user timer.
- Optional auto-dismiss timeout.
Install these packages:
# Debian/Ubuntu/Pop!_OS
sudo apt install upower zenity xdotool wmctrlSystemd (user) doesn’t automatically inherit your desktop env. Add this line so your service can access your display & D-Bus:
- zsh: add to ~/.zprofile
- bash: add to ~/.profile
# Make desktop env vars available to systemd --user on login
systemctl --user import-environment DISPLAY WAYLAND_DISPLAY DBUS_SESSION_BUS_ADDRESS XDG_RUNTIME_DIRLog out and back in (or run that command once in a terminal now).
Verify:
systemctl --user show-environment | egrep 'DISPLAY|DBUS|XDG_RUNTIME_DIR'The variables should be visible. I.e.
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1001/bus
DISPLAY=:1
XDG_RUNTIME_DIR=/run/user/1001Place the files like this (adjust paths if you prefer):
~/bin/battery-alert.sh
~/.config/systemd/user/battery-alert.service
~/.config/systemd/user/battery-alert.timer
chmod +x ~/bin/battery-alert.shOpen ~/bin/battery-alert.sh and tweak:
LOW_BATTERY=20 # notify when discharging at/below this %
CHARGED_LEVEL=95 # notify when charging at/above this %
POPUP_TIMEOUT=8 # seconds; set 0 to require manual close
POPUP_WIDTH=280
POPUP_HEIGHT=120systemctl --user daemon-reload
systemctl --user enable --now battery-alert.timer
systemctl --user list-timers | grep battery-alertsystemctl --user start battery-alert.service
journalctl --user -u battery-alert.service -n 50 --no-pagerYou should see a popup when thresholds are met. (You can also temporarily set LOW_BATTERY=100 to force a low-battery alert for testing while on battery.)
systemctl --user disable --now battery-alert.timer
rm -f ~/.config/systemd/user/battery-alert.{service,timer}
rm -f ~/bin/battery-alert.sh
systemctl --user daemon-reload- Ensure the script waits for the popup PID (already implemented).
- Avoid backgrounding zenity without waiting; systemd will end the cgroup when the oneshot service exits.
- Your user manager lacks GUI env vars. Re-login after adding the line in Step 1 to ~/.zprofile or ~/.profile, or run:
systemctl --user import-environment DISPLAY WAYLAND_DISPLAY DBUS_SESSION_BUS_ADDRESS XDG_RUNTIME_DIR
- You’re probably on Wayland. Use an Xorg session (login screen → gear icon → GNOME on Xorg), or accept non-centered popups.
- Use the timer + oneshot setup in this repo (don’t set Restart=always on a oneshot that exits quickly).
journalctl --user -u battery-alert.service -n 100 --no-pager- The timer runs battery-alert.service every 60s.
- The script reads battery state/percentage via upower.
- If thresholds are hit, it opens a zenity window and uses xdotool/wmctrl to center it at the cursor.
- The script waits for the popup to close (or time out), keeping the systemd unit alive so the popup isn’t killed.
MIT