aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArpit Chakladar <arpitchakladar@gmail.com>2026-09-24 05:06:49 +0530
committerArpit Chakladar <arpitchakladar@gmail.com>2026-09-24 05:06:49 +0530
commita0213d48a3fea3b2209c36390331de101fb7575f (patch)
tree57f31b37ec4f2d0b4a109c53db61393d05d9cb1a
parent3a6e45ad18c519b21c9cadb2d374148647886b05 (diff)
parentc37c4a69fc895099109fc5211bf9449592ebc518 (diff)
downloadhome-manager-config-a0213d48a3fea3b2209c36390331de101fb7575f.tar.gz
home-manager-config-a0213d48a3fea3b2209c36390331de101fb7575f.zip
Merge branch 'neomutt-autosyncing-daemon'
-rw-r--r--modules/communication/neomutt/default.nix58
-rw-r--r--modules/communication/neomutt/neomutt-launcher.sh12
-rw-r--r--modules/communication/neomutt/neomutt-sync-daemon.sh39
-rw-r--r--modules/file-management/yazi/default.nix2
-rw-r--r--modules/gaming/heroic/default.nix2
5 files changed, 104 insertions, 9 deletions
diff --git a/modules/communication/neomutt/default.nix b/modules/communication/neomutt/default.nix
index e091a7d..6bc363b 100644
--- a/modules/communication/neomutt/default.nix
+++ b/modules/communication/neomutt/default.nix
@@ -8,6 +8,12 @@
let
cfg = config.communication.neomutt;
+ mbsyncNamesFromName = (import ./lib.nix { inherit lib; }).mbsyncNamesFromName;
+
+ fullSyncChannels = lib.mapAttrsToList (name: account: (mbsyncNamesFromName name).channels.full) (
+ lib.filterAttrs (name: account: account.enable) config.communication.neomutt.accounts
+ );
+
neomuttSyncScript = pkgs.writeShellApplication {
name = "neomutt-sync";
runtimeInputs = [
@@ -23,6 +29,37 @@ let
text = builtins.readFile ./neomutt-sync.sh;
};
+ neomuttSyncDaemon = pkgs.writeShellApplication {
+ name = "neomutt-sync-daemon";
+ runtimeInputs = [
+ config.terminal.bash.package
+ pkgs.coreutils
+ pkgs.procps
+ config.programs.mbsync.package
+ config.programs.notmuch.package
+ ];
+ text = builtins.readFile ./neomutt-sync-daemon.sh;
+ };
+
+ neomuttLauncher = pkgs.writeShellApplication {
+ name = "neomutt-launcher";
+ runtimeInputs = [
+ pkgs.systemd
+ pkgs.procps
+ pkgs.neomutt
+ pkgs.urlscan
+ ];
+ text =
+ builtins.replaceStrings
+ [
+ "@@NEOMUTT_BIN@@"
+ ]
+ [
+ (lib.getExe pkgs.neomutt)
+ ]
+ (builtins.readFile ./neomutt-launcher.sh);
+ };
+
neomuttSyncCompletion =
pkgs.runCommand "neomutt-sync-completion"
{
@@ -71,21 +108,18 @@ in
builtins.replaceStrings [ "@@HTML_VIEWER@@" ] [ (lib.getExe config.web.chawan.package) ]
(builtins.readFile ./mailcap);
home.file.".local/share/icons/hicolor/scalable/apps/neomutt.svg".source =
- config.lib.file.mkOutOfStoreSymlink "${config.programs.neomutt.package}/share/neomutt/logo/neomutt.svg";
+ "${config.programs.neomutt.package}/share/neomutt/logo/neomutt.svg";
+
programs.neomutt = {
enable = true;
package = pkgs.symlinkJoin {
name = "neomutt-wrapped";
paths = [
+ neomuttLauncher
pkgs.neomutt
neomuttSync
];
- nativeBuildInputs = [ pkgs.makeWrapper ];
- postBuild = ''
- wrapProgram $out/bin/neomutt \
- --prefix PATH : ${config.home.profileDirectory}/bin:${lib.makeBinPath [ pkgs.urlscan ]}
- '';
- meta.mainProgram = "neomutt";
+ meta.mainProgram = "neomutt-launcher";
};
sidebar.enable = true;
sort = "reverse-threads";
@@ -96,6 +130,16 @@ in
builtins.readFile ./.neomuttrc
);
};
+
+ systemd.user.services.neomutt-sync = {
+ Unit = {
+ Description = "Full mail sync while neomutt is running";
+ };
+ Service = {
+ Type = "simple";
+ ExecStart = "${lib.getExe neomuttSyncDaemon} ${lib.concatStringsSep " " fullSyncChannels}";
+ };
+ };
})
(lib.mkIf (cfg.enable && config.terminal.kitty.enable) {
xdg.desktopEntries."neomutt" = {
diff --git a/modules/communication/neomutt/neomutt-launcher.sh b/modules/communication/neomutt/neomutt-launcher.sh
new file mode 100644
index 0000000..62cbe09
--- /dev/null
+++ b/modules/communication/neomutt/neomutt-launcher.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+# Wrapped neomutt: keeps the neomutt-sync systemd daemon alive for the
+# lifetime of a neomutt session.
+set -uo pipefail
+
+systemctl --user start neomutt-sync.service || true
+stop_service() {
+ pgrep -x neomutt >/dev/null || systemctl --user stop neomutt-sync.service || true
+}
+trap stop_service EXIT
+
+"@@NEOMUTT_BIN@@" "$@"
diff --git a/modules/communication/neomutt/neomutt-sync-daemon.sh b/modules/communication/neomutt/neomutt-sync-daemon.sh
new file mode 100644
index 0000000..a78ef5f
--- /dev/null
+++ b/modules/communication/neomutt/neomutt-sync-daemon.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+# systemd daemon: full-sync the -full channels every 10 minutes while
+# neomutt is open. Started/stopped by the wrapped neomutt launcher.
+
+set -uo pipefail
+
+INTERVAL="$((10 * 60))"
+MBSYNCRC="${MBSYNCRC:-$HOME/.config/mbsync/.mbsyncrc}"
+
+if [[ $# -eq 0 ]]; then
+ echo "Usage: $0 <mbsync-channel> [channel...]" >&2
+ exit 2
+fi
+
+sync_once() {
+ echo "Syncing: $*"
+
+ mbsync -c "$MBSYNCRC" "$@"
+ local status=$?
+ if ((status != 0)); then
+ echo "mbsync failed (status $status) for: $*" >&2
+ return "$status"
+ fi
+
+ echo "Indexing new mail with notmuch..."
+ notmuch new --quiet
+}
+
+while true; do
+ sync_once "$@"
+ sleep "$INTERVAL"
+
+ # Safety net: the launcher stops this service when neomutt exits; if that
+ # didn't happen (hard kill), bail out once neomutt is gone.
+ if ! pgrep -x neomutt >/dev/null; then
+ echo "neomutt is not running; stopping sync daemon" >&2
+ exit 0
+ fi
+done
diff --git a/modules/file-management/yazi/default.nix b/modules/file-management/yazi/default.nix
index 72a4568..b56c816 100644
--- a/modules/file-management/yazi/default.nix
+++ b/modules/file-management/yazi/default.nix
@@ -65,7 +65,7 @@ in
};
home.file.".local/share/icons/hicolor/scalable/apps/yazi.png" = {
- source = config.lib.file.mkOutOfStoreSymlink "${cfg.package}/share/pixmaps/yazi.png";
+ source = "${cfg.package}/share/pixmaps/yazi.png";
};
home.sessionVariables = {
diff --git a/modules/gaming/heroic/default.nix b/modules/gaming/heroic/default.nix
index 61eceb5..cf4c03d 100644
--- a/modules/gaming/heroic/default.nix
+++ b/modules/gaming/heroic/default.nix
@@ -35,7 +35,7 @@ in
home.packages = [ cfg.package ];
home.file.".local/share/icons/hicolor/scalable/apps/com.heroicgameslauncher.hgl.svg".source =
- config.lib.file.mkOutOfStoreSymlink "${pkgs.heroic}/share/icons/hicolor/scalable/apps/com.heroicgameslauncher.hgl.svg";
+ "${pkgs.heroic}/share/icons/hicolor/scalable/apps/com.heroicgameslauncher.hgl.svg";
xdg.desktopEntries."heroic" = {
name = "Heroic Games Launcher";