From f165c673fba5439e2df4f67eec1e8520487e31fd Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Fri, 17 Jul 2026 12:21:23 +0800 Subject: [PATCH 1/2] feat(night-shift): default Night Shift to always on Night Shift state lives in the per-user CoreBrightness session and is not exposed through any plist system.defaults can write, so express it as a home-manager launchd user agent that calls nightlight on login. Clear the schedule before turning it on, since sunset-to-sunrise would otherwise flip Night Shift back off at sunrise. RunAtLoad without a StartInterval keeps this a default rather than an enforcement: a manual toggle sticks until the next login. --- home-manager/services/default.nix | 2 + .../services/night-shift/apply-night-shift.sh | 12 ++++ home-manager/services/night-shift/default.nix | 30 +++++++++ spec/night_shift_spec.sh | 62 +++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 home-manager/services/night-shift/apply-night-shift.sh create mode 100644 home-manager/services/night-shift/default.nix create mode 100644 spec/night_shift_spec.sh diff --git a/home-manager/services/default.nix b/home-manager/services/default.nix index 1ff2962c3..48a8aff1e 100644 --- a/home-manager/services/default.nix +++ b/home-manager/services/default.nix @@ -21,6 +21,7 @@ let keydApplicationMapper = ./keyd-application-mapper; makeUpdater = import ./make-updater { inherit pkgs; }; neversslKeepalive = import ./neverssl-keepalive { inherit pkgs; }; + nightShift = import ./night-shift { inherit pkgs; }; obsidian = import ./obsidian { inherit config pkgs inputs; }; ollama = ./ollama; qmd = ./qmd; @@ -46,6 +47,7 @@ in keydApplicationMapper makeUpdater neversslKeepalive + nightShift obsidian ollama qmd diff --git a/home-manager/services/night-shift/apply-night-shift.sh b/home-manager/services/night-shift/apply-night-shift.sh new file mode 100644 index 000000000..4cd6996fa --- /dev/null +++ b/home-manager/services/night-shift/apply-night-shift.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -euo pipefail + +nightlight_bin="@nightlightBin@" +temperature=@temperature@ + +# A sunset-to-sunrise schedule turns Night Shift back off at sunrise, so the +# schedule has to be cleared before `on` can mean "stays on". +"$nightlight_bin" schedule stop +"$nightlight_bin" temp "$temperature" +"$nightlight_bin" on diff --git a/home-manager/services/night-shift/default.nix b/home-manager/services/night-shift/default.nix new file mode 100644 index 000000000..8f6f106c4 --- /dev/null +++ b/home-manager/services/night-shift/default.nix @@ -0,0 +1,30 @@ +{ pkgs }: +let + # 0 = least warm, 100 = warmest. + temperature = 100; + + applyNightShiftScript = pkgs.replaceVars ./apply-night-shift.sh { + nightlightBin = "${pkgs.nightlight}/bin/nightlight"; + inherit temperature; + }; +in +{ + # Night Shift state lives in the per-user CoreBrightness session and is not + # exposed through any plist `system.defaults` can write, so the only way to + # express "on by default" is to talk to that session on login. + # + # RunAtLoad without a StartInterval deliberately makes this a default rather + # than an enforcement: a manual toggle sticks until the next login. + launchd.agents.night-shift = pkgs.lib.mkIf pkgs.stdenv.isDarwin { + enable = true; + config = { + ProgramArguments = [ + "${pkgs.bash}/bin/bash" + "${applyNightShiftScript}" + ]; + RunAtLoad = true; + StandardOutPath = "/tmp/night-shift.log"; + StandardErrorPath = "/tmp/night-shift.error.log"; + }; + }; +} diff --git a/spec/night_shift_spec.sh b/spec/night_shift_spec.sh new file mode 100644 index 000000000..f04ec400c --- /dev/null +++ b/spec/night_shift_spec.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2329 + +Describe 'home-manager/services/night-shift/apply-night-shift.sh' +SCRIPT="$PWD/home-manager/services/night-shift/apply-night-shift.sh" + +Describe 'script properties' +It 'uses bash shebang' +When run bash -c "head -1 '$SCRIPT'" +The output should include '#!/usr/bin/env bash' +End + +It 'uses strict mode' +When run bash -c "head -5 '$SCRIPT'" +The output should include 'set -euo pipefail' +End + +It 'passes bash syntax check after replacing placeholders' +When run bash -c "sed -e 's|@nightlightBin@|/usr/bin/true|g' -e 's|@temperature@|100|g' '$SCRIPT' | bash -n" +The status should be success +End +End + +setup_night_shift_script() { + TEST_DIR=$(mktemp -d) + NIGHTLIGHT_LOG="$TEST_DIR/nightlight.log" + NIGHTLIGHT_BIN="$TEST_DIR/nightlight" + PREPROCESSED_SCRIPT="$TEST_DIR/apply-night-shift.sh" + : >"$NIGHTLIGHT_LOG" + + cat >"$NIGHTLIGHT_BIN" <<'EOF' +#!/usr/bin/env bash +set -eu +printf '%s\n' "$*" >>"$NIGHTLIGHT_LOG" +EOF + chmod +x "$NIGHTLIGHT_BIN" + + sed \ + -e "s|@nightlightBin@|$NIGHTLIGHT_BIN|g" \ + -e 's|@temperature@|100|g' \ + "$SCRIPT" >"$PREPROCESSED_SCRIPT" + chmod +x "$PREPROCESSED_SCRIPT" +} + +cleanup_night_shift_script() { + rm -rf "$TEST_DIR" +} + +Describe 'applying the Night Shift default' +Before 'setup_night_shift_script' +After 'cleanup_night_shift_script' + +It 'clears the schedule before turning Night Shift on' +When run bash -c ': >"'"$NIGHTLIGHT_LOG"'"; NIGHTLIGHT_LOG="'"$NIGHTLIGHT_LOG"'" "'"$PREPROCESSED_SCRIPT"'" >/dev/null && cat "'"$NIGHTLIGHT_LOG"'"' +The status should be success +The line 1 of output should eq 'schedule stop' +The line 2 of output should eq 'temp 100' +The line 3 of output should eq 'on' +End +End + +End From a8f2cdf55a3297168984ec6b291611f1e400ddce Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Fri, 17 Jul 2026 12:38:49 +0800 Subject: [PATCH 2/2] style(gh): format extensions list treefmt expands multi-element lists one entry per line. Unformatted since the gh-stack extension was added in 797139fc. --- home-manager/programs/gh/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/home-manager/programs/gh/default.nix b/home-manager/programs/gh/default.nix index 65adaa25a..90a166d6d 100644 --- a/home-manager/programs/gh/default.nix +++ b/home-manager/programs/gh/default.nix @@ -2,7 +2,10 @@ { programs.gh = { enable = true; - extensions = with pkgs; [ gh-markdown-preview gh-stack ]; + extensions = with pkgs; [ + gh-markdown-preview + gh-stack + ]; settings = { editor = "nvim"; git_protocol = "https";