Okay, I was testing with the AI Claude and this came up, which works, although with a 1 minute delay and we couldn’t improve it. ![]()
(Modify the PATHs if necessary)
In $HOME.config/systemd/user/
todo-alarm.service:
[Unit]
Description=Todo.txt reminder
[Service]
Type=oneshot
ExecStart=%h/.local/bin/todo-alarm.sh
[Install]
WantedBy=default.target
and
todo-alarm.timer:
[Unit]
Description=Run todo alarm checker
[Timer]
OnCalendar=*-*-* *:*:00
OnCalendar=*-*-* *:*:30
Persistent=true
[Install]
WantedBy=timers.target
The script
todo-alarm.sh:
(I use Dunst for notifications and MPV for audio)
#!/bin/bash
TODO="$HOME/.todo/todo.txt"
# Obtener DBUS desde el proceso openbox
USER_ID=$(id -u)
SESS_PID=$(pgrep -u "$USER_ID" openbox 2>/dev/null | head -1)
if [[ -n "$SESS_PID" ]]; then
DBUS_ADDR=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/"$SESS_PID"/environ 2>/dev/null \
| tr -d '\0' | sed 's/DBUS_SESSION_BUS_ADDRESS=//')
export DBUS_SESSION_BUS_ADDRESS="$DBUS_ADDR"
fi
export DISPLAY=:0
NOW=$(date +%s)
WINDOW_START=$((NOW - 60))
TMP=$(mktemp)
while IFS= read -r line; do
# grep oP avoids the BASH_REMATCH bug with lines that begin with
ALARM=$(echo "$line" | grep -oP '(?<=alarm:)\S+')
if [[ -n "$ALARM" ]] && [[ "$line" != *"notified:yes"* ]]; then
DATE_PART="${ALARM%T*}"
TIME_PART="${ALARM#*T}"
ALARM_TS=$(date -d "$DATE_PART $TIME_PART" +%s 2>/dev/null)
if [[ -n "$ALARM_TS" ]] && (( ALARM_TS <= NOW && ALARM_TS > WINDOW_START )); then
# Show the clean task, without the alarm tag.:...
TASK=$(echo "$line" | sed 's/alarm:[^ ]*//' | sed 's/ */ /g' | xargs)
notify-send -u critical -t 0 "📋 Recordatorio" "$TASK"
mpv --no-video "$HOME/Música/ding-47489.mp3" >/dev/null 2>&1
line="$line notified:yes"
fi
fi
echo "$line" >> "$TMP"
done < "$TODO"
mv "$TMP" "$TODO"
Then enable and load the services.
my test .todo.txt
(B) 2026-03-13 alarm:2026-03-13T18:21 plin +Project
2026-03-13 Probar recordatorio alarm:2026-03-13T18:22
that after the alarms it looks like this:
(B) 2026-03-13 alarm:2026-03-13T18:21 plin +Project notified:yes
2026-03-13 Probar recordatorio alarm:2026-03-13T18:22 notified:yes
I hope it’s useful and that you can improve it.
![]()
