Package: reminder-sink
This is a unobtrusive, scriptable reminder/habit/todo task-runner. This does
not actually have any way to setup/remind you for specific habits/tasks, it
provides more of a set of rules which make for an unobtrusive reminder/habit
tracker, it acts as the "sink" for all my other tools/scriptsProbably easiest explained with some examples of scripts this might run:#!/usr/bin/env bash# remind me to listen to a new album once a week# interfaces with my spreadsheet where I track my albums# https://github.com/seanbreckenridge/albumsLISTENCOUNT="$(hpiquery-r1wmy.nextalbums.history|jq'length')"||exit1if[["${LISTENCOUNT}"=='0']];thenexit2# this has 'expired', exit code 2 means print the script nameelseexit0# all good, I've listened to a new album recentlyfiflipflopis a tool which lets me toggle todos for things that I need to do often. Think like: re-add an energy bar to my bag, refill medication.I'll often runflipflopwhen I'm away from my computer usingtermuxon my phone. The data for that is then synced to my computer withsyncthingInstead of adding some reminder system insideflipflop,reminder-sinkis the 'sink' for the data:#!/usr/bin/env bashOUTPUT="$(flipflop.pystatus--filter-on-ojson|jq'keys[]'-r)"if[[-n"$OUTPUT"]];thenecho"$OUTPUT"exit3# this has 'expired', exit code 3 prints the output of this scriptfiexit0# no output, nothing to do from flipflopSo, if I was to runreminder-sinkand all of these had expired, I'd get something like:$reminder-sinkrun
listen_to_album# from the name of the scriptrefill_medication# these 2 lines were the output of 'flipflop.py status'add_energy_barInstead of reminding me once a day to do something, this uses local data (or an API request
if you want -- its just a script, you can do whatever you want!) to determine if I've done
it within the timeframeI really dislike habit building/reminder apps that interrupt me while Im doing other things.
When I get the notification to remind me to do something, it feels like Ihave todo it at that moment,
else I'll forget or delay it, which is totally antithetical to actually building a habitBut, if there's no reminder, I often forget to do things.Instead, this displays the number of tasks which have expired in my menu bar. So, its
still visible to me and I'll glance whenever I have a free minute, but I don't
get interrupted or feel like I have to 'snooze'/delay the habit.I also don't feel too horrible if there's a number there for a couple hours, I get
around to the task eventuallyI generally track my habits with mySelftype usingttally,
and usei3blocksfor my status bar.The block forreminder-sinklooks like this:#!/usr/bin/env bash# if I left-click the icon, send a notification with what's expiredcase"${BLOCK_BUTTON}"in1)notify-send"$(reminder-sinkrun)";;esacreminder-sinkrun|wc-lYou could of course script together a little cron job thatdoesactually remind you once an hour if you have any expired jobs:OUT="$(reminder-sinkrun)"if[[-n"${OUT}"]];thennotify-send"${OUT}"fiOr just runreminder-sink runwhen you start up a new terminal or something, this is very flexibleYou can see some of my other reminder-sink jobsin my dotfiles, but I use this for stuff like:reminding me to log my weight at least once a weekmaking sure I drink enough water (usingttally)listen to album once a week (by using myspreadsheet)tracking physical activityremind me to re-fill on medication when it runs outwatch something on my movie/tv show backlog once every couple days (this gets tracked automatically by mympv-history-daemon)UsageUsage: reminder-sink [OPTIONS] COMMAND [ARGS]...

  reminders-sink is a script that takes other scripts as input and runs them
  in parallel. The exit code of each script it runs determines what reminder-
  sink does:

  0: I've done this task recently, no need to warn
  2: I haven't done this task recently, print the script name
  3: I haven't done this task recently, print the output of the script
  Anything else: Fatal error

  You can set the REMINDER_SINK_PATH environment variable to a colon-delimited
  list of directories that contain reminder-sink jobs. For example, in your
  shell profile, set:

  export REMINDER_SINK_PATH="${HOME}/.local/share/reminder-sink:${HOME}/Documents/reminder-sink"

  This scans the directories for executables and runs them in parallel. A
  script is considered enabled if it is executable or if the file name ends
  with '.enabled'.

Options:
  -d, --debug  print debug information  [env var: REMINDER_SINK_DEBUG]
  -h, --help   Show this message and exit.

Commands:
  list     list all scripts
  run      run all scripts in parallel
  silence  temporarily silence a reminder
  test     test a script

  See https://github.com/seanbreckenridge/reminder-sink for more informationThis uses the shebang of the script (e.g.#!/usr/bin/env bashor#!/usr/bin/python3) to determine
