From e0184ead26cb1c670e99163d33fb547de33fc14b Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sat, 18 Oct 2025 10:20:55 -0500 Subject: [PATCH 1/8] config (darwin): add preferences to manage AltTab.app --- homes/darwin.nix | 2 ++ programs/alttab.nix | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 programs/alttab.nix diff --git a/homes/darwin.nix b/homes/darwin.nix index 4fb4601..12932af 100644 --- a/homes/darwin.nix +++ b/homes/darwin.nix @@ -1,4 +1,6 @@ { config, lib, pkgs, pkgs-unstable, ... }: { + + imports = [ ./../programs/alttab.nix ]; home = { packages = with pkgs; [ asitop diff --git a/programs/alttab.nix b/programs/alttab.nix new file mode 100644 index 0000000..606ebeb --- /dev/null +++ b/programs/alttab.nix @@ -0,0 +1,42 @@ +{ lib, ... }: +let + altTabPref = { pref, value }: + let + defaults-bin = "/usr/bin/defaults"; + altTabId = "com.lwouis.alt-tab-macos"; + pref-type = builtins.typeOf value; + + val-string = if pref-type == "bool" then + "-bool ${if value then "true" else "false"}" + else + "-${pref-type} ${toString value}"; + in "${defaults-bin} write ${altTabId} ${pref} ${val-string}"; +in { + home.activation.setAltTabPrefs = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + ${altTabPref { + pref = "appearanceStyle"; + value = 0; + }} + ${altTabPref { + pref = "nextWindowGesture"; + value = 1; + }} + ${altTabPref { + pref = "screenRecordingPermissionSkipped"; + value = true; + }} + ${altTabPref { + pref = "showFullscreenWindows"; + value = 0; + }} + ${altTabPref { + pref = "showHiddenWindows"; + value = 1; + }} + ${altTabPref { + pref = "updatePolicy"; + value = 2; + }} + ''; + +} From 8b173560bf9b0806fe544549d34f665170da4757 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 19 Oct 2025 08:07:10 -0500 Subject: [PATCH 2/8] module: add `defaults` module MacOS stores most of its preferences in plist files. While those plist files can be manipulated directly, it is generally safer (albeit less declarative) to manipulate app-level plists via the `defaults` cli. This module allows for manipulation of arbitrary app configs via the `defaults` cli appropriate for use in home-manager. --- modules/defaults.nix | 92 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 modules/defaults.nix diff --git a/modules/defaults.nix b/modules/defaults.nix new file mode 100644 index 0000000..cdb9f00 --- /dev/null +++ b/modules/defaults.nix @@ -0,0 +1,92 @@ +# WARNING: This module was "vibe coded" by Claude Sonnet 4.5 Thinking +# Nix modules are mostly boilerplace, so the logic is (mostly) mine, and the +# rest comes from Claude. For reference, here was my prompt: +# +# I would like to write a new module for managing MacOS apps via the `defaults` +# cli. Ideally, the syntax that I want to include in my home-manager config +# should look like: +# +# ```nix +# darwin-defaults = { +# "com.fpfxtknjju.wbgcdolfev" = { +# centerTasksAndButtons = false; +# pinList = [ +# { action = "finderNewWindow"; bundleIdentifier = "com.apple.finder"; } +# { action = "firefoxNewWindow"; bundleIdentifier = "org.mozilla.firefox"; } +# { action = "launchOrActivateApp"; bundleIdentifier = "com.electron.logseq"; } +# ]; +# }; +# "com.lwouis.alt-tab-macos" = { +# screenRecordingPermissionSkipped = true; +# nextWindowGesture = 1; +# }; +# }; +# ``` +# +# This should be fairly easy to implement, as `defaults` accepts (escaped) plist +# strings, and Nix provides lib.generators.toPlist. Can you help me write the +# module, please? + +{ config, lib, pkgs, ... }: +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + inherit (lib) mkOption types mkIf; + inherit (lib.generators) toPlist; + + cfg = config.defaults; + + # Convert domain settings to defaults import command + domainToScript = domain: settings: + let plistContent = toPlist { escape = true; } settings; + in '' + $DRY_RUN_CMD echo "Applying defaults for ${domain}..." + $DRY_RUN_CMD /usr/bin/defaults import ${ + lib.escapeShellArg domain + } - <<'EOF' + ${plistContent} + EOF + ''; + + # Generate all activation scripts + activationScript = + lib.concatStringsSep "\n" (lib.mapAttrsToList domainToScript cfg); + +in { + options.defaults = mkOption { + type = types.attrsOf (types.attrsOf types.anything); + default = { }; + description = '' + Configuration for macOS defaults by domain. + + Each attribute set key represents a domain (typically an app bundle identifier), + and its value is an attribute set of preference keys and values that will be + converted to a plist and imported using the `defaults` command. + + This module only works on macOS (Darwin) systems. + ''; + example = lib.literalExpression '' + { + "com.apple.dock" = { + autohide = true; + tilesize = 48; + orientation = "left"; + }; + "com.apple.finder" = { + AppleShowAllFiles = true; + ShowPathbar = true; + FXEnableExtensionChangeWarning = false; + }; + } + ''; + }; + + config = mkIf (isDarwin && cfg != { }) { + home.activation.defaults = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + if [[ -x /usr/bin/defaults ]]; then + ${activationScript} + else + echo "Warning: /usr/bin/defaults not found. Skipping darwin-defaults configuration." + fi + ''; + }; +} From dafe6c062578c1eccbdcf2f95f41c8d0c741a0ab Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:08:09 -0500 Subject: [PATCH 3/8] feat (module): add app restart to defaults module --- modules/defaults.nix | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/defaults.nix b/modules/defaults.nix index cdb9f00..dd5b2d7 100644 --- a/modules/defaults.nix +++ b/modules/defaults.nix @@ -37,14 +37,15 @@ let # Convert domain settings to defaults import command domainToScript = domain: settings: - let plistContent = toPlist { escape = true; } settings; + let + plistContent = toPlist { escape = true; } settings; + escapedDomain = lib.escapeShellArg domain; in '' $DRY_RUN_CMD echo "Applying defaults for ${domain}..." - $DRY_RUN_CMD /usr/bin/defaults import ${ - lib.escapeShellArg domain - } - <<'EOF' + $DRY_RUN_CMD /usr/bin/defaults import -app ${escapedDomain} - <<'EOF' ${plistContent} EOF + $DRY_RUN_CMD killall ${escapedDomain} && open -a ${escapedDomain} ''; # Generate all activation scripts From 5866fd41de93f7f2b6a7ace1a14ab223b4df8b42 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:19:52 -0500 Subject: [PATCH 4/8] config (Taskbar.app): add initial config for Taskbar.app --- homes/darwin.nix | 6 +++++- programs/taskbar.nix | 49 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 programs/taskbar.nix diff --git a/homes/darwin.nix b/homes/darwin.nix index 12932af..d3c2982 100644 --- a/homes/darwin.nix +++ b/homes/darwin.nix @@ -1,6 +1,10 @@ { config, lib, pkgs, pkgs-unstable, ... }: { - imports = [ ./../programs/alttab.nix ]; + imports = [ + ./../modules/defaults.nix + ./../programs/alttab.nix + ./../programs/taskbar.nix + ]; home = { packages = with pkgs; [ asitop diff --git a/programs/taskbar.nix b/programs/taskbar.nix new file mode 100644 index 0000000..992c1f6 --- /dev/null +++ b/programs/taskbar.nix @@ -0,0 +1,49 @@ +{ ... }: { + defaults."Taskbar" = { + centerTasksAndButtons = false; + hideReviewOptions = true; + permissionsResetOnce = true; + pinList = [ + { + action = "finderNewWindow"; + bundleIdentifier = "com.apple.finder"; + } + { + action = "launchOrActivateApp"; + bundleIdentifier = "com.apple.AppStore"; + } + { + action = "firefoxNewWindow"; + bundleIdentifier = "org.mozilla.firefox"; + } + { + action = "launchOrActivateApp"; + bundleIdentifier = "com.apple.systempreferences"; + } + { + action = "launchOrActivateApp"; + bundleIdentifier = "com.electron.logseq"; + } + { + action = "launchOrActivateApp"; + bundleIdentifier = "org.mozilla.thunderbird"; + } + { + action = "launchOrActivateApp"; + bundleIdentifier = + "com.apple.Safari.WebApp.2F51A6D0-087A-438F-92D3-A73FE09CB4CC"; + } + { + action = "launchOrActivateApp"; + bundleIdentifier = + "com.apple.Safari.WebApp.5EC6478E-03A6-4147-8A4D-6EF3DE3F06D3"; + } + ]; + sendCrashReports = true; + showMenubarIcon = false; + showThumbnails = true; + showWindowTitleInThumbails = true; + taskViewMaxWidth = 200; + updatePolicy = 0; + }; +} From 88873d06f2defa1d88fc7371d08a153ef7f948ed Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:21:20 -0500 Subject: [PATCH 5/8] refactor (AltTab.app): Use defaults module for AltTab.app --- programs/alttab.nix | 50 ++++++++------------------------------------- 1 file changed, 9 insertions(+), 41 deletions(-) diff --git a/programs/alttab.nix b/programs/alttab.nix index 606ebeb..1901f4d 100644 --- a/programs/alttab.nix +++ b/programs/alttab.nix @@ -1,42 +1,10 @@ -{ lib, ... }: -let - altTabPref = { pref, value }: - let - defaults-bin = "/usr/bin/defaults"; - altTabId = "com.lwouis.alt-tab-macos"; - pref-type = builtins.typeOf value; - - val-string = if pref-type == "bool" then - "-bool ${if value then "true" else "false"}" - else - "-${pref-type} ${toString value}"; - in "${defaults-bin} write ${altTabId} ${pref} ${val-string}"; -in { - home.activation.setAltTabPrefs = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - ${altTabPref { - pref = "appearanceStyle"; - value = 0; - }} - ${altTabPref { - pref = "nextWindowGesture"; - value = 1; - }} - ${altTabPref { - pref = "screenRecordingPermissionSkipped"; - value = true; - }} - ${altTabPref { - pref = "showFullscreenWindows"; - value = 0; - }} - ${altTabPref { - pref = "showHiddenWindows"; - value = 1; - }} - ${altTabPref { - pref = "updatePolicy"; - value = 2; - }} - ''; - +{ ... }: { + defaults."AltTab" = { + appearanceStyle = 0; + nextWindowGesture = 1; + screenRecordingPermissionSkipped = true; + showFullscreenWindows = 0; + showHiddenWindows = 1; + updatePolicy = 2; + }; } From c592c01f6e55bf1d160e8c4e6dcd8fc7bd7c7163 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:24:56 -0500 Subject: [PATCH 6/8] refactor (yt-dlp): Move yt-dlp settings to own file --- homes/common.nix | 2 +- programs/yt-dlp.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 programs/yt-dlp.nix diff --git a/homes/common.nix b/homes/common.nix index b68983f..2b452dd 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -16,6 +16,7 @@ in { ./../programs/lsd.nix ./../programs/neovim.nix ./../programs/starship.nix + ./../programs/yt-dlp.nix ]; home = { stateVersion = "23.11"; @@ -107,7 +108,6 @@ in { gh.enable = true; gpg.enable = true; pandoc.enable = true; - yt-dlp.enable = true; }; xdg = { dataFile = { "julia/config/startup.jl".source = ./../dotfiles/startup.jl; }; diff --git a/programs/yt-dlp.nix b/programs/yt-dlp.nix new file mode 100644 index 0000000..9ee29b7 --- /dev/null +++ b/programs/yt-dlp.nix @@ -0,0 +1 @@ +{ ... }: { programs.yt-dlp = { enable = true; }; } From beb8aa13039772ef30a23cb1ddfff02a55ed4120 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:28:13 -0500 Subject: [PATCH 7/8] feat (yt-dlp): Use unstable yt-dlp YouTube constantly changes settings to mess with downloaders. Try to mitigate that by using the most bleeding-edge version of yt-dlp available. --- programs/yt-dlp.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/programs/yt-dlp.nix b/programs/yt-dlp.nix index 9ee29b7..fa2069a 100644 --- a/programs/yt-dlp.nix +++ b/programs/yt-dlp.nix @@ -1 +1,6 @@ -{ ... }: { programs.yt-dlp = { enable = true; }; } +{ pkgs-unstable, ... }: { + programs.yt-dlp = { + enable = true; + package = pkgs-unstable.yt-dlp; + }; +} From cc173b20b9b7309d235be8e76668fbc3373f0212 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:30:51 -0500 Subject: [PATCH 8/8] dock (corianne): Switch to using Taskbar --- systems/darwin/corianne.nix | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index 9628dcd..db34258 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -39,9 +39,10 @@ in { system.primaryUser = "millironx"; system.defaults.dock = { - autohide = false; + autohide = true; minimize-to-application = true; mru-spaces = false; + orientation = "left"; persistent-apps = let dedupDotApp = appName: if pkgs.lib.strings.hasSuffix ".app" appName then @@ -69,20 +70,10 @@ in { }; in [ (sysApp "Firefox") - (chromeApp "Messages") - (sysApp "Signal") (sysApp "Thunderbird") - (localApp "Immich") (sysApp "Logseq") (sysApp "Zed") (sysApp "Steam") - (sysApp "Amperfy") - (sysApp "Microsoft Word") - (sysApp "Microsoft Excel") - (sysApp "Microsoft PowerPoint") - (localApp "Canvas") - (sysApp "Zotero") - (localApp "VetPrep") (chromeApp "Instinct Dashboard") (chromeApp "Carestream") ]; @@ -213,6 +204,7 @@ in { "slack" "stats" "steam" + "taskbar" "textmate" "thunderbird@esr" "ungoogled-chromium"