about summary refs log tree commit diff stats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/by-name/ca/cargo/module.nix18
-rw-r--r--modules/by-name/fi/firefox/module.nix2
-rw-r--r--modules/by-name/fi/firefox/profile.nix5
-rw-r--r--modules/by-name/fi/firefox/search_engines/default.nix28
-rw-r--r--modules/by-name/lf/lf/commands/default.nix5
-rwxr-xr-xmodules/by-name/lf/lf/commands/scripts/open.sh15
-rwxr-xr-xmodules/by-name/lf/lf/commands/scripts/trash_restore.sh1
-rw-r--r--modules/by-name/lf/lf/ctpv/default.nix41
-rw-r--r--modules/by-name/lf/lf/ctpv/helpers.sh2
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/any.sh13
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/archive/atool.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/dll/dll.sh9
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/epub/default.nix10
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/epub/epub.sh9
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/pdf/default.nix1
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/pdf/pdf.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/pgp/pgp.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/sqlite/sqlite.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/x-bittorrent/torrent.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/default.nix11
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/pem.sh8
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/audio/audio.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/audio/default.nix1
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/default.nix9
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/font/default.nix1
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/font/font.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/image/image.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/image/svg+xml/svg.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/image/x-xcf/xcf.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/inode/ls.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/inode/symlink.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/libreoffice.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/text/bat.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/text/diff/delta.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/text/glow.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/text/html/default.nix13
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/text/html/elinks.sh18
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/text/json/jq.sh5
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/video/video.sh5
-rw-r--r--modules/by-name/lf/lf/module.nix2
-rw-r--r--modules/by-name/mp/mpd/mpc.nix5
-rw-r--r--modules/by-name/nv/nvim/plgs/harpoon/default.nix116
-rw-r--r--modules/by-name/nv/nvim/plgs/lf-nvim/default.nix10
-rw-r--r--modules/by-name/nv/nvim/plgs/telescope/extensions/bibtex/default.nix5
-rw-r--r--modules/by-name/ta/taskwarrior/module.nix21
-rw-r--r--modules/by-name/ti/timewarrior/module.nix36
-rwxr-xr-xmodules/by-name/ti/timewarrior/taskwarirror_hooks/on-modify_track-timewarrior.py94
-rwxr-xr-xmodules/by-name/ti/timewarrior/taskwarrior_hooks/on-modify.track-timewarrior.py124
-rwxr-xr-xmodules/by-name/ti/timewarrior/taskwarrior_hooks/on-modify.track-total-active-time.py (renamed from modules/by-name/ti/timewarrior/taskwarirror_hooks/on-modify_track-total-active-time.py)43
-rw-r--r--modules/by-name/ts/tskm/module.nix9
-rw-r--r--modules/by-name/wa/water-reminder/module.nix57
-rw-r--r--modules/by-name/xd/xdg/module.nix123
-rwxr-xr-xmodules/by-name/xd/xdg/scripts/lf-wrapper.sh (renamed from modules/by-name/xd/xdg/lf-wrapper.sh)0
-rwxr-xr-xmodules/by-name/xd/xdg/scripts/url-handler.sh (renamed from modules/home.legacy/conf/xdg/url_handler.sh)7
-rw-r--r--modules/by-name/zs/zsh/module.nix5
-rw-r--r--modules/common/default.nix5
-rw-r--r--modules/home.legacy/conf/default.nix2
-rw-r--r--modules/home.legacy/conf/mail/accounts/soispha.nix4
-rw-r--r--modules/home.legacy/conf/xdg/default.nix59
-rw-r--r--modules/home.legacy/conf/xdg/xdg_vars.nix29
-rw-r--r--modules/home.legacy/conf/ytcc/default.nix11
-rw-r--r--modules/home.legacy/conf/ytcc/ytcc.conf37
-rw-r--r--modules/home.legacy/pkgs/default.nix5
63 files changed, 448 insertions, 671 deletions
diff --git a/modules/by-name/ca/cargo/module.nix b/modules/by-name/ca/cargo/module.nix
new file mode 100644
index 00000000..f7153509
--- /dev/null
+++ b/modules/by-name/ca/cargo/module.nix
@@ -0,0 +1,18 @@
+{
+  config,
+  lib,
+  ...
+}: let
+  cfg = config.soispha.programs.cargo;
+in {
+  options.soispha.programs.cargo = {
+    enable = lib.mkEnableOption "cargo";
+  };
+  config = lib.mkIf cfg.enable {
+    home-manager.users.soispha = {
+      home.sessionVariables = {
+        CARGO_HOME = "${config.home-manager.users.soispha.xdg.dataHome}/cargo";
+      };
+    };
+  };
+}
diff --git a/modules/by-name/fi/firefox/module.nix b/modules/by-name/fi/firefox/module.nix
index feeb8198..17bfa049 100644
--- a/modules/by-name/fi/firefox/module.nix
+++ b/modules/by-name/fi/firefox/module.nix
@@ -120,7 +120,7 @@ in {
       enable = true;
       preferencesStatus = "locked";
 
-      languagePacks = ["de" "sv-SE" "en-CA"];
+      languagePacks = ["en-CA" "de" "sv-SE"];
 
       nativeMessagingHosts.packages = [
         pkgs.tridactyl-native
diff --git a/modules/by-name/fi/firefox/profile.nix b/modules/by-name/fi/firefox/profile.nix
index 7cdf4d90..195c2075 100644
--- a/modules/by-name/fi/firefox/profile.nix
+++ b/modules/by-name/fi/firefox/profile.nix
@@ -1,4 +1,7 @@
-{config, pkgs}: preConfig: ({
+{
+  config,
+  pkgs,
+}: preConfig: ({
     userChrome = ./userChrome.css;
 
     bookmarks = {
diff --git a/modules/by-name/fi/firefox/search_engines/default.nix b/modules/by-name/fi/firefox/search_engines/default.nix
index d05a5af8..51a447e1 100644
--- a/modules/by-name/fi/firefox/search_engines/default.nix
+++ b/modules/by-name/fi/firefox/search_engines/default.nix
@@ -1,6 +1,6 @@
 {pkgs, ...}: {
   # DEFAULT
-  brave-search= {
+  brave-search = {
     name = "Brave Search";
     urls = [{template = "https://search.brave.com/search?q={searchTerms}";}];
     icon = ./logos/brave.svg;
@@ -8,53 +8,53 @@
   };
 
   # NIX
-  nix-packages= {
+  nix-packages = {
     name = "Nix packages";
     urls = [{template = "https://search.nixos.org/packages?type=packages&query={searchTerms}";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
     definedAliases = ["@np"];
   };
 
-  nix-functions= {
+  nix-functions = {
     name = "Nix functions";
     urls = [{template = "https://noogle.dev/q?term={searchTerms}";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
     definedAliases = ["@ng"];
   };
 
-  nixos-options= {
+  nixos-options = {
     name = "NixOS options";
     urls = [{template = "https://search.nixos.org/options?type=options&query={searchTerms}";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
     definedAliases = ["@no"];
   };
-  homemanager-options= {
+  homemanager-options = {
     name = "Home-Manager options";
     urls = [{template = "https://home-manager-options.extranix.com/?query={searchTerms}&release=master";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
     definedAliases = ["@nh"];
   };
 
-  nixpkgs-issues= {
+  nixpkgs-issues = {
     name = "Nixpkgs issues";
     urls = [{template = "https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+{searchTerms}";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
     definedAliases = ["@ni"];
   };
-  nixpkgs-pull-requests= {
+  nixpkgs-pull-requests = {
     name = "Nixpkgs pull requests";
     urls = [{template = "https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+{searchTerms}";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
     definedAliases = ["@nr"];
   };
 
-  nixpkgs-pull-requests-tracker= {
+  nixpkgs-pull-requests-tracker = {
     name = "Nixpkgs pull requests tracker";
     urls = [{template = "https://nixpk.gs/pr-tracker.html?pr={searchTerms}";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
     definedAliases = ["@nt"];
   };
-  nixos-wiki= {
+  nixos-wiki = {
     name = "NixOS Wiki";
     urls = [{template = "https://wiki.nixos.org/w/index.php?search={searchTerms}";}];
     icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
@@ -62,13 +62,13 @@
   };
 
   # RUST
-  rust-std= {
+  rust-std = {
     name = "Rust std";
     urls = [{template = "https://doc.rust-lang.org/std/?search={searchTerms}";}];
     icon = ./logos/rust_std.svg;
     definedAliases = ["@rs"];
   };
-  rust-tokio= {
+  rust-tokio = {
     name = "Rust tokio";
     urls = [{template = "https://docs.rs/tokio/latest/tokio/index.html?search={searchTerms}";}];
     icon = ./logos/rust_tokio.png;
@@ -76,19 +76,19 @@
   };
 
   # OTHER
-  google-scholar= {
+  google-scholar = {
     name = "Google Scholar";
     urls = [{template = "https://scholar.google.com/scholar?hl=en&q={searchTerms}";}];
     icon = ./logos/google_scholar.ico;
     definedAliases = ["@gs"];
   };
-  wikipedia= {
+  wikipedia = {
     name = "Wikipedia";
     urls = [{template = "https://en.wikipedia.org/wiki/{searchTerms}";}];
     icon = ./logos/wikipedia.svg;
     definedAliases = ["@wp"];
   };
-  arch-wiki= {
+  arch-wiki = {
     name = "Arch Wiki";
     urls = [{template = "https://wiki.archlinux.org/index.php?search={searchTerms}";}];
     icon = ./logos/arch_linux.svg;
diff --git a/modules/by-name/lf/lf/commands/default.nix b/modules/by-name/lf/lf/commands/default.nix
index 0c42607b..90b333c6 100644
--- a/modules/by-name/lf/lf/commands/default.nix
+++ b/modules/by-name/lf/lf/commands/default.nix
@@ -124,11 +124,6 @@ in {
     dependencies = [pkgs.gnused];
   };
 
-  open = async {
-    name = "open";
-    dependencies = [pkgs.handlr-regex];
-  };
-
   trash = pipe {
     name = "trash";
     dependencies = [pkgs.trash-cli];
diff --git a/modules/by-name/lf/lf/commands/scripts/open.sh b/modules/by-name/lf/lf/commands/scripts/open.sh
deleted file mode 100755
index b494074f..00000000
--- a/modules/by-name/lf/lf/commands/scripts/open.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-# shellcheck shell=sh
-
-# shellcheck disable=SC2269
-f="$f"
-# shellcheck disable=SC2269
-fx="$fx"
-# shellcheck disable=SC2269
-fs="$fs"
-# shellcheck disable=SC2269
-id="$id"
-
-# TODO: For some reason, `xdg-utils` tries to open firefox with it's default profile for
-# _everything_. Using `handlr-regex` sort-of solves this. <2025-04-04>
-handlr open "$f"
-# vim: ft=sh
diff --git a/modules/by-name/lf/lf/commands/scripts/trash_restore.sh b/modules/by-name/lf/lf/commands/scripts/trash_restore.sh
index 5a7624db..cc2d4890 100755
--- a/modules/by-name/lf/lf/commands/scripts/trash_restore.sh
+++ b/modules/by-name/lf/lf/commands/scripts/trash_restore.sh
@@ -13,6 +13,5 @@ while IFS="$(printf '\n')" read -r file; do
     set -- "$@" "$(pwd)/$file"
 done <"$(conceal list | fzf --multi --ansi | awk '{$1="";$2=""; print $0}' | sed 's/^\s*//' | tmp)"
 
-
 [ "$#" -ne 0 ] && trash restore --match=exact "$@"
 # vim: ft=sh
diff --git a/modules/by-name/lf/lf/ctpv/default.nix b/modules/by-name/lf/lf/ctpv/default.nix
index 3748eca4..98438fba 100644
--- a/modules/by-name/lf/lf/ctpv/default.nix
+++ b/modules/by-name/lf/lf/ctpv/default.nix
@@ -1,5 +1,4 @@
 {
-  sysLib,
   lib,
   config,
   pkgs,
@@ -8,15 +7,15 @@
   functionCall = {
     name,
     dependencies,
-    replacementStrings,
     scriptPath,
-    ...
+    environment,
   }:
-    sysLib.writeShellScript {
+    pkgs.writeShellApplication {
       inherit name;
-      src = scriptPath;
-      keepPath = false;
-      inherit replacementStrings dependencies;
+      text = builtins.readFile ./helpers.sh + builtins.readFile scriptPath;
+      inheritPath = false;
+      runtimeInputs = dependencies;
+      runtimeEnv = environment;
     }
     + "/bin/${name}";
 
@@ -24,8 +23,8 @@
     matches,
     priority,
     dependencies,
-    replacementStrings,
     previewer,
+    environment,
   }: let
     mkMimePath = val: let
       split = lib.strings.splitString "/" val;
@@ -49,7 +48,7 @@
       inherit
         name
         dependencies
-        replacementStrings
+        environment
         ;
       scriptPath = previewer;
     };
@@ -93,6 +92,12 @@
         };
       };
 
+      environment = lib.mkOption {
+        type = lib.types.attrsOf lib.types.str;
+        default = {};
+        description = "Environment variables to set for the script";
+      };
+
       previewer = lib.mkOption {
         type = lib.types.pathInStore;
         description = "The path to the preview script or binary";
@@ -104,13 +109,6 @@
         default = 0;
         description = "The priority to use this previewer.";
       };
-      replacementStrings = lib.mkOption {
-        type = lib.types.attrsOf (lib.types.either lib.types.str lib.types.pathInStore);
-        default = {
-          HELPERS = ./helpers.sh;
-        };
-        description = "Arbitrary strings to replace in the shell script.";
-      };
       dependencies = lib.mkOption {
         type = lib.types.listOf lib.types.package;
         default = [];
@@ -153,17 +151,6 @@ in {
 
     package = lib.mkPackageOption pkgs "ctpv-64-types" {};
 
-    # TODO: This is necessary, as the `./prev` dir is imported separately and as such
-    # cannot access the `./helpers.sh` file in it's parent directory.
-    # This separate import should ideally be removed. <2024-12-15>
-    helpers = lib.mkOption {
-      default = ./helpers.sh;
-      type = lib.types.pathInStore;
-
-      internal = true;
-      readOnly = true;
-    };
-
     previewers = lib.mkOption {
       description = ''
         The previewers to add to the config file.
diff --git a/modules/by-name/lf/lf/ctpv/helpers.sh b/modules/by-name/lf/lf/ctpv/helpers.sh
index 6dc7fee6..30e4483a 100644
--- a/modules/by-name/lf/lf/ctpv/helpers.sh
+++ b/modules/by-name/lf/lf/ctpv/helpers.sh
@@ -59,7 +59,7 @@ preview_xxd() {
     # This has been derived mathematically.
     octet_columns=$(((2 * w - 22) / 7))
 
-    if [ -n "$CTPV_LESS_PREVIEWER" ]; then
+    if [ "${CTPV_LESS_PREVIEWER:-unset}" != "-unset" ]; then
         __base_xxd_preview "$1"
     else
         __base_xxd_preview "$1" -len "$((h * octet_columns))"
diff --git a/modules/by-name/lf/lf/ctpv/prev/any.sh b/modules/by-name/lf/lf/ctpv/prev/any.sh
index 38dfd538..7ce72dcd 100644
--- a/modules/by-name/lf/lf/ctpv/prev/any.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/any.sh
@@ -1,16 +1,13 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 w="$w"
 # shellcheck disable=SC2269
-e="$e"
+e="${e:-[missing extension]}"
 # shellcheck disable=SC2269
-m="$m"
+m="${m:-[missing mime type]}"
 # shellcheck disable=SC2269
 h="$h"
 
@@ -19,8 +16,6 @@ extension="$e"
 # shellcheck disable=SC2269
 mime="$m"
 
-. %HELPERS
-
 is_not_printable() {
     grep --text --quiet '[^[:print:]]' "$1"
 }
@@ -33,8 +28,8 @@ case "$mime" in
 *)
     echo "(ctpv did not recognize this file, with extension: '$extension' and mime: '$mime')"
 
-    directory_storage="%STORAGE_DIRECTORY/$mime"
-    mkdir --parents "$(dirname "%STORAGE_DIRECTORY/$mime")"
+    directory_storage="$STORAGE_DIRECTORY/$mime"
+    mkdir --parents "$(dirname "$STORAGE_DIRECTORY/$mime")"
 
     printf "%s -- %s\n" "$f" "$extension" >>"$directory_storage"
     ;;
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/archive/atool.sh b/modules/by-name/lf/lf/ctpv/prev/application/archive/atool.sh
index 5f4baac7..3aebfbb3 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/archive/atool.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/application/archive/atool.sh
@@ -1,11 +1,6 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 
-. %HELPERS
-
 atool --list -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/dll/dll.sh b/modules/by-name/lf/lf/ctpv/prev/application/dll/dll.sh
index 678506eb..5237ecec 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/dll/dll.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/application/dll/dll.sh
@@ -1,19 +1,14 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 w="$w"
 # shellcheck disable=SC2269
-e="$e"
+e="${e:-[missing extension]}"
 # shellcheck disable=SC2269
-m="$m"
+m="${m:-[missing mime type]}"
 # shellcheck disable=SC2269
 h="$h"
 
-. %HELPERS
-
 preview_xxd "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/epub/default.nix b/modules/by-name/lf/lf/ctpv/prev/application/epub/default.nix
index 40510a78..b4df845a 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/epub/default.nix
+++ b/modules/by-name/lf/lf/ctpv/prev/application/epub/default.nix
@@ -5,11 +5,11 @@
       matches.mime = ["application/epub+zip"];
       matches.extension = ["epub"];
       priority = 1;
-      dependencies = with pkgs; [
-        bk
-        epub-thumbnailer
-        chafa
-        gnused
+      dependencies = [
+        pkgs.bk
+        pkgs.epub-thumbnailer
+        pkgs.chafa
+        pkgs.gnused
       ];
     };
   };
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/epub/epub.sh b/modules/by-name/lf/lf/ctpv/prev/application/epub/epub.sh
index 703e7dad..3bec0dd1 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/epub/epub.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/application/epub/epub.sh
@@ -1,23 +1,18 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 w="$w"
 # shellcheck disable=SC2269
-e="$e"
+e="${e:-[missing extension]}"
 # shellcheck disable=SC2269
-m="$m"
+m="${m:-[missing mime type]}"
 # shellcheck disable=SC2269
 h="$h"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 epub() {
     epub-thumbnailer "$f" "$cache_f" 20000
 }
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/pdf/default.nix b/modules/by-name/lf/lf/ctpv/prev/application/pdf/default.nix
index d3061ea8..24112737 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/pdf/default.nix
+++ b/modules/by-name/lf/lf/ctpv/prev/application/pdf/default.nix
@@ -8,6 +8,7 @@
         pkgs.poppler_utils # for `pdftoppm`
         pkgs.chafa
         pkgs.gnused
+        pkgs.coreutils
       ];
     };
   };
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/pdf/pdf.sh b/modules/by-name/lf/lf/ctpv/prev/application/pdf/pdf.sh
index 2f807b1a..4d99f4b0 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/pdf/pdf.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/application/pdf/pdf.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 pdf() {
     pdftoppm -f 1 -l 1 \
         -scale-to-x 1920 \
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/pgp/pgp.sh b/modules/by-name/lf/lf/ctpv/prev/application/pgp/pgp.sh
index a4eefd96..4747a8c4 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/pgp/pgp.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/application/pgp/pgp.sh
@@ -1,13 +1,8 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 w="$w"
 
-. %HELPERS
-
 hide_script_env sq inspect --certifications -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/sqlite/sqlite.sh b/modules/by-name/lf/lf/ctpv/prev/application/sqlite/sqlite.sh
index 07e77a93..62c1abec 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/sqlite/sqlite.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/application/sqlite/sqlite.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 w="$w"
 
-. %HELPERS
-
 echo "SQLite database. Schema:"
 echo
 
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/x-bittorrent/torrent.sh b/modules/by-name/lf/lf/ctpv/prev/application/x-bittorrent/torrent.sh
index 16cfcbcd..f1da355a 100644
--- a/modules/by-name/lf/lf/ctpv/prev/application/x-bittorrent/torrent.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/application/x-bittorrent/torrent.sh
@@ -1,13 +1,8 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 transmission-show -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/default.nix b/modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/default.nix
new file mode 100644
index 00000000..a6a32808
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/default.nix
@@ -0,0 +1,11 @@
+{pkgs, ...}: {
+  soispha.programs.lf.ctpv.previewers = {
+    pem = {
+      previewer = ./pem.sh;
+      matches.mime = ["application/x-pem-file"];
+      dependencies = [
+        pkgs.openssl
+      ];
+    };
+  };
+}
diff --git a/modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/pem.sh b/modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/pem.sh
new file mode 100644
index 00000000..76ee3002
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/application/x-pem-file/pem.sh
@@ -0,0 +1,8 @@
+#! /usr/bin/env dash
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+openssl x509 -in "$f" -text -noout
diff --git a/modules/by-name/lf/lf/ctpv/prev/audio/audio.sh b/modules/by-name/lf/lf/ctpv/prev/audio/audio.sh
index c5abc646..2e9e147c 100644
--- a/modules/by-name/lf/lf/ctpv/prev/audio/audio.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/audio/audio.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 audio() {
     ffmpegthumbnailer -i "$f" -s 0 -q 5 -t 10 -o "$cache_f" 2>/dev/null
 }
diff --git a/modules/by-name/lf/lf/ctpv/prev/audio/default.nix b/modules/by-name/lf/lf/ctpv/prev/audio/default.nix
index 0c60e9d5..20df04b3 100644
--- a/modules/by-name/lf/lf/ctpv/prev/audio/default.nix
+++ b/modules/by-name/lf/lf/ctpv/prev/audio/default.nix
@@ -9,6 +9,7 @@
 
         pkgs.chafa
         pkgs.gnused
+        pkgs.coreutils
       ];
     };
   };
diff --git a/modules/by-name/lf/lf/ctpv/prev/default.nix b/modules/by-name/lf/lf/ctpv/prev/default.nix
index b59430f8..3e54e88a 100644
--- a/modules/by-name/lf/lf/ctpv/prev/default.nix
+++ b/modules/by-name/lf/lf/ctpv/prev/default.nix
@@ -10,18 +10,15 @@ in {
       previewer = ./any.sh;
       priority = -1;
       matches.mime = ["*/*"];
-      replacementStrings = {
-        # FIXME: This declaration replaces the default (although it should be merged with
-        # the default value.) There must be a way, so that repeating the default values is
-        # not needed. <2024-12-15>
-        HELPERS = cfg.ctpv.helpers;
-
+      environment = {
         STORAGE_DIRECTORY = "${cfg.ctpv.xdgDataHome}/ctpv/missing_previews";
       };
 
       dependencies = [
         pkgs.tinyxxd # For xxd
         pkgs.bat
+        pkgs.gnugrep
+        pkgs.coreutils
       ];
     };
   };
diff --git a/modules/by-name/lf/lf/ctpv/prev/font/default.nix b/modules/by-name/lf/lf/ctpv/prev/font/default.nix
index 306e7892..48bcb7ad 100644
--- a/modules/by-name/lf/lf/ctpv/prev/font/default.nix
+++ b/modules/by-name/lf/lf/ctpv/prev/font/default.nix
@@ -13,6 +13,7 @@
         pkgs.fontforge # for `fontimage`
         pkgs.chafa
         pkgs.gnused
+        pkgs.coreutils
       ];
     };
   };
diff --git a/modules/by-name/lf/lf/ctpv/prev/font/font.sh b/modules/by-name/lf/lf/ctpv/prev/font/font.sh
index 4065557e..9e5ef3c1 100644
--- a/modules/by-name/lf/lf/ctpv/prev/font/font.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/font/font.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 font() {
     fontimage -o "$cache_f.png" "$f" 2>/dev/null &&
         mv -- "$cache_f.png" "$cache_f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/image/image.sh b/modules/by-name/lf/lf/ctpv/prev/image/image.sh
index b5b97668..42c99c23 100644
--- a/modules/by-name/lf/lf/ctpv/prev/image/image.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/image/image.sh
@@ -1,11 +1,6 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 
-. %HELPERS
-
 send_image "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/image/svg+xml/svg.sh b/modules/by-name/lf/lf/ctpv/prev/image/svg+xml/svg.sh
index 04a06f56..ce588ada 100644
--- a/modules/by-name/lf/lf/ctpv/prev/image/svg+xml/svg.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/image/svg+xml/svg.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 svg() {
     magick "$f" "jpg:$cache_f"
 }
diff --git a/modules/by-name/lf/lf/ctpv/prev/image/x-xcf/xcf.sh b/modules/by-name/lf/lf/ctpv/prev/image/x-xcf/xcf.sh
index 1603e337..abb83a89 100644
--- a/modules/by-name/lf/lf/ctpv/prev/image/x-xcf/xcf.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/image/x-xcf/xcf.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 xcf() {
     # TODO: Add this (currently it fails, as gimp lacks the `python-fu` evaluator) <2024-11-25>
     true
diff --git a/modules/by-name/lf/lf/ctpv/prev/inode/ls.sh b/modules/by-name/lf/lf/ctpv/prev/inode/ls.sh
index f73bd1c2..f5b95d13 100644
--- a/modules/by-name/lf/lf/ctpv/prev/inode/ls.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/inode/ls.sh
@@ -1,8 +1,5 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
@@ -10,6 +7,4 @@ cache_d="$cache_d"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 ls --color --group-directories-first -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/inode/symlink.sh b/modules/by-name/lf/lf/ctpv/prev/inode/symlink.sh
index b30957d0..fb0dea8f 100644
--- a/modules/by-name/lf/lf/ctpv/prev/inode/symlink.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/inode/symlink.sh
@@ -1,13 +1,8 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 
-. %HELPERS
-
 #
 # do nothing because in src/ctpv.c some kind of a "preview"
 # is already printed
diff --git a/modules/by-name/lf/lf/ctpv/prev/libreoffice.sh b/modules/by-name/lf/lf/ctpv/prev/libreoffice.sh
index ec57da0b..9407aade 100644
--- a/modules/by-name/lf/lf/ctpv/prev/libreoffice.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/libreoffice.sh
@@ -1,8 +1,5 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
@@ -10,8 +7,6 @@ cache_d="$cache_d"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 doc() {
     # File produced by libreoffice
     jpg="$(printf '%s\n' "$f" | sed 's|^.*/||; s|\..*$||')"
diff --git a/modules/by-name/lf/lf/ctpv/prev/text/bat.sh b/modules/by-name/lf/lf/ctpv/prev/text/bat.sh
index be952aea..a466c9c7 100644
--- a/modules/by-name/lf/lf/ctpv/prev/text/bat.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/text/bat.sh
@@ -1,13 +1,8 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 w="$w"
 
-. %HELPERS
-
 preview_bat "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/text/diff/delta.sh b/modules/by-name/lf/lf/ctpv/prev/text/diff/delta.sh
index 6a4e9a4e..3f8b5631 100644
--- a/modules/by-name/lf/lf/ctpv/prev/text/diff/delta.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/text/diff/delta.sh
@@ -1,11 +1,6 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 
-. %HELPERS
-
 delta <"$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/text/glow.sh b/modules/by-name/lf/lf/ctpv/prev/text/glow.sh
index 301fe675..30f2af78 100644
--- a/modules/by-name/lf/lf/ctpv/prev/text/glow.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/text/glow.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 w="$w"
 
-. %HELPERS
-
 # Specify the style, to force `glow` to output colors.
 # tracking issue: https://github.com/charmbracelet/glow/issues/654
 # We can't use `hide_script_env` because of some bespoke reason. (It just forces glow to
diff --git a/modules/by-name/lf/lf/ctpv/prev/text/html/default.nix b/modules/by-name/lf/lf/ctpv/prev/text/html/default.nix
deleted file mode 100644
index 2a7a9a9f..00000000
--- a/modules/by-name/lf/lf/ctpv/prev/text/html/default.nix
+++ /dev/null
@@ -1,13 +0,0 @@
-{pkgs, ...}: {
-  # TODO: I might want to use lynx/w3m instead <2024-11-24>
-  soispha.programs.lf.ctpv.previewers = {
-    elinks = {
-      previewer = ./elinks.sh;
-      priority = 1;
-      matches.mime = ["text/html"];
-      dependencies = [
-        pkgs.elinks
-      ];
-    };
-  };
-}
diff --git a/modules/by-name/lf/lf/ctpv/prev/text/html/elinks.sh b/modules/by-name/lf/lf/ctpv/prev/text/html/elinks.sh
deleted file mode 100644
index ca0de22e..00000000
--- a/modules/by-name/lf/lf/ctpv/prev/text/html/elinks.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#! /usr/bin/env dash
-
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
-# shellcheck disable=SC2269
-f="$f"
-# shellcheck disable=SC2269
-w="$w"
-
-. %HELPERS
-
-elinks \
-    -dump 1 -dump-width "$w" \
-    -no-references -no-numbering <"$f"
-
-# lynx -dump -nonumbers -nolist -width="$w" -- "$f"
-# w3m -dump "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/text/json/jq.sh b/modules/by-name/lf/lf/ctpv/prev/text/json/jq.sh
index bf807d1d..c7090ccb 100644
--- a/modules/by-name/lf/lf/ctpv/prev/text/json/jq.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/text/json/jq.sh
@@ -1,11 +1,6 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 
-. %HELPERS
-
 jq --color-output . <"$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/video/video.sh b/modules/by-name/lf/lf/ctpv/prev/video/video.sh
index e42e3612..d1972187 100644
--- a/modules/by-name/lf/lf/ctpv/prev/video/video.sh
+++ b/modules/by-name/lf/lf/ctpv/prev/video/video.sh
@@ -1,15 +1,10 @@
 #! /usr/bin/env dash
 
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
 # shellcheck disable=SC2269
 f="$f"
 # shellcheck disable=SC2269
 cache_f="$cache_f"
 
-. %HELPERS
-
 video() {
     ffmpegthumbnailer -i "$f" -o "$cache_f" -s 0 -t 50% 2>/dev/null
 }
diff --git a/modules/by-name/lf/lf/module.nix b/modules/by-name/lf/lf/module.nix
index 6dc8e919..ae1534d0 100644
--- a/modules/by-name/lf/lf/module.nix
+++ b/modules/by-name/lf/lf/module.nix
@@ -75,7 +75,7 @@ in {
           icons = true;
           ifs = "\\n"; # internal field separator for shell commands
           #info = "size"; # show the size of a directory
-          shell = "sh";
+          shell = "${lib.getExe pkgs.dash}";
           shellopts = "-eu"; # e: exit on error; u: error for unset variables
         };
         extraConfig = ''
diff --git a/modules/by-name/mp/mpd/mpc.nix b/modules/by-name/mp/mpd/mpc.nix
index 031465fe..b1398b77 100644
--- a/modules/by-name/mp/mpd/mpc.nix
+++ b/modules/by-name/mp/mpd/mpc.nix
@@ -5,7 +5,6 @@
   ...
 }: let
   cfg = config.soispha.services.mpd.mpc;
-  parentCfg = config.soispha.services.mpd;
 in {
   options.soispha.services.mpd.mpc = {
     enable = lib.mkEnableOption "mpc with extensions";
@@ -29,9 +28,7 @@ in {
         beets = cfg.beetsPkg;
       })
       # Displays the lyrics of the currently playing song
-      (pkgs.mpp-lyrics.override {
-        mpd_music_dir = parentCfg.directories.music;
-      })
+      pkgs.mpp-lyrics
     ];
   };
 }
diff --git a/modules/by-name/nv/nvim/plgs/harpoon/default.nix b/modules/by-name/nv/nvim/plgs/harpoon/default.nix
index 05a40d9f..3760ce15 100644
--- a/modules/by-name/nv/nvim/plgs/harpoon/default.nix
+++ b/modules/by-name/nv/nvim/plgs/harpoon/default.nix
@@ -1,100 +1,44 @@
 {
-  pkgs,
-  config,
   lib,
+  config,
   ...
 }: let
-  numbers = ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"];
-  mkNumberedCommand = {
-    command_template,
-    prefix,
-    number,
-    desc_template,
-  }: {
-    key = "${prefix}${number}";
-    action.__raw = ''
-      function()
-        ${command_template number}
-      end
-    '';
-    options.desc = "${desc_template number}";
-  };
-  mkGotoTerminalCommand = number: let
-    desc_template = number: "Goto terminal number ${number}";
-    command_template = number: ''require("harpoon.term").gotoTerminal(${number})'';
-    prefix = "gt";
-  in
-    mkNumberedCommand {inherit desc_template command_template prefix number;};
-  mkGotoFileCommand = number: let
-    desc_template = number: "Goto Buffer number ${number}";
-    command_template = number: ''require("harpoon.ui").nav_file(${number})'';
-    prefix = "gf";
-  in
-    mkNumberedCommand {inherit desc_template command_template prefix number;};
-
-  gotoTerminalMappings = builtins.map mkGotoTerminalCommand numbers;
-  gotoFileMappings = builtins.map mkGotoFileCommand numbers;
   cfg = config.soispha.programs.nvim;
 in {
   home-manager.users.soispha.programs.nixvim = lib.mkIf cfg.enable {
-    plugins.harpoon = {
-      enable = true;
-      package = pkgs.vimPlugins.harpoon;
-      enableTelescope = true;
-      # menu.width = "vim.api.nvim_win_get_width(0) - 4"; # TODO: integrate that
-      keymaps = {
-        tmuxGotoTerminal = null; # TODO:
-      };
-    };
+    plugins.harpoon.enable = true;
+
     keymaps =
-      [
-        {
-          key = "-";
-          action.__raw = ''
+      lib.mapAttrsToList
+      (key: action: {
+        mode = "n";
+        inherit key;
+        action.__raw = builtins.elemAt action 0;
+        options.silent = true;
+        options.desc = builtins.elemAt action 1;
+      })
+      {
+        # add current file
+        "<leader><leader>" = [
+          # lua
+          ''
             function()
-              require("harpoon.ui").nav_next()
-             end
-          '';
-          options.desc = "go to the next marked file";
-        }
-        {
-          key = "_";
-          action.__raw = ''
-            function()
-              require("harpoon.ui").nav_prev()
-             end
-          '';
-          options.desc = "go to the previous marked file";
-        }
-        {
-          key = "<leader><leader>";
-          action.__raw = ''
-            function()
-              require("harpoon.mark").add_file()
-            end
-          '';
-          options.desc = "add a mark to the open file in harpoon.";
-        }
-        {
-          key = "gqc";
-          action.__raw = ''
-            function()
-              require("harpoon.cmd-ui").toggle_quick_menu()
+              require("harpoon"):list():add()
             end
-          '';
-          options.desc = "toggle the harpoon command quick menu to see all commands.";
-        }
-        {
-          key = "<leader>q";
-          action.__raw = ''
+          ''
+          "Add a mark to the open file in harpoon."
+        ];
+
+        # open menu
+        "<leader>q" = [
+          # lua
+          ''
             function()
-              require("harpoon.ui").toggle_quick_menu()
+                require("harpoon").ui:toggle_quick_menu(require("harpoon"):list())
             end
-          '';
-          options.desc = "toggle the harpoon normal quick menu to see all marks.";
-        }
-      ]
-      ++ gotoFileMappings
-      ++ gotoTerminalMappings;
+          ''
+          "Toggle the harpoon normal quick menu to see all marks."
+        ];
+      };
   };
 }
diff --git a/modules/by-name/nv/nvim/plgs/lf-nvim/default.nix b/modules/by-name/nv/nvim/plgs/lf-nvim/default.nix
index 1e7c91e3..6c363ee1 100644
--- a/modules/by-name/nv/nvim/plgs/lf-nvim/default.nix
+++ b/modules/by-name/nv/nvim/plgs/lf-nvim/default.nix
@@ -2,22 +2,18 @@
   pkgs,
   lib,
   config,
-  nixpkgs_open_prs,
-  system,
   ...
 }: let
   cfg = config.soispha.programs.nvim;
 in {
+  # TODO: package lf-nvim though a module
+  # TODO: change the nvim path, when I change the path with lf
   home-manager.users.soispha.programs.nixvim = lib.mkIf cfg.enable {
-    # TODO: package lf-nvim though a module
-    # FIXME: change the nvim path, when I change the path with lf
     extraConfigLuaPost = ''
       ${lib.strings.fileContents ./lua/lf-nvim.lua}
     '';
     extraPlugins = [
-      nixpkgs_open_prs.nixpkgs-lf.legacyPackages."${system}".vimPlugins.lf-nvim
-
-      pkgs.vimPlugins.toggleterm-nvim # required by lf-nvim
+      pkgs.vimPlugins.lf-nvim
     ];
   };
 }
diff --git a/modules/by-name/nv/nvim/plgs/telescope/extensions/bibtex/default.nix b/modules/by-name/nv/nvim/plgs/telescope/extensions/bibtex/default.nix
index 4cab0258..8eee9a27 100644
--- a/modules/by-name/nv/nvim/plgs/telescope/extensions/bibtex/default.nix
+++ b/modules/by-name/nv/nvim/plgs/telescope/extensions/bibtex/default.nix
@@ -1,7 +1,4 @@
-{
-  config,
-  ...
-}: let
+{config, ...}: let
   cfg = config.soispha.programs.nvim;
 in {
   # TODO: Re-enable this, once the plugin is merged into nixpkgs <2025-03-29>
diff --git a/modules/by-name/ta/taskwarrior/module.nix b/modules/by-name/ta/taskwarrior/module.nix
index 3d53706c..2c1f91c2 100644
--- a/modules/by-name/ta/taskwarrior/module.nix
+++ b/modules/by-name/ta/taskwarrior/module.nix
@@ -23,19 +23,24 @@
 
     executable = pkgs.writeShellApplication {
       name = "add-hook-${builtins.baseNameOf path}";
-      runtimeInputs = [pkgs.taskwarrior pkgs.coreutils] ++ deps;
+      runtimeInputs = [pkgs.taskwarrior3 pkgs.coreutils pkgs.gnugrep] ++ deps;
       inheritPath = false;
       text =
         # bash
         ''
           die() {
-            echo "$@"
+            echo "$@">&2
             exit 1
           }
 
           enable_hook_dbg() {
-              debug_hooks="$(task _get rc.debug.hooks)"
-              [ "$debug_hooks" ] && [ "$debug_hooks" -ge 1 ] && set -x
+              # TODO: We should probably be smarter with the debug detection <2025-04-04>
+              if echo "$2" | grep --quiet 'rc.debug.hooks='; then
+                set -x
+                mkdir --parents "$HOME/.cache/task"
+                exec >>"$HOME/.cache/task/hook.log.$1"
+                exec 2>>"$HOME/.cache/task/hook.log.$1"
+              fi
           }
 
           addedCall() {
@@ -51,7 +56,7 @@
           # We don't change the task, thus immediately return the JSON
           echo "$new_task"
 
-          enable_hook_dbg
+          enable_hook_dbg "$@"
           addedCall "$new_task" "$old_task"
 
           exit 0
@@ -91,17 +96,19 @@ in {
 
   config = {
     lib.taskwarrior = {
-      mkHook = mkHook;
+      inherit mkHook;
     };
 
     home-manager.users.soispha = lib.mkIf cfg.enable {
       services.taskwarrior-sync = {
         enable = true;
+        package = pkgs.taskwarrior3;
       };
 
       programs.taskwarrior = {
         enable = true;
         colorTheme = ./nord.theme;
+        package = pkgs.taskwarrior3;
         extraConfig = cfg.includeFiles;
 
         config = {
@@ -111,6 +118,8 @@ in {
             tags = true;
           };
 
+          news.version = "3.4.1";
+
           regex = true;
           weekstart = "Monday";
 
diff --git a/modules/by-name/ti/timewarrior/module.nix b/modules/by-name/ti/timewarrior/module.nix
index d6b4dc32..f33d02be 100644
--- a/modules/by-name/ti/timewarrior/module.nix
+++ b/modules/by-name/ti/timewarrior/module.nix
@@ -7,49 +7,41 @@
   cfg = config.soispha.programs.timewarrior;
 
   track_timewarrior = pkgs.stdenv.mkDerivation {
-    name = "track_timewarrior.taskwarrior-hook";
+    name = "track-timewarrior";
     nativeBuildInputs = [
       pkgs.makeWrapper
     ];
     buildInputs = [
       pkgs.timewarrior
-      pkgs.taskwarrior
-      # TODO: Use a `taskw` package, that actually supports newer python variants <2024-07-13>
-      (pkgs.python311.withPackages (pythonPackages:
-        with pythonPackages; [
-          taskw
-        ]))
+      pkgs.taskwarrior3
+      pkgs.python3
     ];
     dontUnpack = true;
     installPhase = ''
-      install -Dm755 ${./taskwarirror_hooks/on-modify_track-timewarrior.py} $out/bin/bin
-      wrapProgram $out/bin/bin \
-      --prefix PATH : ${lib.makeBinPath [pkgs.taskwarrior pkgs.timewarrior]}
+      install -Dm755 ${./taskwarrior_hooks/on-modify.track-timewarrior.py} $out/bin/track-timewarrior
+      wrapProgram $out/bin/track-timewarrior \
+      --set PATH ${lib.makeBinPath [pkgs.taskwarrior3 pkgs.timewarrior]}
     '';
 
-    meta.mainProgram = "bin";
+    meta.mainProgram = "track-timewarrior";
   };
   track_total_active_time = pkgs.stdenv.mkDerivation {
-    name = "track_total_active_time.taskwarrior-hook";
+    name = "track-total-active-time";
     nativeBuildInputs = [
       pkgs.makeWrapper
     ];
     buildInputs = [
-      pkgs.taskwarrior
-      # TODO: Use a `taskw` package, that actually supports newer python variants <2024-07-13>
-      (pkgs.python311.withPackages (pythonPackages:
-        with pythonPackages; [
-          taskw
-        ]))
+      pkgs.taskwarrior3
+      pkgs.python3
     ];
     dontUnpack = true;
     installPhase = ''
-      install -Dm755 ${./taskwarirror_hooks/on-modify_track-total-active-time.py} $out/bin/bin
-      wrapProgram $out/bin/bin \
-      --prefix PATH : ${lib.makeBinPath [pkgs.taskwarrior]}
+      install -Dm755 ${./taskwarrior_hooks/on-modify.track-total-active-time.py} $out/bin/track-total-active-time
+      wrapProgram $out/bin/track-total-active-time \
+      --set PATH ${lib.makeBinPath [pkgs.taskwarrior3]}
     '';
 
-    meta.mainProgram = "bin";
+    meta.mainProgram = "track-total-active-time";
   };
 in {
   options.soispha.programs.timewarrior = {
diff --git a/modules/by-name/ti/timewarrior/taskwarirror_hooks/on-modify_track-timewarrior.py b/modules/by-name/ti/timewarrior/taskwarirror_hooks/on-modify_track-timewarrior.py
deleted file mode 100755
index b482af6a..00000000
--- a/modules/by-name/ti/timewarrior/taskwarirror_hooks/on-modify_track-timewarrior.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright (C) 2016-present Arctic Ice Studio <development@arcticicestudio.com>
-# Copyright (C) 2016-present Sven Greb <development@svengreb.de>
-
-# Project:    igloo
-# Repository: https://github.com/arcticicestudio/igloo
-# License:    MIT
-# References:
-#   https://taskwarrior.org/docs
-#   https://taskwarrior.org/docs/timewarrior
-#   timew(1)
-#   task(1)
-
-"""A Taskwarrior hook to track the time of a active task with Taskwarrior.
-
-This hook will extract all of the following for use as Timewarrior tags:
-
-* UUID
-* Project
-* Tags
-* Description
-* UDAs
-
-Note:
-    This hook requires Python 3 and is only compatible with Taskwarrior version greater or equal to 2.4!
-
-This hook is a fork from the `official on-modify.timewarrior hook`_.
-
-.. _`official on-modify.timewarrior hook`:
-   https://github.com/GothenburgBitFactory/timewarrior/blob/dev/ext/on-modify.timewarrior
-"""
-
-import subprocess
-import sys
-from json import loads, dumps
-from os import system
-from sys import stdin
-from taskw import TaskWarrior
-
-# Make no changes to the task, simply observe.
-old = loads(stdin.readline())
-new = loads(stdin.readline())
-print(dumps(new))
-
-
-w = TaskWarrior(config_filename=sys.argv[4].replace("rc:", ""))
-config = w.load_config(config_filename=sys.argv[4].replace("rc:", ""))
-if "max_active_tasks" in config:
-    MAX_ACTIVE = int(config["max_active_tasks"])
-else:
-    MAX_ACTIVE = 1
-
-
-# Extract attributes for use as tags.
-tags = [new["description"]]
-
-if "project" in new:
-    project = new["project"]
-    tags.append(project)
-    if "." in project:
-        tags.extend([tag for tag in project.split(".")])
-
-if "tags" in new:
-    tags.extend(new["tags"])
-
-combined = " ".join(["'%s'" % tag for tag in tags]).encode("utf-8").strip()
-
-# Task has been started.
-if "start" in new and "start" not in old:
-    # Prevent this task from starting if "task +ACTIVE count" is greater than "MAX_ACTIVE".
-    p = subprocess.Popen(
-        ["task", "+ACTIVE", "status:pending", "count", "rc.verbose:off"],
-        stdout=subprocess.PIPE,
-    )
-    out, err = p.communicate()
-    count = int(out.rstrip())
-    if count >= MAX_ACTIVE:
-        print(
-            "Only %d task(s) can be active at a time. "
-            "See 'max_active_tasks' in .taskrc." % MAX_ACTIVE
-        )
-        sys.exit(1)
-
-    system("timew start " + combined.decode() + " :yes")
-
-# Task has been stopped.
-elif "start" not in new and "start" in old:
-    system("timew stop " + combined.decode() + " :yes")
-
-# Any task that is active, with a non-pending status should not be tracked.
-elif "start" in new and new["status"] != "pending":
-    system("timew stop " + combined.decode() + " :yes")
diff --git a/modules/by-name/ti/timewarrior/taskwarrior_hooks/on-modify.track-timewarrior.py b/modules/by-name/ti/timewarrior/taskwarrior_hooks/on-modify.track-timewarrior.py
new file mode 100755
index 00000000..0bef8bc2
--- /dev/null
+++ b/modules/by-name/ti/timewarrior/taskwarrior_hooks/on-modify.track-timewarrior.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python3
+
+###############################################################################
+#
+# Copyright 2016 - 2021, 2023, Gothenburg Bit Factory
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# https://www.opensource.org/licenses/mit-license.php
+#
+###############################################################################
+
+import json
+import subprocess
+import sys
+
+# Hook should extract all the following for use as Timewarrior tags:
+#   UUID
+#   Project
+#   Tags
+#   Description
+#   UDAs
+
+try:
+    input_stream = sys.stdin.buffer
+except AttributeError:
+    input_stream = sys.stdin
+
+
+MAX_ACTIVE = 1
+
+
+def extract_tags_from(json_obj) -> [str]:
+    # Extract attributes for use as tags.
+    tags = [json_obj["description"]]
+
+    if "project" in json_obj:
+        tags.append(json_obj["project"])
+
+    if "tags" in json_obj:
+        if type(json_obj["tags"]) is str:
+            # Usage of tasklib (e.g. in taskpirate) converts the tag list into a string
+            # If this is the case, convert it back into a list first
+            # See https://github.com/tbabej/taskpirate/issues/11
+            tags.extend(json_obj["tags"].split(","))
+        else:
+            tags.extend(json_obj["tags"])
+
+    return tags
+
+
+def extract_annotation_from(json_obj):
+    if "annotations" not in json_obj:
+        return "''"
+
+    return json_obj["annotations"][0]["description"]
+
+
+def main(old, new):
+    start_or_stop = ""
+
+    # Started task.
+    if "start" in new and "start" not in old:
+        # Prevent this task from starting if "task +ACTIVE count" is greater than "MAX_ACTIVE".
+        p = subprocess.Popen(
+            ["task", "+ACTIVE", "status:pending", "count", "rc.verbose:off"],
+            stdout=subprocess.PIPE,
+        )
+        out, err = p.communicate()
+        count = int(out.rstrip())
+        if count >= MAX_ACTIVE:
+            print(
+                f"Only {MAX_ACTIVE} task(s) can be active at a time.",
+            )
+            sys.exit(1)
+        else:
+            start_or_stop = "start"
+
+    # Stopped task.
+    elif ("start" not in new or "end" in new) and "start" in old:
+        start_or_stop = "stop"
+
+    if start_or_stop:
+        tags = extract_tags_from(new)
+
+        subprocess.call(["timew", start_or_stop] + tags + [":yes"])
+
+    # Modifications to task other than start/stop
+    elif "start" in new and "start" in old:
+        old_tags = extract_tags_from(old)
+        new_tags = extract_tags_from(new)
+
+        if old_tags != new_tags:
+            subprocess.call(["timew", "untag", "@1"] + old_tags + [":yes"])
+            subprocess.call(["timew", "tag", "@1"] + new_tags + [":yes"])
+
+        old_annotation = extract_annotation_from(old)
+        new_annotation = extract_annotation_from(new)
+
+        if old_annotation != new_annotation:
+            subprocess.call(["timew", "annotate", "@1", new_annotation])
+
+
+if __name__ == "__main__":
+    old = json.loads(input_stream.readline().decode("utf-8", errors="replace"))
+    new = json.loads(input_stream.readline().decode("utf-8", errors="replace"))
+    print(json.dumps(new))
+    main(old, new)
diff --git a/modules/by-name/ti/timewarrior/taskwarirror_hooks/on-modify_track-total-active-time.py b/modules/by-name/ti/timewarrior/taskwarrior_hooks/on-modify.track-total-active-time.py
index d5b380d0..0b6be082 100755
--- a/modules/by-name/ti/timewarrior/taskwarirror_hooks/on-modify_track-total-active-time.py
+++ b/modules/by-name/ti/timewarrior/taskwarrior_hooks/on-modify.track-total-active-time.py
@@ -20,37 +20,24 @@ By default, this plugin allows to have one task active at a time. This can be ch
 ``1``.
 
 Note:
-    This hook requires Python 3 and the `taskw`_ package to be installed which provides the python bindings for Taskwarrior!
-    Also note that this hook is only compatible with Taskwarrior version greater or equal to 2.4!
+    Note that this hook is only compatible with Taskwarrior version greater or equal to 2.4!
 
 This hook is a fork from `kostajh/taskwarrior-time-tracking-hook`_
 
-.. _taskw:
-   https://pypi.python.org/pypi/taskw
 .. _kostajh/taskwarrior-time-tracking-hook:
    https://github.com/kostajh/taskwarrior-time-tracking-hook
 """
 
 import datetime
 import json
-import re
 import sys
 import subprocess
-from taskw import TaskWarrior
 from typing import TypeVar
 
 TIME_FORMAT = "%Y%m%dT%H%M%SZ"
 UDA_KEY = "total_active_time"
 
-w = TaskWarrior(config_filename=sys.argv[4].replace("rc:", ""))
-config = w.load_config(config_filename=sys.argv[4].replace("rc:", ""))
-if "max_active_tasks" in config:
-    MAX_ACTIVE = int(config["max_active_tasks"])
-else:
-    MAX_ACTIVE = 1
-
-"""Compiled regular expression for the duration as ISO-8601 formatted string."""
-ISO8601DURATION = re.compile("P((\d*)Y)?((\d*)M)?((\d*)D)?T((\d*)H)?((\d*)M)?((\d*)S)?")
+MAX_ACTIVE = 1
 
 """The duration type either as integer (in seconds), as ISO-8601 formatted string ("PT1H10M31S") or the seconds suffixed with "seconds"."""
 DurationType = TypeVar("DurationType", str, int)
@@ -63,31 +50,7 @@ def duration_str_to_time_delta(duration_str: DurationType) -> datetime.timedelta
     :return: The duration as timedelta object
     """
     if duration_str.startswith("P"):
-        match = ISO8601DURATION.match(duration_str)
-        if match:
-            year = match.group(2)
-            month = match.group(4)
-            day = match.group(6)
-            hour = match.group(8)
-            minute = match.group(10)
-            second = match.group(12)
-            value = 0
-            if second:
-                value += int(second)
-            if minute:
-                value += int(minute) * 60
-            if hour:
-                value += int(hour) * 3600
-            if day:
-                value += int(day) * 3600 * 24
-            if month:
-                # Assume a month is 30 days for now.
-                value += int(month) * 3600 * 24 * 30
-            if year:
-                # Assume a year is 365 days for now.
-                value += int(year) * 3600 * 24 * 365
-        else:
-            value = int(duration_str)
+        value = datetime.fromisoformat(duration_str)
     elif duration_str.endswith("seconds"):
         value = int(duration_str.rstrip("seconds"))
     else:
diff --git a/modules/by-name/ts/tskm/module.nix b/modules/by-name/ts/tskm/module.nix
index 75af4509..51be48fe 100644
--- a/modules/by-name/ts/tskm/module.nix
+++ b/modules/by-name/ts/tskm/module.nix
@@ -2,7 +2,6 @@
   lib,
   config,
   pkgs,
-  baseLib,
   ...
 }: let
   cfg = config.soispha.programs.tskm;
@@ -15,13 +14,11 @@
   in
     [name] ++ subprojects;
 
-  firefoxProfiles = builtins.listToAttrs (builtins.map (name:
+  firefoxProfiles = builtins.listToAttrs (lib.imap0 (index: name:
     lib.attrsets.nameValuePair name {
       inherit name;
-      # We use the hash-based function here, so that we can avoid an id change if a new
-      # profile is added (i.e., simply using it index.)
-      # TODO: However, I do not know what this id is for and if it would be bad if it changed? <2025-04-02>
-      id = baseLib.idFromString name;
+      # Add one here, so that we can have the default profile at id 0.
+      id = index + 1;
     })
   allProjectNames);
 
diff --git a/modules/by-name/wa/water-reminder/module.nix b/modules/by-name/wa/water-reminder/module.nix
new file mode 100644
index 00000000..39e63771
--- /dev/null
+++ b/modules/by-name/wa/water-reminder/module.nix
@@ -0,0 +1,57 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}: let
+  cfg = config.soispha.services.water-reminder;
+in {
+  options.soispha.services.water-reminder = {
+    enable = lib.mkEnableOption "periodic reminder for water intake";
+
+    frequency = lib.mkOption {
+      type = lib.types.str;
+      default = "*-*-* *:00/30:00"; # Every 30 minutes
+      description = ''
+        How often to remind. This value is passed to the systemd
+        timer configuration as the `OnCalendar` option. See
+        {manpage}`systemd.time(7)` for more information about the format.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    home-manager.users.soispha = {
+      systemd.user.services.water-reminder = {
+        Unit = {Description = "Water reminder";};
+        Service = {
+          CPUSchedulingPolicy = "idle";
+          IOSchedulingClass = "idle";
+          ExecStart = lib.getExe (
+            pkgs.writeShellApplication {
+              name = "water-reminder";
+
+              inheritPath = false;
+              runtimeInputs = [pkgs.libnotify];
+
+              text =
+                # bash
+                ''
+                  notify-send 'Seek fluid intake' 'Water intake required' --wait --expire-time=0 --urgency=critical
+                '';
+            }
+          );
+        };
+      };
+
+      systemd.user.timers.water-reminder = {
+        Unit = {Description = "periodic reminder for water intake";};
+        Timer = {
+          Unit = "water-reminder.service";
+          OnCalendar = cfg.frequency;
+        };
+        Install = {WantedBy = ["timers.target"];};
+      };
+    };
+  };
+}
diff --git a/modules/by-name/xd/xdg/module.nix b/modules/by-name/xd/xdg/module.nix
index 1202cd96..a7c77cd7 100644
--- a/modules/by-name/xd/xdg/module.nix
+++ b/modules/by-name/xd/xdg/module.nix
@@ -1,60 +1,119 @@
 {
   pkgs,
   lib,
+  config,
   ...
 }: let
-  cmd = pkgs.writeShellApplication {
-    name = "lf_wrapper";
+  lf-wrapper = pkgs.writeShellApplication {
+    name = "lf-wrapper";
 
     runtimeInputs = [pkgs.lf pkgs.alacritty];
     inheritPath = true;
 
-    text = builtins.readFile ./lf-wrapper.sh;
+    text = builtins.readFile ./scripts/lf-wrapper.sh;
+  };
+
+  url-handler = pkgs.writeShellApplication {
+    name = "url-handler";
+
+    runtimeInputs = [pkgs.rofi pkgs.libnotify pkgs.zathura pkgs.tskm];
+    inheritPath = false;
+
+    text = builtins.readFile ./scripts/url-handler.sh;
   };
 
   tfcConfigFile = (pkgs.formats.ini {}).generate "xdg-desktop-portal-termfilechooser.ini" {
     filechooser = {
       default_dir = "/tmp";
-      cmd = "${lib.getExe cmd}";
+      cmd = "${lib.getExe lf-wrapper}";
     };
   };
+
+  cfg = config.soispha.xdg;
 in {
-  services.dbus.enable = true;
-  xdg = {
-    portal = {
-      enable = true;
-      wlr = {
+  options.soispha.xdg = {
+    enable = lib.mkEnableOption "xdg";
+  };
+
+  config = lib.mkIf cfg.enable {
+    home-manager.users.soispha = {
+      xdg = {
+        configFile."xdg-desktop-portal-termfilechooser/config".source = tfcConfigFile;
+
+        desktopEntries = {
+          url-handler = {
+            name = "url-handler";
+            genericName = "Web Browser";
+            exec = "${lib.getExe url-handler} %u";
+            terminal = false;
+            categories = [
+              "Application"
+              "Network"
+              "WebBrowser"
+            ];
+            mimeType = [
+              "text/html"
+              "text/xml"
+              "x-scheme-handler/http"
+              "x-scheme-handler/https"
+              "x-scheme-handler/about"
+              "x-scheme-handler/unknown"
+            ];
+          };
+        };
+      };
+    };
+
+    services.dbus.enable = true;
+
+    xdg = {
+      mime = {
         enable = true;
+        defaultApplications = {
+          "application/pdf" = ["url-handler.desktop"];
+          "application/x-pdf" = ["url-handler.desktop"];
+
+          "text/html" = ["url-handler.desktop"];
+          "text/xml" = ["url-handler.desktop"];
+          "x-scheme-handler/http" = ["url-handler.desktop"];
+          "x-scheme-handler/https" = ["url-handler.desktop"];
+          "x-scheme-handler/about" = ["url-handler.desktop"];
+          "x-scheme-handler/unknown" = ["url-handler.desktop"];
+        };
       };
-      config = {
-        common = {
-          # NOTE: The next entry is supposedly needed for gtk based apps <2023-08-31>
-          default = ["wlr" "gtk"];
-          "org.freedesktop.impl.portal.FileChooser" = ["termfilechooser"];
+
+      portal = {
+        enable = true;
+        wlr = {
+          enable = true;
         };
+        config = {
+          common = {
+            # NOTE: The next entry is supposedly needed for gtk based apps <2023-08-31>
+            default = ["wlr" "gtk"];
+            "org.freedesktop.impl.portal.FileChooser" = ["termfilechooser"];
+          };
 
-        # TODO: Also activate, when on another wlr-based compositor <2023-11-25>
-        river = {
-          default = ["wlr" "gtk"];
-          "org.freedesktop.impl.portal.FileChooser" = ["termfilechooser"];
+          # TODO: Also activate, when on another wlr-based compositor <2023-11-25>
+          river = {
+            default = ["wlr" "gtk"];
+            "org.freedesktop.impl.portal.FileChooser" = ["termfilechooser"];
+          };
         };
+
+        extraPortals = [
+          pkgs.xdg-desktop-portal-gtk
+          pkgs.xdg-desktop-portal-wlr
+          pkgs.xdg-desktop-portal-termfilechooser
+        ];
       };
+    };
 
-      extraPortals = [
-        pkgs.xdg-desktop-portal-gtk
-        pkgs.xdg-desktop-portal-wlr
-        pkgs.xdg-desktop-portal-termfilechooser
+    systemd.user.services.xdg-desktop-portal-termfilechooser = {
+      serviceConfig.ExecStart = [
+        ""
+        "${pkgs.xdg-desktop-portal-termfilechooser}/libexec/xdg-desktop-portal-termfilechooser --loglevel=TRACE"
       ];
     };
   };
-
-  environment.etc."xdg/xdg-desktop-portal-termfilechooser/config".source = tfcConfigFile;
-
-  systemd.user.services.xdg-desktop-portal-termfilechooser = {
-    serviceConfig.ExecStart = [
-      ""
-      "${pkgs.xdg-desktop-portal-termfilechooser}/libexec/xdg-desktop-portal-termfilechooser --loglevel=TRACE"
-    ];
-  };
-  # TODO: mime = {};
 }
diff --git a/modules/by-name/xd/xdg/lf-wrapper.sh b/modules/by-name/xd/xdg/scripts/lf-wrapper.sh
index f85f7bac..f85f7bac 100755
--- a/modules/by-name/xd/xdg/lf-wrapper.sh
+++ b/modules/by-name/xd/xdg/scripts/lf-wrapper.sh
diff --git a/modules/home.legacy/conf/xdg/url_handler.sh b/modules/by-name/xd/xdg/scripts/url-handler.sh
index f15df384..d1c8277d 100755
--- a/modules/home.legacy/conf/xdg/url_handler.sh
+++ b/modules/by-name/xd/xdg/scripts/url-handler.sh
@@ -2,7 +2,7 @@
 
 project="$({
     tskm projects list
-    echo nvim zathura
+    printf "%s\n" nvim zathura
 } | rofi -sep "$(printf "\n")" -dmenu)"
 
 if [ "$project" = "nvim" ]; then
@@ -10,9 +10,10 @@ if [ "$project" = "nvim" ]; then
 elif [ "$project" = "zathura" ]; then
     zathura "$1"
 elif [ "$project" ]; then
-    firefox -P "$project" "$1"
+    tskm open project "$project" "$1"
 else
-    notify-send "(URL HANDLER) No project selected" && exit 1
+    notify-send "(URL HANDLER) No project selected"
+    exit 1
 fi
 
 # vim: ft=sh
diff --git a/modules/by-name/zs/zsh/module.nix b/modules/by-name/zs/zsh/module.nix
index b50e72ac..fd99031b 100644
--- a/modules/by-name/zs/zsh/module.nix
+++ b/modules/by-name/zs/zsh/module.nix
@@ -3,6 +3,7 @@
   lib,
   shell_library,
   system,
+  pkgs,
   ...
 }: let
   cfg = config.soispha.programs.zsh;
@@ -133,8 +134,8 @@ in {
         };
 
         shellAliases = {
-          ll = ". ll";
-          lm = ". lm";
+          ll = ". ${lib.getExe pkgs.ll}";
+          lm = ". ${lib.getExe pkgs.lm}";
         };
       };
     };
diff --git a/modules/common/default.nix b/modules/common/default.nix
index 48fdf241..1c00c710 100644
--- a/modules/common/default.nix
+++ b/modules/common/default.nix
@@ -29,6 +29,7 @@
     };
     polkit.enable = true;
     power.enable = true;
+    xdg.enable = true;
 
     services = {
       adb = {
@@ -56,6 +57,7 @@
       printing.enable = true;
       scanning.enable = true;
       snapper.enable = true;
+      water-reminder.enable = true;
       steam.enable = false;
       systemDiff.enable = true;
       unison = {
@@ -104,6 +106,7 @@
         shell = pkgs.zsh;
       };
       atuin.enable = true;
+      cargo.enable = true;
       direnv.enable = true;
       git.enable = true;
       imv.enable = true;
@@ -192,7 +195,7 @@
       };
       tskm = {
         enable = true;
-        projects = builtins.fromJSON (builtins.readFile ./projects.nix);
+        projects = builtins.fromJSON (builtins.readFile ./projects.json);
       };
       yambar.enable = true;
       yt.enable = true;
diff --git a/modules/home.legacy/conf/default.nix b/modules/home.legacy/conf/default.nix
index 5a10951c..767039c6 100644
--- a/modules/home.legacy/conf/default.nix
+++ b/modules/home.legacy/conf/default.nix
@@ -27,7 +27,5 @@
     ./starship
     ./swayidle
     ./tridactyl
-    ./xdg
-    ./ytcc
   ];
 }
diff --git a/modules/home.legacy/conf/mail/accounts/soispha.nix b/modules/home.legacy/conf/mail/accounts/soispha.nix
index 6e3e6228..11634ab3 100644
--- a/modules/home.legacy/conf/mail/accounts/soispha.nix
+++ b/modules/home.legacy/conf/mail/accounts/soispha.nix
@@ -33,11 +33,11 @@
   #   };
   # };
   smtp = {
-    host = "mail.foss-syndicate.org";
+    host = "mail.vhack.eu";
     port = 465;
   };
   imap = {
-    host = "mail.foss-syndicate.org";
+    host = "mail.vhack.eu";
     port = 993;
   };
   jmap = {
diff --git a/modules/home.legacy/conf/xdg/default.nix b/modules/home.legacy/conf/xdg/default.nix
deleted file mode 100644
index 9751d806..00000000
--- a/modules/home.legacy/conf/xdg/default.nix
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  pkgs,
-  lib,
-  ...
-}: let
-  url_handler = pkgs.writeShellApplication {
-    name = "url-handler";
-    text = builtins.readFile ./url_handler.sh;
-    inheritPath = false;
-    runtimeInputs = [
-      pkgs.rofi
-      pkgs.libnotify
-      pkgs.zathura
-      pkgs.tskm
-    ];
-  };
-in {
-  imports = [
-    ./xdg_vars.nix
-  ];
-
-  xdg = {
-    mimeApps = {
-      enable = true;
-      defaultApplications = {
-        "application/pdf" = ["url_handler.desktop"];
-        "application/x-pdf" = ["url_handler.desktop"];
-
-        "text/html" = ["url_handler.desktop"];
-        "text/xml" = ["url_handler.desktop"];
-        "x-scheme-handler/http" = ["url_handler.desktop"];
-        "x-scheme-handler/https" = ["url_handler.desktop"];
-        "x-scheme-handler/about" = ["url_handler.desktop"];
-        "x-scheme-handler/unknown" = ["url_handler.desktop"];
-      };
-    };
-    desktopEntries = {
-      url-handler = {
-        name = "url-handler";
-        genericName = "Web Browser";
-        exec = "${lib.getExe url_handler} %u";
-        terminal = false;
-        categories = [
-          "Application"
-          "Network"
-          "WebBrowser"
-        ];
-        mimeType = [
-          "text/html"
-          "text/xml"
-          "x-scheme-handler/http"
-          "x-scheme-handler/https"
-          "x-scheme-handler/about"
-          "x-scheme-handler/unknown"
-        ];
-      };
-    };
-  };
-}
diff --git a/modules/home.legacy/conf/xdg/xdg_vars.nix b/modules/home.legacy/conf/xdg/xdg_vars.nix
deleted file mode 100644
index aa2f30d4..00000000
--- a/modules/home.legacy/conf/xdg/xdg_vars.nix
+++ /dev/null
@@ -1,29 +0,0 @@
-{config, ...}: let
-  inherit (config.xdg) dataHome;
-in {
-  # FIXME: Move these options in relevant modules, that are connected to their software.
-  #        <2024-10-21>
-
-  # Variables that only have to be set because special applications fail to set reasonable
-  # defaults (mostly understandable because of backwards-compatibility, but yeah)
-  home.sessionVariables = {
-    CARGO_HOME = "${dataHome}/cargo";
-    GRADLE_USER_HOME = "${dataHome}/gradle";
-
-    #_JAVA_OPTIONS = lib.concatStringsSep " " [
-    #        ''-Djava.util.prefs.userRoot="${config.xdg.configHome}/java"''
-    #        ''-Djavafx.cachedir="${config.xdg.cacheHome}/openjfx"''
-    #      ];
-    #GOPATH = "${config.xdg.dataHome}/go";
-    #GTK2_RC_FILES = "${config.xdg.configHome}/gtk-2.0/gtkrc";
-    #RUSTUP_HOME = "${config.xdg.dataHome}/rustup";
-    #NPM_CONFIG_USERCONFIG = "${config.xdg.configHome}/npm/npmrc";
-    #NUGET_PACKAGES = "${config.xdg.cacheHome}/NuGetPackages";
-    #XAUTHORITY = "${config.xdg.stateHome}/Xauthority";
-    #COMPDUMPFILE = "${config.xdg.dataHome}/zsh/.zcompdump}";
-    #IPYTHONDIR = "${config.xdg.configHome}/ipython";
-    #PARALLEL_HOME = "${config.xdg.configHome}/parallel";
-    #STACK_XDG = "1";
-    #WINEPREFIX = "${config.xdg.dataHome}/wine";
-  };
-}
diff --git a/modules/home.legacy/conf/ytcc/default.nix b/modules/home.legacy/conf/ytcc/default.nix
deleted file mode 100644
index 87300ec1..00000000
--- a/modules/home.legacy/conf/ytcc/default.nix
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  config,
-  pkgs,
-  ...
-}: {
-  xdg.configFile."ytcc/ytcc.conf".source = pkgs.substituteAll {
-    src = ./ytcc.conf;
-    download_dir = "${config.xdg.userDirs.download}/ytcc";
-    xdg_data_home = config.xdg.dataHome;
-  };
-}
diff --git a/modules/home.legacy/conf/ytcc/ytcc.conf b/modules/home.legacy/conf/ytcc/ytcc.conf
deleted file mode 100644
index 289843ad..00000000
--- a/modules/home.legacy/conf/ytcc/ytcc.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-[ytcc]
-download_dir = @download_dir@
-mpv_flags = --really-quiet --ytdl --ytdl-format=bestvideo[height<=?1080]+bestaudio/best --speed=2.7
-download_subdirs = true
-order_by = playlists:asc, publish_date:desc
-video_attrs = id, title, publish_date, duration, playlists
-playlist_attrs = name, url, tags, reverse
-db_path = @xdg_data_home@/ytcc/ytcc.db
-date_format = %Y-%m-%d
-max_update_fail = 5
-max_update_backlog = 20
-age_limit = 0
-
-[tui]
-alphabet = sdfervghnuiojkl
-default_action = play_video
-
-[theme]
-prompt_download_audio = 2
-prompt_download_video = 4
-prompt_play_audio = 2
-prompt_play_video = 4
-prompt_mark_watched = 1
-table_alternate_background = 245
-plain_label_text = 244
-
-[youtube_dl]
-format = bestvideo[height<=?1080]+bestaudio/best
-output_template = %(title)s.%(ext)s
-ratelimit = 0
-retries = 0
-subtitles = off
-thumbnail = true
-skip_live_stream = true
-merge_output_format = mkv
-max_duration = 0
-restrict_filenames = false
diff --git a/modules/home.legacy/pkgs/default.nix b/modules/home.legacy/pkgs/default.nix
index 31942f0d..fd8b811a 100644
--- a/modules/home.legacy/pkgs/default.nix
+++ b/modules/home.legacy/pkgs/default.nix
@@ -85,7 +85,8 @@ with pkgs; let
 
     SystemUpdate = [
       fupdate # Generic update tool.
-      update-sys # System update tool (meant to slot into `fupdate`).
+      fupdate-sys # System update tool (meant to slot into `fupdate`).
+      fupdate-flake # Nix flake update tool (meant to slot into `fupdate`).
     ];
 
     FileListers = [
@@ -93,8 +94,6 @@ with pkgs; let
       fd # Simple, fast and user-friendly alternative to find
       ripgrep # A search tool that combines the usability of ag with the raw speed of grep
       file # Show information about a file
-      ll # Wrapper around `lf` to automatically change the path
-      lm # Wrapper around `ll` to automatically cd to the last accessed path
     ];
 
     Programming = {