what to run the file with. If it can't detect properly, it usesbash(you can change that likeREMINDER_SINK_DEFAULT_INTERPRETER=python)Example$ reminder-sink list
Script(path=PosixPath('/home/sean/data/reminder-sink/self_type_common.py'), enabled=False)
Script(path=PosixPath('/home/sean/data/reminder-sink/physical_activity.enabled'), enabled=True)
Script(path=PosixPath('/home/sean/data/reminder-sink/mal_sources'), enabled=False)
Script(path=PosixPath('/home/sean/.local/scripts/reminder-sink/flipflop'), enabled=True)
Script(path=PosixPath('/home/sean/.local/scripts/reminder-sink/weight'), enabled=True)
Script(path=PosixPath('/home/sean/.local/scripts/reminder-sink/listen_to_album'), enabled=True)
Script(path=PosixPath('/home/sean/.local/scripts/reminder-sink/food'), enabled=True)
Script(path=PosixPath('/home/sean/.local/scripts/reminder-sink/water'), enabled=True)This runs the scripts in parallel, with the number of threads equal to the number of cores you have available:$ reminder-sink --debug run
2023-10-06 00:54:28,197 DEBUG - reminder-sink: Running scripts with 16 threads
2023-10-06 00:54:28,197 DEBUG - reminder-sink: Searching /home/sean/data/reminder-sink
2023-10-06 00:54:28,197 DEBUG - self_type_common: not enabled
2023-10-06 00:54:28,197 DEBUG - physical_activity: Starting '/usr/bin/env bash /home/sean/data/reminder-sink/physical_activity.enabled'
2023-10-06 00:54:28,199 DEBUG - mal_sources: Starting '/usr/bin/env bash /home/sean/data/reminder-sink/mal_sources'
2023-10-06 00:54:28,199 DEBUG - reminder-sink: finished searching /home/sean/data/reminder-sink
2023-10-06 00:54:28,199 DEBUG - reminder-sink: Searching /home/sean/.local/scripts/reminder-sink
2023-10-06 00:54:28,200 DEBUG - flipflop: Starting '/usr/bin/env bash /home/sean/.local/scripts/reminder-sink/flipflop'
2023-10-06 00:54:28,201 DEBUG - weight: Starting '/usr/bin/env bash /home/sean/.local/scripts/reminder-sink/weight'
2023-10-06 00:54:28,203 DEBUG - listen_to_album: Starting '/usr/bin/env bash /home/sean/.local/scripts/reminder-sink/listen_to_album'
2023-10-06 00:54:28,203 DEBUG - food: Starting '/usr/bin/env bash /home/sean/.local/scripts/reminder-sink/food'
2023-10-06 00:54:28,204 DEBUG - reminder-sink: finished searching /home/sean/.local/scripts/reminder-sink
2023-10-06 00:54:28,204 DEBUG - water: Starting '/usr/bin/env bash /home/sean/.local/scripts/reminder-sink/water'
2023-10-06 00:54:28,218 DEBUG - mal_sources: (took 0.01922) with exit code 0 and output ''
2023-10-06 00:54:28,306 DEBUG - flipflop: (took 0.10657) with exit code 0 and output ''
2023-10-06 00:54:28,319 DEBUG - physical_activity: (took 0.12172) with exit code 0 and output ''
2023-10-06 00:54:28,321 DEBUG - weight: (took 0.12033) with exit code 0 and output ''
2023-10-06 00:54:28,346 DEBUG - food: (took 0.14306) with exit code 0 and output ''
2023-10-06 00:54:28,357 DEBUG - water: (took 0.15303) with exit code 0 and output ''
2023-10-06 00:54:28,436 DEBUG - listen_to_album: (took 0.23399) with exit code 0 and output ''To temporarily silence a reminder, you can use the 'silence' command:Usage: reminder-sink silence [OPTIONS] COMMAND [ARGS]...

  Silences a reminder for some duration

  This can be useful to ignore a reminder temporarily without modifying the
  underlying mechanism to check for the reminder

  To change the location of the file where this stores silenced reminders, you
  can set the REMINDER_SINK_SILENT_FILE envvar

Options:
  -h, --help  Show this message and exit.

Commands:
  add    silence a reminder
  file   print location of silenced reminders file
  list   list silenced reminders
  reset  reset all silenced remindersI have a binding in myi3 blockletthat lets me quickly ignore an active reminder withfzf:reminder-sinksilenceadd"$(reminder-sinkrun|fzf--header="What to silence?")"InstallationRequirespython3.10+To install with pip, run:pip install reminder-sinkTestsgitclone'https://github.com/seanbreckenridge/reminder-sink'cd./reminder-sink
pipinstall'.[testing]'flake8./reminder_sink
mypy./reminder_sink