reminder-sink


Namereminder-sink JSON
Version 0.1.2 PyPI version JSON
download
home_pageNone
SummaryA unobtrusive, scriptable reminder/habit/todo task-runner
upload_time2025-09-09 07:49:14
maintainerNone
docs_urlNone
authorpurarue
requires_python>=3.10
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            This is an 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/scripts

Probably easiest explained with some examples of scripts this might run:

```bash
#!/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/purarue/albums
LISTENCOUNT="$(hpi query -r 1w my.nextalbums.history | jq 'length')" || exit 1

if [[ "${LISTENCOUNT}" == '0' ]]; then
    exit 2  # this has 'expired', exit code 2 means print the script name
else
    exit 0  # all good, I've listened to a new album recently
fi
```

[`flipflop`](https://purarue.xyz/d/flipflop.py?redirect) is 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 run `flipflop` when I'm away from my computer using [termux](https://termux.dev/en/) on my phone. The data for that is then synced to my computer with [syncthing](https://syncthing.net/)

Instead of adding some reminder system inside `flipflop`, `reminder-sink` is the 'sink' for the data:

```bash
#!/usr/bin/env bash
OUTPUT="$(flipflop.py status --filter-on -o json | jq 'keys[]' -r)"

if [[ -n "$OUTPUT" ]]; then
	echo "$OUTPUT"
	exit 3  # this has 'expired', exit code 3 prints the output of this script
fi
exit 0  # no output, nothing to do from flipflop
```

So, if I was to run `reminder-sink` and all of these had expired, I'd get something like:

```bash
$ reminder-sink run
listen_to_album   # from the name of the script
refill_medication  # these 2 lines were the output of 'flipflop.py status'
add_energy_bar
```

Instead 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 timeframe

I 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 I _have to_ do it at that moment,
else I'll forget or delay it, which is totally antithetical to actually building a habit

But, 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 eventually

I generally track my habits with my `Self` type using [`ttally`](https://github.com/purarue/ttally),
and use [`i3blocks`](https://github.com/vivien/i3blocks) for my status bar. [The block for
`reminder-sink`](https://purarue.xyz/d/b-reminder-sink?redirect) looks like this:

![image](https://github.com/purarue/reminder-sink/assets/7804791/0bc9706d-419c-41fe-91dc-217893ba2475)

```bash
#!/usr/bin/env bash

# if I left-click the icon, send a notification with what's expired
case "${BLOCK_BUTTON}" in
1)
    notify-send "$(reminder-sink run)"
    ;;
esac

reminder-sink run | wc -l
```

You could of course script together a little cron job that _does_ actually remind you once an hour if you have any expired jobs:

```bash
OUT="$(reminder-sink run)"
if [[ -n "${OUT}" ]]; then
    notify-send "${OUT}"
fi
```

Or just run `reminder-sink run` when you start up a new terminal or something, this is very flexible

You can see some of my other reminder-sink jobs [in my dotfiles](https://github.com/purarue/dotfiles/tree/master/.local/scripts/reminder-sink), but I use this for stuff like:

- reminding me to log my weight at least once a week
- making sure I drink enough water (using [`ttally`](https://github.com/purarue/ttally))
- listen to album once a week (by using my [spreadsheet](https://purarue.xyz/s/albums))
- tracking physical activity
- remind me to re-fill on medication when it runs out
- watch something on my movie/tv show backlog once every couple days (this gets tracked automatically by my [`mpv-history-daemon`](https://github.com/purarue/mpv-history-daemon))

## Usage

```
Usage: 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/purarue/reminder-sink for more information
```

This uses the shebang of the script (e.g. `#!/usr/bin/env bash` or `#!/usr/bin/python3`) to determine
what to run the file with. If it can't detect properly, it uses `bash` (you can change that like `REMINDER_SINK_DEFAULT_INTERPRETER=python`)

## Example

```
$ reminder-sink list
Script(path=PosixPath('/home/username/data/reminder-sink/self_type_common.py'), enabled=False)
Script(path=PosixPath('/home/username/data/reminder-sink/physical_activity.enabled'), enabled=True)
Script(path=PosixPath('/home/username/data/reminder-sink/mal_sources'), enabled=False)
Script(path=PosixPath('/home/username/.local/scripts/reminder-sink/flipflop'), enabled=True)
Script(path=PosixPath('/home/username/.local/scripts/reminder-sink/weight'), enabled=True)
Script(path=PosixPath('/home/username/.local/scripts/reminder-sink/listen_to_album'), enabled=True)
Script(path=PosixPath('/home/username/.local/scripts/reminder-sink/food'), enabled=True)
Script(path=PosixPath('/home/username/.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/username/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/username/data/reminder-sink/physical_activity.enabled'
2023-10-06 00:54:28,199 DEBUG - mal_sources: Starting '/usr/bin/env bash /home/username/data/reminder-sink/mal_sources'
2023-10-06 00:54:28,199 DEBUG - reminder-sink: finished searching /home/username/data/reminder-sink
2023-10-06 00:54:28,199 DEBUG - reminder-sink: Searching /home/username/.local/scripts/reminder-sink
2023-10-06 00:54:28,200 DEBUG - flipflop: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/flipflop'
2023-10-06 00:54:28,201 DEBUG - weight: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/weight'
2023-10-06 00:54:28,203 DEBUG - listen_to_album: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/listen_to_album'
2023-10-06 00:54:28,203 DEBUG - food: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/food'
2023-10-06 00:54:28,204 DEBUG - reminder-sink: finished searching /home/username/.local/scripts/reminder-sink
2023-10-06 00:54:28,204 DEBUG - water: Starting '/usr/bin/env bash /home/username/.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 reminders
```

If you want to debug the current silenced status, pass debug like `reminder-sink --debug silence list`

I have a binding in my [i3 blocklet](https://purarue.xyz/d/b-reminder-sink?redirect) that lets me quickly ignore an active reminder using [`fzf`](https://github.com/junegunn/fzf) and [`evry duration`](https://github.com/purarue/evry#duration) to allow me to pick an active reminder and enter a [human readable duration](https://github.com/purarue/evry#duration). See [`reminder-sink-silence`](https://purarue.xyz/d/reminder-sink-silence?redirect)

## Installation

Requires `python3.10+`

To install with pip, run:

```
pip install reminder-sink
```

### Tests

```bash
git clone 'https://github.com/purarue/reminder-sink'
cd ./reminder-sink
pip install '.[testing]'
flake8 ./reminder_sink
mypy ./reminder_sink
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "reminder-sink",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": null,
    "author": "purarue",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/21/de/2dc07ab76b634b3346b32911e5e13d8597f233cf8b1d31a4ab947fa61315/reminder_sink-0.1.2.tar.gz",
    "platform": null,
    "description": "This is an unobtrusive, scriptable reminder/habit/todo task-runner. This does\nnot actually have any way to setup/remind you for specific habits/tasks, it\nprovides more of a set of rules which make for an unobtrusive reminder/habit\ntracker, it acts as the \"sink\" for all my other tools/scripts\n\nProbably easiest explained with some examples of scripts this might run:\n\n```bash\n#!/usr/bin/env bash\n# remind me to listen to a new album once a week\n\n# interfaces with my spreadsheet where I track my albums\n# https://github.com/purarue/albums\nLISTENCOUNT=\"$(hpi query -r 1w my.nextalbums.history | jq 'length')\" || exit 1\n\nif [[ \"${LISTENCOUNT}\" == '0' ]]; then\n    exit 2  # this has 'expired', exit code 2 means print the script name\nelse\n    exit 0  # all good, I've listened to a new album recently\nfi\n```\n\n[`flipflop`](https://purarue.xyz/d/flipflop.py?redirect) is 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.\n\nI'll often run `flipflop` when I'm away from my computer using [termux](https://termux.dev/en/) on my phone. The data for that is then synced to my computer with [syncthing](https://syncthing.net/)\n\nInstead of adding some reminder system inside `flipflop`, `reminder-sink` is the 'sink' for the data:\n\n```bash\n#!/usr/bin/env bash\nOUTPUT=\"$(flipflop.py status --filter-on -o json | jq 'keys[]' -r)\"\n\nif [[ -n \"$OUTPUT\" ]]; then\n\techo \"$OUTPUT\"\n\texit 3  # this has 'expired', exit code 3 prints the output of this script\nfi\nexit 0  # no output, nothing to do from flipflop\n```\n\nSo, if I was to run `reminder-sink` and all of these had expired, I'd get something like:\n\n```bash\n$ reminder-sink run\nlisten_to_album   # from the name of the script\nrefill_medication  # these 2 lines were the output of 'flipflop.py status'\nadd_energy_bar\n```\n\nInstead of reminding me once a day to do something, this uses local data (or an API request\nif you want -- its just a script, you can do whatever you want!) to determine if I've done\nit within the timeframe\n\nI really dislike habit building/reminder apps that interrupt me while Im doing other things.\nWhen I get the notification to remind me to do something, it feels like I _have to_ do it at that moment,\nelse I'll forget or delay it, which is totally antithetical to actually building a habit\n\nBut, if there's no reminder, I often forget to do things.\n\nInstead, this displays the number of tasks which have expired in my menu bar. So, its\nstill visible to me and I'll glance whenever I have a free minute, but I don't\nget interrupted or feel like I have to 'snooze'/delay the habit.\n\nI also don't feel too horrible if there's a number there for a couple hours, I get\naround to the task eventually\n\nI generally track my habits with my `Self` type using [`ttally`](https://github.com/purarue/ttally),\nand use [`i3blocks`](https://github.com/vivien/i3blocks) for my status bar. [The block for\n`reminder-sink`](https://purarue.xyz/d/b-reminder-sink?redirect) looks like this:\n\n![image](https://github.com/purarue/reminder-sink/assets/7804791/0bc9706d-419c-41fe-91dc-217893ba2475)\n\n```bash\n#!/usr/bin/env bash\n\n# if I left-click the icon, send a notification with what's expired\ncase \"${BLOCK_BUTTON}\" in\n1)\n    notify-send \"$(reminder-sink run)\"\n    ;;\nesac\n\nreminder-sink run | wc -l\n```\n\nYou could of course script together a little cron job that _does_ actually remind you once an hour if you have any expired jobs:\n\n```bash\nOUT=\"$(reminder-sink run)\"\nif [[ -n \"${OUT}\" ]]; then\n    notify-send \"${OUT}\"\nfi\n```\n\nOr just run `reminder-sink run` when you start up a new terminal or something, this is very flexible\n\nYou can see some of my other reminder-sink jobs [in my dotfiles](https://github.com/purarue/dotfiles/tree/master/.local/scripts/reminder-sink), but I use this for stuff like:\n\n- reminding me to log my weight at least once a week\n- making sure I drink enough water (using [`ttally`](https://github.com/purarue/ttally))\n- listen to album once a week (by using my [spreadsheet](https://purarue.xyz/s/albums))\n- tracking physical activity\n- remind me to re-fill on medication when it runs out\n- watch something on my movie/tv show backlog once every couple days (this gets tracked automatically by my [`mpv-history-daemon`](https://github.com/purarue/mpv-history-daemon))\n\n## Usage\n\n```\nUsage: reminder-sink [OPTIONS] COMMAND [ARGS]...\n\n  reminders-sink is a script that takes other scripts as input and runs them\n  in parallel. The exit code of each script it runs determines what reminder-\n  sink does:\n\n  0: I've done this task recently, no need to warn\n  2: I haven't done this task recently, print the script name\n  3: I haven't done this task recently, print the output of the script\n  Anything else: Fatal error\n\n  You can set the REMINDER_SINK_PATH environment variable to a colon-delimited\n  list of directories that contain reminder-sink jobs. For example, in your\n  shell profile, set:\n\n  export REMINDER_SINK_PATH=\"${HOME}/.local/share/reminder-sink:${HOME}/Documents/reminder-sink\"\n\n  This scans the directories for executables and runs them in parallel. A\n  script is considered enabled if it is executable or if the file name ends\n  with '.enabled'.\n\nOptions:\n  -d, --debug  print debug information  [env var: REMINDER_SINK_DEBUG]\n  -h, --help   Show this message and exit.\n\nCommands:\n  list     list all scripts\n  run      run all scripts in parallel\n  silence  temporarily silence a reminder\n  test     test a script\n\n  See https://github.com/purarue/reminder-sink for more information\n```\n\nThis uses the shebang of the script (e.g. `#!/usr/bin/env bash` or `#!/usr/bin/python3`) to determine\nwhat to run the file with. If it can't detect properly, it uses `bash` (you can change that like `REMINDER_SINK_DEFAULT_INTERPRETER=python`)\n\n## Example\n\n```\n$ reminder-sink list\nScript(path=PosixPath('/home/username/data/reminder-sink/self_type_common.py'), enabled=False)\nScript(path=PosixPath('/home/username/data/reminder-sink/physical_activity.enabled'), enabled=True)\nScript(path=PosixPath('/home/username/data/reminder-sink/mal_sources'), enabled=False)\nScript(path=PosixPath('/home/username/.local/scripts/reminder-sink/flipflop'), enabled=True)\nScript(path=PosixPath('/home/username/.local/scripts/reminder-sink/weight'), enabled=True)\nScript(path=PosixPath('/home/username/.local/scripts/reminder-sink/listen_to_album'), enabled=True)\nScript(path=PosixPath('/home/username/.local/scripts/reminder-sink/food'), enabled=True)\nScript(path=PosixPath('/home/username/.local/scripts/reminder-sink/water'), enabled=True)\n```\n\nThis runs the scripts in parallel, with the number of threads equal to the number of cores you have available:\n\n```\n$ reminder-sink --debug run\n2023-10-06 00:54:28,197 DEBUG - reminder-sink: Running scripts with 16 threads\n2023-10-06 00:54:28,197 DEBUG - reminder-sink: Searching /home/username/data/reminder-sink\n2023-10-06 00:54:28,197 DEBUG - self_type_common: not enabled\n2023-10-06 00:54:28,197 DEBUG - physical_activity: Starting '/usr/bin/env bash /home/username/data/reminder-sink/physical_activity.enabled'\n2023-10-06 00:54:28,199 DEBUG - mal_sources: Starting '/usr/bin/env bash /home/username/data/reminder-sink/mal_sources'\n2023-10-06 00:54:28,199 DEBUG - reminder-sink: finished searching /home/username/data/reminder-sink\n2023-10-06 00:54:28,199 DEBUG - reminder-sink: Searching /home/username/.local/scripts/reminder-sink\n2023-10-06 00:54:28,200 DEBUG - flipflop: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/flipflop'\n2023-10-06 00:54:28,201 DEBUG - weight: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/weight'\n2023-10-06 00:54:28,203 DEBUG - listen_to_album: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/listen_to_album'\n2023-10-06 00:54:28,203 DEBUG - food: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/food'\n2023-10-06 00:54:28,204 DEBUG - reminder-sink: finished searching /home/username/.local/scripts/reminder-sink\n2023-10-06 00:54:28,204 DEBUG - water: Starting '/usr/bin/env bash /home/username/.local/scripts/reminder-sink/water'\n2023-10-06 00:54:28,218 DEBUG - mal_sources: (took 0.01922) with exit code 0 and output ''\n2023-10-06 00:54:28,306 DEBUG - flipflop: (took 0.10657) with exit code 0 and output ''\n2023-10-06 00:54:28,319 DEBUG - physical_activity: (took 0.12172) with exit code 0 and output ''\n2023-10-06 00:54:28,321 DEBUG - weight: (took 0.12033) with exit code 0 and output ''\n2023-10-06 00:54:28,346 DEBUG - food: (took 0.14306) with exit code 0 and output ''\n2023-10-06 00:54:28,357 DEBUG - water: (took 0.15303) with exit code 0 and output ''\n2023-10-06 00:54:28,436 DEBUG - listen_to_album: (took 0.23399) with exit code 0 and output ''\n```\n\nTo temporarily silence a reminder, you can use the 'silence' command:\n\n```\nUsage: reminder-sink silence [OPTIONS] COMMAND [ARGS]...\n\n  Silences a reminder for some duration\n\n  This can be useful to ignore a reminder temporarily without modifying the\n  underlying mechanism to check for the reminder\n\n  To change the location of the file where this stores silenced reminders, you\n  can set the REMINDER_SINK_SILENT_FILE envvar\n\nOptions:\n  -h, --help  Show this message and exit.\n\nCommands:\n  add    silence a reminder\n  file   print location of silenced reminders file\n  list   list silenced reminders\n  reset  reset all silenced reminders\n```\n\nIf you want to debug the current silenced status, pass debug like `reminder-sink --debug silence list`\n\nI have a binding in my [i3 blocklet](https://purarue.xyz/d/b-reminder-sink?redirect) that lets me quickly ignore an active reminder using [`fzf`](https://github.com/junegunn/fzf) and [`evry duration`](https://github.com/purarue/evry#duration) to allow me to pick an active reminder and enter a [human readable duration](https://github.com/purarue/evry#duration). See [`reminder-sink-silence`](https://purarue.xyz/d/reminder-sink-silence?redirect)\n\n## Installation\n\nRequires `python3.10+`\n\nTo install with pip, run:\n\n```\npip install reminder-sink\n```\n\n### Tests\n\n```bash\ngit clone 'https://github.com/purarue/reminder-sink'\ncd ./reminder-sink\npip install '.[testing]'\nflake8 ./reminder_sink\nmypy ./reminder_sink\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A unobtrusive, scriptable reminder/habit/todo task-runner",
    "version": "0.1.2",
    "project_urls": {
        "Homepage": "https://github.com/purarue/reminder-sink"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b4d39ac198ac20fbcf019a7f85b6a217a3925ce99a07ef1fdf88bb5edb00ff7a",
                "md5": "0245ae833a0ea4d5be0dd18f77ae1eb2",
                "sha256": "c59d6ba5e6b1bd8e427ccb4848dc7735c4610486a5186f153f214ba3b2e25402"
            },
            "downloads": -1,
            "filename": "reminder_sink-0.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0245ae833a0ea4d5be0dd18f77ae1eb2",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 11853,
            "upload_time": "2025-09-09T07:49:13",
            "upload_time_iso_8601": "2025-09-09T07:49:13.061985Z",
            "url": "https://files.pythonhosted.org/packages/b4/d3/9ac198ac20fbcf019a7f85b6a217a3925ce99a07ef1fdf88bb5edb00ff7a/reminder_sink-0.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "21de2dc07ab76b634b3346b32911e5e13d8597f233cf8b1d31a4ab947fa61315",
                "md5": "50e47f655c6e971ff4babe985389c6c1",
                "sha256": "85498e778e9c4592a67e8a0b92c3f1129f70c781f39c19ee2bca9b7fc1ce5dc3"
            },
            "downloads": -1,
            "filename": "reminder_sink-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "50e47f655c6e971ff4babe985389c6c1",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 14140,
            "upload_time": "2025-09-09T07:49:14",
            "upload_time_iso_8601": "2025-09-09T07:49:14.196220Z",
            "url": "https://files.pythonhosted.org/packages/21/de/2dc07ab76b634b3346b32911e5e13d8597f233cf8b1d31a4ab947fa61315/reminder_sink-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-09 07:49:14",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "purarue",
    "github_project": "reminder-sink",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "reminder-sink"
}
        
Elapsed time: 0.69904s