Skip to content

Dankman - #1272

Merged
shunkakinoki merged 14 commits into
mainfrom
dankman
Mar 25, 2026
Merged

Dankman#1272
shunkakinoki merged 14 commits into
mainfrom
dankman

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Mar 25, 2026

Copy link
Copy Markdown
Owner

Summary by cubic

Adds cross-platform notification and clipboard helpers, wires them into claude, codex, and tmux, and enables automatic light/dark switching on Linux with darkman and custom ghostty themes. Scripts now live in ~/.local/scripts, are on PATH for bash, fish, and zsh, and include tests across macOS and Linux.

  • New Features

    • ~/.local/scripts/notify-local: unified notifier for macOS (osascript), Linux (notify-send), and terminal-notifier; used by claude and codex with PATH/~/.local/scripts fallback.
    • ~/.local/scripts/clipboard-copy: pipe to pbcopy, wl-copy, xclip, or xsel; used by tmux.
    • Linux theme sync: darkman service with GTK/dconf scripts and XDG portal integration; ghostty now uses dark:Dracula Custom,light:Catppuccin Latte Custom.
  • Bug Fixes

    • darkman theming: removed GTK_THEME=Adwaita:dark and GTK “prefer-dark” overrides, and ensured scripts find dconf via @dconf@ so portal-aware apps follow system light/dark mode.

Written for commit 576d953. Summary will update on new commits.

Copilot AI review requested due to automatic review settings March 25, 2026 04:24
@mesa-dot-dev

mesa-dot-dev Bot commented Mar 25, 2026

Copy link
Copy Markdown

You do not have enough credits to review this pull request. Please purchase more credits to continue.

@coderabbitai

coderabbitai Bot commented Mar 25, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR introduces cross-platform local scripts for clipboard and notification handling, replaces hardcoded notification mechanisms with these scripts, adds Darkman dark/light mode integration with theme switching, creates custom Ghostty themes, updates all shell configurations to expose new scripts in PATH, and removes hardcoded GTK dark-mode preferences in favor of dynamic theme switching.

Changes

Cohort / File(s) Summary
Local scripts infrastructure
home-manager/modules/local-scripts/clipboard-copy.sh, home-manager/modules/local-scripts/notify-local.sh, home-manager/modules/local-scripts/default.nix
New Bash scripts for cross-platform clipboard operations (pbcopy/wl-copy/xclip/xsel fallback) and desktop notifications (osascript/notify-send/terminal-notifier fallback). Home Manager module installs both scripts to ~/.local/scripts/ as executable files.
Shell PATH initialization
home-manager/programs/bash/default.nix, home-manager/programs/fish/default.nix, home-manager/programs/zsh/default.nix
Added ~/.local/scripts to PATH in bashrc, fish loginShellInit/interactiveShellInit, and zsh initialization, exposing local scripts in all shell environments.
Configuration updates to use local scripts
config/claude/notify.sh, config/codex/config.toml, config/codex/config.tpl.toml, home-manager/programs/tmux/tmux.conf
Replaced hardcoded notification (osascript) and clipboard (pbcopy/wl-copy/xclip inline logic) commands with calls to new local scripts (~/.local/scripts/notify-local and ~/.local/scripts/clipboard-copy).
Ghostty custom themes
config/ghostty/config, config/ghostty/default.nix, config/ghostty/themes/Dracula Custom, config/ghostty/themes/Catppuccin Latte Custom
Added two new custom theme files with explicit color palettes and UI styling. Updated Ghostty config to use dual-variant theme mapping (dark: Dracula Custom, light: Catppuccin Latte Custom). Removed split-divider styling. Registered new theme files in Home Manager configuration.
Darkman dark/light mode service
home-manager/services/darkman/default.nix, home-manager/services/darkman/dark-mode.sh, home-manager/services/darkman/light-mode.sh, home-manager/services/default.nix, named-hosts/matic/default.nix
Introduced Darkman service integration (Linux-only) with mode scripts that switch GTK theme and dconf interface color-scheme. Enabled darkman in XDG portal settings alongside gtk implementation.
Theme system updates
config/gtk/default.nix, config/hyprland/hyprland.conf
Removed hardcoded dark theme preferences (gtk-application-prefer-dark-theme, GTK_THEME env var, dconf prefer-dark setting) in favor of dynamic Darkman-driven switching. Updated GTK theme from Adwaita-dark to Adwaita for automatic switching.
Module integration
home-manager/modules/default.nix
Added local-scripts module to Home Manager module imports.
Test coverage
spec/clipboard_copy_spec.sh, spec/notify_local_spec.sh, spec/darkman_spec.sh, spec/coverage_spec.sh, spec/notify_spec.sh
New comprehensive test specs for clipboard-copy and notify-local scripts with multi-backend fallback testing. Added darkman script tests for shebang, strict mode, and dconf writes. Updated coverage tracking and notify hook tests to use new notify-local script.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

  • PR #1220: Modifies tmux @clipboard_cmd configuration to define cross-platform fallback logic that is now replaced by the new clipboard-copy script.
  • PR #362: Updates Ghostty theme configuration setting to use custom theme variants with dark/light mapping.
  • PR #421: Adds and maintains spec/coverage_spec.sh for shell script test coverage tracking, which this PR extends with new script entries.

Suggested labels

codex

Poem

🐰 Beneath the ~/.local trees,
Scripts dance in the gentle breeze,
Darkman whispers: light or dark,
Clipboard hops and notifications spark,
Cross-platform magic, leaving its mark! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Dankman' is vague and does not clearly convey the main changes; it appears to be a play on words related to 'darkman' but lacks specificity. Use a more descriptive title such as 'Add cross-platform notification/clipboard helpers and darkman theme switching' to clearly communicate the primary changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description is directly related to the changeset. It accurately describes the main objectives: adding cross-platform notification and clipboard helper scripts, integrating them into existing tools, enabling automatic light/dark theme switching, and organizing scripts in ~/.local/scripts with proper PATH configuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dankman

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the system's adaptability by introducing a robust, automated dark/light theme switching mechanism via the darkman service and by refactoring notification and clipboard functionalities into generic, cross-platform utilities. These changes streamline configuration, improve consistency across different environments, and prepare the system for dynamic theme adjustments.

Highlights

  • Cross-Platform Utilities: Introduced generic, cross-platform clipboard-copy and notify-local shell scripts to centralize clipboard operations and local notifications, moving away from macOS-specific osascript.
  • Automated Theme Switching: Implemented the darkman service for intelligent, automated dark/light theme switching, specifically configuring it to manage GTK themes and color schemes based on system preferences.
  • Notification System Integration: Updated existing notification configurations for Claude and Codex to leverage the new notify-local utility, ensuring consistent and platform-agnostic notification delivery.
  • Ghostty Custom Themes: Configured Ghostty to use newly added custom Dracula and Catppuccin Latte themes for dark and light modes, respectively, and integrated them into the NixOS configuration.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@mesa-dot-dev

mesa-dot-dev Bot commented Mar 25, 2026

Copy link
Copy Markdown

Mesa Description

TL;DR

Adds cross-platform notification and clipboard helpers, integrates them into claude, codex, and tmux, and enables automatic light/dark switching with darkman and custom ghostty themes. Scripts are now located in ~/.local/scripts and added to PATH for bash, fish, and zsh, with comprehensive tests for macOS and Linux.

What changed?

  • config/claude/notify.sh: Updated to use the generalized notify-local script for platform-agnostic notifications.
  • config/codex/config.toml: notify command updated to use "$HOME/.local/scripts/notify-local" for notifications.
  • config/codex/config.tpl.toml: Notification command updated to use "$HOME/.local/scripts/notify-local" for notifications.
  • config/ghostty/config: Changed Ghostty theme to conditional dark:Dracula Custom,light:Catppuccin Latte Custom and removed split-divider-color/unfocused-split-fill settings.
  • config/ghostty/default.nix: Added "Dracula Custom" and "Catppuccin Latte Custom" themes to NixOS configuration, symlinking theme files.
  • config/ghostty/themes/Catppuccin Latte Custom: New Ghostty theme file defining Catppuccin Latte color palette.
  • config/ghostty/themes/Dracula Custom: New Ghostty theme file defining a Dracula-like color scheme.
  • config/gtk/default.nix: Switched GTK theme preference from 'Adwaita-dark' to 'Adwaita', removing explicit dark theme settings.
  • home-manager/programs/tmux/tmux.conf: Delegated clipboard operations to ~/.local/scripts/clipboard-copy by updating @clipboard_cmd.
  • home-manager/services/darkman/default.nix: New Home Manager service for darkman on Linux, configuring geoclue and gtk-theme scripts with correct dconf paths.
  • home-manager/services/default.nix: Integrated the darkman service into Home Manager.
  • named-hosts/matic/default.nix: Added "darkman" to the org.freedesktop.impl.portal.Settings array.
  • home-manager/modules/default.nix: Added the local-scripts module to imported modules.
  • spec/clipboard_copy_spec.sh: New comprehensive shell spec tests for clipboard-copy.sh covering various backends and error handling.
  • spec/notify_local_spec.sh: New comprehensive test suite for notify-local.sh validating behavior across notification backends.
  • home-manager/modules/local-scripts/clipboard-copy.sh: New script for cross-platform clipboard copy supporting macOS, Wayland, and X11.
  • home-manager/modules/local-scripts/default.nix: New Home Manager module to configure and deploy clipboard-copy and notify-local to ~/.local/scripts/.
  • home-manager/modules/local-scripts/notify-local.sh: New bash script for cross-platform desktop notifications.
  • home-manager/programs/bash/default.nix: Included $HOME/.local/scripts in the PATH environment variable for bash.
  • home-manager/programs/fish/default.nix: Added .local/scripts to the fish shell's path.
  • home-manager/programs/zsh/default.nix: Added .local/scripts to the PATH environment variable for zsh.
  • spec/coverage_spec.sh: Extended coverage checks to include new darkman_spec.sh and the new clipboard-copy.sh and notify-local.sh scripts.
  • spec/notify_spec.sh: Updated test suite to replace osascript with notify-local in notification tests.
  • config/hyprland/hyprland.conf: Removed GTK_THEME environment variable setting for Adwaita:dark.
  • home-manager/services/darkman/dark-mode.sh: Updated dark-mode.sh script for dark mode settings.
  • home-manager/services/darkman/light-mode.sh: New script to configure GNOME desktop for light mode using dconf.
  • spec/darkman_spec.sh: New shell-based tests for darkman service's dark-mode.sh and light-mode.sh scripts.

Description generated by Mesa. Update settings

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 13 files

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new darkman service for automatic theme switching on Linux, refactors clipboard and notification handling into shared local scripts, and updates Ghostty terminal themes. Review comments highlight issues with line continuations in the darkman service scripts, which cause dconf commands to fail, and suggest an improvement for the notify-local script to utilize the sound parameter with terminal-notifier for better consistency.

Comment on lines +13 to +16
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/color-scheme "'prefer-dark'"
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/gtk-theme "'Adwaita-dark'"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The backslash \ for line continuation causes the two dconf commands to be concatenated into a single, invalid command. This will prevent the dark mode theme from being applied correctly. Each command should be on its own line without continuation.

        ${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/color-scheme "'prefer-dark'"
        ${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/gtk-theme "'Adwaita-dark'"

Comment on lines +21 to +24
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/color-scheme "'prefer-light'"
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/gtk-theme "'Adwaita'"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the darkModeScripts, the backslash \ for line continuation will cause these two dconf commands to be incorrectly concatenated, leading to a script failure. Please remove the line continuation to ensure each command runs separately.

        ${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/color-scheme "'prefer-light'"
        ${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/gtk-theme "'Adwaita'"

Comment on lines +82 to +83
terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
exit 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The notify-local script receives a sound parameter, but it's not being used when terminal-notifier is the backend. terminal-notifier supports sounds via the -sound flag. Using this would make notifications more consistent across different backends on macOS.

        if [[ -n "$sound" ]]; then
          terminal-notifier -title "$title" -message "$message" -sound "$sound" >/dev/null 2>&1 || true
        else
          terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
        fi
        exit 0

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces Darkman-based light/dark theme switching and refactors local clipboard/notification helpers, along with Ghostty theme configuration updates.

Changes:

  • Add a Home Manager services.darkman module and set the portal Settings backend to Darkman.
  • Add shared ~/.local/bin/clipboard-copy and ~/.local/bin/notify-local helpers and wire them into tmux/Codex/Claude.
  • Add custom Ghostty themes and switch Ghostty config to use dark/light theme mapping.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
named-hosts/matic/default.nix Prefer Darkman for the portal Settings implementation.
home-manager/services/default.nix Register new darkman Home Manager service module.
home-manager/services/darkman/default.nix Add Darkman service config and scripts to toggle GTK theme via dconf.
home-manager/programs/tmux/tmux.conf Switch tmux clipboard command to shared local helper script.
home-manager/modules/local-binaries/default.nix Add clipboard-copy and notify-local local executables.
config/gtk/default.nix Remove hard-coded dark preference and set base GTK theme to Adwaita.
config/ghostty/themes/Dracula Custom Add custom Dracula theme file for Ghostty.
config/ghostty/themes/Catppuccin Latte Custom Add custom Catppuccin Latte theme file for Ghostty.
config/ghostty/default.nix Install the custom Ghostty theme files into XDG config.
config/ghostty/config Use dark/light theme mapping and remove split styling now owned by themes.
config/codex/config.tpl.toml Route notifications through notify-local.
config/codex/config.toml Route notifications through notify-local.
config/claude/notify.sh Route notifications through notify-local when available.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +11 to +15
xdg.configFile."ghostty/themes/Dracula Custom" = {
source = ./themes + "/Dracula Custom";
};
xdg.configFile."ghostty/themes/Catppuccin Latte Custom" = {
source = ./themes + "/Catppuccin Latte Custom";

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using theme filenames with spaces and building the source path via string concatenation is fragile in Nix/Home Manager (spaces can cause awkward store name/path handling, and string-vs-path coercion can be surprising). Consider renaming the theme files to space-free names (e.g., Dracula-Custom, Catppuccin-Latte-Custom) and referencing them as proper Nix paths so source is unambiguously a path.

Suggested change
xdg.configFile."ghostty/themes/Dracula Custom" = {
source = ./themes + "/Dracula Custom";
};
xdg.configFile."ghostty/themes/Catppuccin Latte Custom" = {
source = ./themes + "/Catppuccin Latte Custom";
xdg.configFile."ghostty/themes/Dracula-Custom" = {
source = ./themes/Dracula-Custom;
};
xdg.configFile."ghostty/themes/Catppuccin-Latte-Custom" = {
source = ./themes/Catppuccin-Latte-Custom;

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +26
darkModeScripts = {
gtk-theme = ''
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/color-scheme "'prefer-dark'"
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/gtk-theme "'Adwaita-dark'"
'';
};
lightModeScripts = {
gtk-theme = ''
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/color-scheme "'prefer-light'"
${pkgs.dconf}/bin/dconf write \
/org/gnome/desktop/interface/gtk-theme "'Adwaita'"
'';
};

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These scripts only update GNOME dconf keys. However, Home Manager’s gtk.theme.name typically writes ~/.config/gtk-3.0/settings.ini / gtk-4.0/settings.ini (and similar), which many GTK apps read directly. That can lead to inconsistent theming where apps remain on the statically configured theme even after Darkman toggles dconf. To keep behavior consistent, either (a) have Darkman scripts also update the GTK settings.ini theme entries, or (b) avoid enforcing a static gtk.theme.name and rely on a single source of truth for theme switching.

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +25
if command -v xclip >/dev/null 2>&1; then
exec xclip -selection clipboard
fi

if command -v xsel >/dev/null 2>&1; then

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For X11 backends, xclip/xsel typically require a valid X display. As written, this will attempt to exec them even when $DISPLAY is unset (e.g., SSH, headless shells), which will fail noisily and prevent the script from reaching the final error message. Consider gating these branches on $DISPLAY being set (similar to the Wayland check).

Suggested change
if command -v xclip >/dev/null 2>&1; then
exec xclip -selection clipboard
fi
if command -v xsel >/dev/null 2>&1; then
if [[ -n "''${DISPLAY:-}" ]] && command -v xclip >/dev/null 2>&1; then
exec xclip -selection clipboard
fi
if [[ -n "''${DISPLAY:-}" ]] && command -v xsel >/dev/null 2>&1; then

Copilot uses AI. Check for mistakes.
Comment thread home-manager/programs/tmux/tmux.conf Outdated
# Clipboard
set -g set-clipboard on
set -g @clipboard_cmd "command -v pbcopy >/dev/null 2>&1 && pbcopy || { [ -n \"$WAYLAND_DISPLAY\" ] && wl-copy || xclip -selection clipboard; }"
set -g @clipboard_cmd "~/.local/bin/clipboard-copy"

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ~ in tmux option values can be brittle because expansion depends on how/where the value is later executed. Using an explicit $HOME/.local/bin/clipboard-copy (or an absolute path) is more robust across tmux/plugin execution contexts.

Suggested change
set -g @clipboard_cmd "~/.local/bin/clipboard-copy"
set -g @clipboard_cmd "$HOME/.local/bin/clipboard-copy"

Copilot uses AI. Check for mistakes.
inherit (pkgs) lib;
in
{
services.darkman = lib.mkIf pkgs.stdenv.isLinux {

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title suggests the scope is Darkman-focused, but the changes also introduce clipboard/notification helper binaries and Ghostty theme updates. Consider updating the PR title/description to reflect the broader scope or splitting the unrelated changes into separate PRs to make review and rollback safer.

Copilot uses AI. Check for mistakes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
home-manager/services/darkman/default.nix (1)

11-25: Consider deduplicating repeated dconf paths/theme literals.

Small constant extraction would reduce drift risk between dark/light scripts.

♻️ Optional refactor
 { pkgs, ... }:
 let
   inherit (pkgs) lib;
+  dconf = "${pkgs.dconf}/bin/dconf";
+  iface = "/org/gnome/desktop/interface";
+  darkTheme = "Adwaita-dark";
+  lightTheme = "Adwaita";
 in
 {
   services.darkman = lib.mkIf pkgs.stdenv.isLinux {
@@
     darkModeScripts = {
       gtk-theme = ''
-        ${pkgs.dconf}/bin/dconf write \
-          /org/gnome/desktop/interface/color-scheme "'prefer-dark'"
-        ${pkgs.dconf}/bin/dconf write \
-          /org/gnome/desktop/interface/gtk-theme "'Adwaita-dark'"
+        ${dconf} write \
+          ${iface}/color-scheme "'prefer-dark'"
+        ${dconf} write \
+          ${iface}/gtk-theme "'${darkTheme}'"
       '';
     };
     lightModeScripts = {
       gtk-theme = ''
-        ${pkgs.dconf}/bin/dconf write \
-          /org/gnome/desktop/interface/color-scheme "'prefer-light'"
-        ${pkgs.dconf}/bin/dconf write \
-          /org/gnome/desktop/interface/gtk-theme "'Adwaita'"
+        ${dconf} write \
+          ${iface}/color-scheme "'prefer-light'"
+        ${dconf} write \
+          ${iface}/gtk-theme "'${lightTheme}'"
       '';
     };
   };
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@home-manager/services/darkman/default.nix` around lines 11 - 25, Extract
repeated literals into small constants and reference them from the
darkModeScripts and lightModeScripts blocks: pull out the dconf binary path
(${pkgs.dconf}/bin/dconf), the interface keys
(/org/gnome/desktop/interface/color-scheme and
/org/gnome/desktop/interface/gtk-theme), and the theme names ("Adwaita" /
"Adwaita-dark") into local variables at the top of the file, then use those
variables inside the gtk-theme script strings in darkModeScripts and
lightModeScripts so the same identifiers (e.g., dconfBinary, colorSchemeKey,
gtkThemeKey, adwaitaTheme, adwaitaDarkTheme) are reused instead of duplicating
literals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/codex/config.toml`:
- Line 4: The hook currently calls "$HOME/.local/bin/notify-local" unguarded;
update the command string so the notifier is only invoked if present (e.g., test
-x "$HOME/.local/bin/notify-local" or command -v notify-local) before running
the notify step that uses JSON, LAST_MESSAGE and notify-local, otherwise skip
notification to avoid failing the hook when the binary is missing.

In `@home-manager/modules/local-binaries/default.nix`:
- Around line 62-84: The notifier blocks (commands osascript, notify-send,
terminal-notifier called in the script around the escape_applescript usage)
currently use "|| true" and then unconditionally exit, which masks failures and
prevents fallbacks; change each block to run the notifier command without
forcing success, capture its exit status, and only run exit 0 when the command
succeeded (e.g., test the command's return code or use && exit 0 after the
notifier invocation) so that if osascript/notify-send/terminal-notifier exists
but fails, the script will continue to try the next backend instead of silently
stopping.

---

Nitpick comments:
In `@home-manager/services/darkman/default.nix`:
- Around line 11-25: Extract repeated literals into small constants and
reference them from the darkModeScripts and lightModeScripts blocks: pull out
the dconf binary path (${pkgs.dconf}/bin/dconf), the interface keys
(/org/gnome/desktop/interface/color-scheme and
/org/gnome/desktop/interface/gtk-theme), and the theme names ("Adwaita" /
"Adwaita-dark") into local variables at the top of the file, then use those
variables inside the gtk-theme script strings in darkModeScripts and
lightModeScripts so the same identifiers (e.g., dconfBinary, colorSchemeKey,
gtkThemeKey, adwaitaTheme, adwaitaDarkTheme) are reused instead of duplicating
literals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a7bf1185-19ed-42cf-9942-d9676cd3716e

📥 Commits

Reviewing files that changed from the base of the PR and between 729ddf4 and a3e5ec6.

📒 Files selected for processing (13)
  • config/claude/notify.sh
  • config/codex/config.toml
  • config/codex/config.tpl.toml
  • config/ghostty/config
  • config/ghostty/default.nix
  • config/ghostty/themes/Catppuccin Latte Custom
  • config/ghostty/themes/Dracula Custom
  • config/gtk/default.nix
  • home-manager/modules/local-binaries/default.nix
  • home-manager/programs/tmux/tmux.conf
  • home-manager/services/darkman/default.nix
  • home-manager/services/default.nix
  • named-hosts/matic/default.nix

Comment thread config/codex/config.toml Outdated
Comment on lines +62 to +84
if command -v osascript >/dev/null 2>&1; then
escaped_title="$(escape_applescript "$title")"
escaped_message="$(escape_applescript "$message")"

if [[ -n "$sound" ]]; then
escaped_sound="$(escape_applescript "$sound")"
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
else
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true
fi

exit 0
fi

if command -v notify-send >/dev/null 2>&1; then
notify-send "$title" "$message" >/dev/null 2>&1 || true
exit 0
fi

if command -v terminal-notifier >/dev/null 2>&1; then
terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
exit 0
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find the file
find . -name "default.nix" -path "*/local-binaries/*" | head -20

Repository: shunkakinoki/dotfiles

Length of output: 114


🏁 Script executed:

# Check if the file exists and read the relevant lines
if [ -f "home-manager/modules/local-binaries/default.nix" ]; then
  wc -l "home-manager/modules/local-binaries/default.nix"
  echo "=== Lines 62-84 ==="
  sed -n '62,84p' "home-manager/modules/local-binaries/default.nix" | cat -n
fi

Repository: shunkakinoki/dotfiles

Length of output: 1190


🏁 Script executed:

# Get more context to understand the full function
sed -n '50,90p' "home-manager/modules/local-binaries/default.nix" | cat -n

Repository: shunkakinoki/dotfiles

Length of output: 1557


Prevent silent notification failures by only exiting when notifier commands succeed.

Currently, || true masks command failures on lines 68, 70, 77, and 82, but each conditional block still unconditionally exits (lines 73, 78, 83), preventing fallback to the next backend when a notifier fails. This can silently drop notifications even when alternative backends are available.

🔧 Suggested fix
       if command -v osascript >/dev/null 2>&1; then
         escaped_title="$(escape_applescript "$title")"
         escaped_message="$(escape_applescript "$message")"

         if [[ -n "$sound" ]]; then
           escaped_sound="$(escape_applescript "$sound")"
-          osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
+          if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1; then
+            exit 0
+          fi
         else
-          osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true
+          if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1; then
+            exit 0
+          fi
         fi
-
-        exit 0
       fi

       if command -v notify-send >/dev/null 2>&1; then
-        notify-send "$title" "$message" >/dev/null 2>&1 || true
-        exit 0
+        if notify-send "$title" "$message" >/dev/null 2>&1; then
+          exit 0
+        fi
       fi

       if command -v terminal-notifier >/dev/null 2>&1; then
-        terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
-        exit 0
+        if terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1; then
+          exit 0
+        fi
       fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if command -v osascript >/dev/null 2>&1; then
escaped_title="$(escape_applescript "$title")"
escaped_message="$(escape_applescript "$message")"
if [[ -n "$sound" ]]; then
escaped_sound="$(escape_applescript "$sound")"
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
else
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true
fi
exit 0
fi
if command -v notify-send >/dev/null 2>&1; then
notify-send "$title" "$message" >/dev/null 2>&1 || true
exit 0
fi
if command -v terminal-notifier >/dev/null 2>&1; then
terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
exit 0
fi
if command -v osascript >/dev/null 2>&1; then
escaped_title="$(escape_applescript "$title")"
escaped_message="$(escape_applescript "$message")"
if [[ -n "$sound" ]]; then
escaped_sound="$(escape_applescript "$sound")"
if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1; then
exit 0
fi
else
if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1; then
exit 0
fi
fi
fi
if command -v notify-send >/dev/null 2>&1; then
if notify-send "$title" "$message" >/dev/null 2>&1; then
exit 0
fi
fi
if command -v terminal-notifier >/dev/null 2>&1; then
if terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1; then
exit 0
fi
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@home-manager/modules/local-binaries/default.nix` around lines 62 - 84, The
notifier blocks (commands osascript, notify-send, terminal-notifier called in
the script around the escape_applescript usage) currently use "|| true" and then
unconditionally exit, which masks failures and prevents fallbacks; change each
block to run the notifier command without forcing success, capture its exit
status, and only run exit 0 when the command succeeded (e.g., test the command's
return code or use && exit 0 after the notifier invocation) so that if
osascript/notify-send/terminal-notifier exists but fails, the script will
continue to try the next backend instead of silently stopping.

Move clipboard-copy and notify-local bash scripts from inline nix text
blocks to standalone .sh files with a dedicated scripts module. Add
shellspec tests for both scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 0876af77c12f

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="spec/clipboard_copy_spec.sh">

<violation number="1" location="spec/clipboard_copy_spec.sh:19">
P2: These backend-selection tests only check exit status and never assert which clipboard command was invoked, so they can pass without validating the intended code path.</violation>

<violation number="2" location="spec/clipboard_copy_spec.sh:80">
P2: The no-backend test leaks an entire system bin directory into PATH, so clipboard backends may still be discoverable and make this test flaky/non-deterministic.</violation>
</file>

<file name="spec/notify_local_spec.sh">

<violation number="1" location="spec/notify_local_spec.sh:56">
P2: The terminal-notifier test setup only hides other backends when `osascript` exists, so on Linux it can accidentally use system `notify-send` and not actually test the intended branch.</violation>
</file>

<file name="home-manager/modules/scripts/notify-local.sh">

<violation number="1" location="home-manager/modules/scripts/notify-local.sh:34">
P2: The osascript path always exits even on failure, so fallback notifiers are never attempted when osascript is present but unusable.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@@ -0,0 +1,97 @@
#!/usr/bin/env bash

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: These backend-selection tests only check exit status and never assert which clipboard command was invoked, so they can pass without validating the intended code path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At spec/clipboard_copy_spec.sh, line 19:

<comment>These backend-selection tests only check exit status and never assert which clipboard command was invoked, so they can pass without validating the intended code path.</comment>

<file context>
@@ -0,0 +1,97 @@
+
+It 'uses pbcopy'
+When run bash "$SCRIPT" </dev/null
+The status should be success
+End
+End
</file context>
Fix with Cubic

# Keep bash on PATH but nothing else
local bash_dir
bash_dir="$(dirname "$(command -v bash)")"
export PATH="$MOCK_BIN:$bash_dir"

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The no-backend test leaks an entire system bin directory into PATH, so clipboard backends may still be discoverable and make this test flaky/non-deterministic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At spec/clipboard_copy_spec.sh, line 80:

<comment>The no-backend test leaks an entire system bin directory into PATH, so clipboard backends may still be discoverable and make this test flaky/non-deterministic.</comment>

<file context>
@@ -0,0 +1,97 @@
+  # Keep bash on PATH but nothing else
+  local bash_dir
+  bash_dir="$(dirname "$(command -v bash)")"
+  export PATH="$MOCK_BIN:$bash_dir"
+  export MOCK_BIN MOCK_ORIGINAL_PATH
+}
</file context>
Fix with Cubic

Comment thread spec/notify_local_spec.sh
setup() {
mock_bin_setup notify-send
# Hide osascript so notify-send path is taken
if command -v osascript >/dev/null 2>&1; then

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The terminal-notifier test setup only hides other backends when osascript exists, so on Linux it can accidentally use system notify-send and not actually test the intended branch.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At spec/notify_local_spec.sh, line 56:

<comment>The terminal-notifier test setup only hides other backends when `osascript` exists, so on Linux it can accidentally use system `notify-send` and not actually test the intended branch.</comment>

<file context>
@@ -0,0 +1,128 @@
+setup() {
+  mock_bin_setup notify-send
+  # Hide osascript so notify-send path is taken
+  if command -v osascript >/dev/null 2>&1; then
+    local bash_dir cat_dir printf_dir
+    bash_dir="$(dirname "$(command -v bash)")"
</file context>
Fix with Cubic

escaped_sound="$(escape_applescript "$sound")"
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
else
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The osascript path always exits even on failure, so fallback notifiers are never attempted when osascript is present but unusable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/modules/scripts/notify-local.sh, line 34:

<comment>The osascript path always exits even on failure, so fallback notifiers are never attempted when osascript is present but unusable.</comment>

<file context>
@@ -0,0 +1,50 @@
+    escaped_sound="$(escape_applescript "$sound")"
+    osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
+  else
+    osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true
+  fi
+
</file context>
Fix with Cubic

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@home-manager/modules/scripts/notify-local.sh`:
- Around line 26-48: The fallback logic currently suppresses failures with "||
true" and then unconditionally exits, so if
osascript/notify-send/terminal-notifier exists but fails the script won't try
the next backend; change each backend block (the osascript block that uses
escaped_title/escaped_message/escaped_sound, the notify-send invocation, and the
terminal-notifier invocation) to run the notification command without "|| true"
and only exit 0 when that command returns success (e.g. command && exit 0 or
capture the exit status and conditionally exit), so a runtime failure will fall
through to the next backend.

In `@spec/clipboard_copy_spec.sh`:
- Around line 23-71: The tests for "when wl-copy is available", "when xclip is
available", and "when xsel is available" are non-deterministic because other
higher-priority backends on PATH can satisfy the run; update each setup/cleanup
pair (the setup/cleanup functions used by Describe blocks and the
mock_bin_setup/mock_bin_cleanup helpers) to isolate PATH so only the test's
mocked binary is visible (e.g., create a temp mock bin dir in mock_bin_setup,
export PATH to that dir only during the test, and restore PATH in
mock_bin_cleanup), and apply the same PATH-isolation pattern used for xclip to
the wl-copy and xsel tests and ensure WAYLAND_DISPLAY is set/unset only where
intended.

In `@spec/notify_local_spec.sh`:
- Around line 79-103: The test setup() leaves host notify-send visible so the
script may choose notify-send instead of terminal-notifier; update setup() in
spec/notify_local_spec.sh to ensure notify-send (and osascript) are not on PATH
by either adding mock_bin_setup notify-send (so a dummy is used) or by removing
the directory containing notify-send from PATH (e.g., capture "$(dirname
"$(command -v notify-send)")" and exclude it when exporting PATH), and keep the
existing logic that hides osascript by rebuilding PATH to include only
"$MOCK_BIN" plus required system dirs; also ensure mock_bin_cleanup is still
called in cleanup().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e353040b-04f6-46fd-8e45-a85ec0ddb47d

📥 Commits

Reviewing files that changed from the base of the PR and between a3e5ec6 and 77b7f04.

📒 Files selected for processing (6)
  • home-manager/modules/default.nix
  • home-manager/modules/scripts/clipboard-copy.sh
  • home-manager/modules/scripts/default.nix
  • home-manager/modules/scripts/notify-local.sh
  • spec/clipboard_copy_spec.sh
  • spec/notify_local_spec.sh
✅ Files skipped from review due to trivial changes (3)
  • home-manager/modules/default.nix
  • home-manager/modules/scripts/default.nix
  • home-manager/modules/scripts/clipboard-copy.sh

Comment on lines +26 to +48
if command -v osascript >/dev/null 2>&1; then
escaped_title="$(escape_applescript "$title")"
escaped_message="$(escape_applescript "$message")"

if [[ -n "$sound" ]]; then
escaped_sound="$(escape_applescript "$sound")"
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
else
osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true
fi

exit 0
fi

if command -v notify-send >/dev/null 2>&1; then
notify-send "$title" "$message" >/dev/null 2>&1 || true
exit 0
fi

if command -v terminal-notifier >/dev/null 2>&1; then
terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
exit 0
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fallback chain exits even when the chosen backend fails.

Line 32/34/41/46 suppress errors with || true, then Line 37/42/47 unconditionally exits. If osascript or notify-send exists but fails at runtime, the script won’t try the next backend.

Suggested fix
 if command -v osascript >/dev/null 2>&1; then
   escaped_title="$(escape_applescript "$title")"
   escaped_message="$(escape_applescript "$message")"

   if [[ -n "$sound" ]]; then
     escaped_sound="$(escape_applescript "$sound")"
-    osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
+    if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1; then
+      exit 0
+    fi
   else
-    osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true
+    if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1; then
+      exit 0
+    fi
   fi
-
-  exit 0
 fi

 if command -v notify-send >/dev/null 2>&1; then
-  notify-send "$title" "$message" >/dev/null 2>&1 || true
-  exit 0
+  if notify-send "$title" "$message" >/dev/null 2>&1; then
+    exit 0
+  fi
 fi

 if command -v terminal-notifier >/dev/null 2>&1; then
-  terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
-  exit 0
+  terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
 fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@home-manager/modules/scripts/notify-local.sh` around lines 26 - 48, The
fallback logic currently suppresses failures with "|| true" and then
unconditionally exits, so if osascript/notify-send/terminal-notifier exists but
fails the script won't try the next backend; change each backend block (the
osascript block that uses escaped_title/escaped_message/escaped_sound, the
notify-send invocation, and the terminal-notifier invocation) to run the
notification command without "|| true" and only exit 0 when that command returns
success (e.g. command && exit 0 or capture the exit status and conditionally
exit), so a runtime failure will fall through to the next backend.

Comment on lines +23 to +71
Describe 'when wl-copy is available on Wayland'
setup() {
mock_bin_setup wl-copy
export WAYLAND_DISPLAY=wayland-0
}
cleanup() {
mock_bin_cleanup
unset WAYLAND_DISPLAY
}
Before 'setup'
After 'cleanup'

It 'uses wl-copy'
When run bash "$SCRIPT" </dev/null
The status should be success
End
End

Describe 'when xclip is available'
setup() {
mock_bin_setup xclip
}
cleanup() {
mock_bin_cleanup
}
Before 'setup'
After 'cleanup'

It 'uses xclip'
When run bash "$SCRIPT" </dev/null
The status should be success
End
End

Describe 'when xsel is available'
setup() {
mock_bin_setup xsel
}
cleanup() {
mock_bin_cleanup
}
Before 'setup'
After 'cleanup'

It 'uses xsel'
When run bash "$SCRIPT" </dev/null
The status should be success
End
End

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Backend-selection tests are currently non-deterministic.

At Line 23, Line 41, and Line 57 blocks, the tests only assert success, so a higher-priority backend on PATH can satisfy the run and still pass. That means these cases may not actually validate wl-copy/xclip/xsel selection.

Suggested hardening
 It 'uses xclip'
-When run bash "$SCRIPT" </dev/null
+When run bash -c 'bash '"$SCRIPT"' </dev/null; cat "$MOCK_LOG"'
 The status should be success
+The output should include 'xclip'
 End

Apply the same pattern to wl-copy and xsel, and isolate PATH similarly where needed so earlier backends cannot be chosen.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/clipboard_copy_spec.sh` around lines 23 - 71, The tests for "when
wl-copy is available", "when xclip is available", and "when xsel is available"
are non-deterministic because other higher-priority backends on PATH can satisfy
the run; update each setup/cleanup pair (the setup/cleanup functions used by
Describe blocks and the mock_bin_setup/mock_bin_cleanup helpers) to isolate PATH
so only the test's mocked binary is visible (e.g., create a temp mock bin dir in
mock_bin_setup, export PATH to that dir only during the test, and restore PATH
in mock_bin_cleanup), and apply the same PATH-isolation pattern used for xclip
to the wl-copy and xsel tests and ensure WAYLAND_DISPLAY is set/unset only where
intended.

Comment thread spec/notify_local_spec.sh
Comment on lines +79 to +103
Describe 'with terminal-notifier available (no osascript or notify-send)'
setup() {
mock_bin_setup terminal-notifier
# Hide osascript so terminal-notifier path is taken
if command -v osascript >/dev/null 2>&1; then
local bash_dir cat_dir printf_dir
bash_dir="$(dirname "$(command -v bash)")"
cat_dir="$(dirname "$(command -v cat)")"
printf_dir="$(dirname "$(command -v printf)")"
export PATH="$MOCK_BIN:$bash_dir:$cat_dir:$printf_dir"
fi
}
cleanup() {
mock_bin_cleanup
}
Before 'setup'
After 'cleanup'

It 'uses terminal-notifier'
When run bash -c 'bash '"$SCRIPT"' "Title" "Message"; cat "$MOCK_LOG"'
The status should be success
The output should include 'terminal-notifier'
The output should include 'Title'
The output should include 'Message'
End

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

terminal-notifier scenario can be bypassed by host notify-send.

In this setup, notify-send is not isolated out of PATH, so the script may take the notify-send branch instead of terminal-notifier depending on runner environment.

Suggested fix
 Describe 'with terminal-notifier available (no osascript or notify-send)'
 setup() {
   mock_bin_setup terminal-notifier
-  # Hide osascript so terminal-notifier path is taken
-  if command -v osascript >/dev/null 2>&1; then
-    local bash_dir cat_dir printf_dir
-    bash_dir="$(dirname "$(command -v bash)")"
-    cat_dir="$(dirname "$(command -v cat)")"
-    printf_dir="$(dirname "$(command -v printf)")"
-    export PATH="$MOCK_BIN:$bash_dir:$cat_dir:$printf_dir"
-  fi
+  # Isolate PATH so neither osascript nor notify-send can be discovered
+  local bash_dir cat_dir printf_dir
+  bash_dir="$(dirname "$(command -v bash)")"
+  cat_dir="$(dirname "$(command -v cat)")"
+  printf_dir="$(dirname "$(command -v printf)")"
+  export PATH="$MOCK_BIN:$bash_dir:$cat_dir:$printf_dir"
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Describe 'with terminal-notifier available (no osascript or notify-send)'
setup() {
mock_bin_setup terminal-notifier
# Hide osascript so terminal-notifier path is taken
if command -v osascript >/dev/null 2>&1; then
local bash_dir cat_dir printf_dir
bash_dir="$(dirname "$(command -v bash)")"
cat_dir="$(dirname "$(command -v cat)")"
printf_dir="$(dirname "$(command -v printf)")"
export PATH="$MOCK_BIN:$bash_dir:$cat_dir:$printf_dir"
fi
}
cleanup() {
mock_bin_cleanup
}
Before 'setup'
After 'cleanup'
It 'uses terminal-notifier'
When run bash -c 'bash '"$SCRIPT"' "Title" "Message"; cat "$MOCK_LOG"'
The status should be success
The output should include 'terminal-notifier'
The output should include 'Title'
The output should include 'Message'
End
Describe 'with terminal-notifier available (no osascript or notify-send)'
setup() {
mock_bin_setup terminal-notifier
# Isolate PATH so neither osascript nor notify-send can be discovered
local bash_dir cat_dir printf_dir
bash_dir="$(dirname "$(command -v bash)")"
cat_dir="$(dirname "$(command -v cat)")"
printf_dir="$(dirname "$(command -v printf)")"
export PATH="$MOCK_BIN:$bash_dir:$cat_dir:$printf_dir"
}
cleanup() {
mock_bin_cleanup
}
Before 'setup'
After 'cleanup'
It 'uses terminal-notifier'
When run bash -c 'bash '"$SCRIPT"' "Title" "Message"; cat "$MOCK_LOG"'
The status should be success
The output should include 'terminal-notifier'
The output should include 'Title'
The output should include 'Message'
End
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/notify_local_spec.sh` around lines 79 - 103, The test setup() leaves
host notify-send visible so the script may choose notify-send instead of
terminal-notifier; update setup() in spec/notify_local_spec.sh to ensure
notify-send (and osascript) are not on PATH by either adding mock_bin_setup
notify-send (so a dummy is used) or by removing the directory containing
notify-send from PATH (e.g., capture "$(dirname "$(command -v notify-send)")"
and exclude it when exporting PATH), and keep the existing logic that hides
osascript by rebuilding PATH to include only "$MOCK_BIN" plus required system
dirs; also ensure mock_bin_cleanup is still called in cleanup().

shunkakinoki and others added 6 commits March 25, 2026 16:07
Update all references to clipboard-copy and notify-local to use
~/.local/scripts/ instead of ~/.local/bin/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 8075bc53fe6a
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 45f07761fccf
…otification scripts

Entire-Checkpoint: f65f116ce65c

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="spec/coverage_spec.sh">

<violation number="1" location="spec/coverage_spec.sh:232">
P2: The new local-scripts entries were added to `covered_scripts` without adding matching `has spec file for ...` assertions, weakening this test’s spec-file coverage guard.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread spec/coverage_spec.sh
GTK_THEME=Adwaita:dark in hyprland.conf was overriding the portal
color-scheme preference, keeping Electron apps (Slack, Chrome) stuck
in dark mode. Extracted darkman scripts to external files and added
spec coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="spec/darkman_spec.sh">

<violation number="1" location="spec/darkman_spec.sh:55">
P2: The light-theme assertion is too broad and can pass for `Adwaita-dark`; assert the exact light value instead.</violation>
</file>

<file name="home-manager/services/darkman/default.nix">

<violation number="1" location="home-manager/services/darkman/default.nix:12">
P2: The extraction to `builtins.readFile` dropped explicit `${pkgs.dconf}/bin/dconf` resolution, so these hooks now depend on `dconf` being present on PATH and may fail in sessions where it is not.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread spec/darkman_spec.sh

It 'sets gtk-theme to Adwaita'
When run bash -c "cat '$LIGHT_SCRIPT'"
The output should include "Adwaita"

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The light-theme assertion is too broad and can pass for Adwaita-dark; assert the exact light value instead.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At spec/darkman_spec.sh, line 55:

<comment>The light-theme assertion is too broad and can pass for `Adwaita-dark`; assert the exact light value instead.</comment>

<file context>
@@ -0,0 +1,64 @@
+
+It 'sets gtk-theme to Adwaita'
+When run bash -c "cat '$LIGHT_SCRIPT'"
+The output should include "Adwaita"
+End
+
</file context>
Fix with Cubic

Comment thread home-manager/services/darkman/default.nix Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
home-manager/modules/local-scripts/notify-local.sh (1)

26-48: ⚠️ Potential issue | 🟠 Major

Fallback chain still exits even when a backend fails.

On Line 37 / Line 42 / Line 47, the script exits after backend detection, not backend success. Runtime failures are swallowed and no fallback is attempted.

Proposed fix
 if command -v osascript >/dev/null 2>&1; then
   escaped_title="$(escape_applescript "$title")"
   escaped_message="$(escape_applescript "$message")"

   if [[ -n $sound ]]; then
     escaped_sound="$(escape_applescript "$sound")"
-    osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1 || true
+    if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\" sound name \"$escaped_sound\"" >/dev/null 2>&1; then
+      exit 0
+    fi
   else
-    osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1 || true
+    if osascript -e "display notification \"$escaped_message\" with title \"$escaped_title\"" >/dev/null 2>&1; then
+      exit 0
+    fi
   fi
-
-  exit 0
 fi

 if command -v notify-send >/dev/null 2>&1; then
-  notify-send "$title" "$message" >/dev/null 2>&1 || true
-  exit 0
+  if notify-send "$title" "$message" >/dev/null 2>&1; then
+    exit 0
+  fi
 fi

 if command -v terminal-notifier >/dev/null 2>&1; then
-  terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1 || true
-  exit 0
+  if terminal-notifier -title "$title" -message "$message" >/dev/null 2>&1; then
+    exit 0
+  fi
 fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@home-manager/modules/local-scripts/notify-local.sh` around lines 26 - 48, The
script currently exits after selecting a backend even if the notification
command fails, because each backend block ends with an unconditional exit and
uses "|| true" to swallow runtime failures; update each backend block (the
osascript display notification branch, the notify-send branch, and the
terminal-notifier branch) to attempt the notification, check its exit status,
and only exit 0 when the command actually succeeds—otherwise continue to the
next backend. Concretely: remove the "|| true" and the unconditional exit inside
each detected-backend block, run the notification (redirecting output as
needed), test the command's return code (e.g. if command succeeds then exit 0),
and only fall through to subsequent backends when the notification failed.
🧹 Nitpick comments (1)
spec/darkman_spec.sh (1)

53-56: Light-mode GTK theme assertion is too broad.

Current check can pass on non-exact values containing Adwaita. Prefer matching the quoted exact theme token.

Proposed test tightening
 It 'sets gtk-theme to Adwaita'
 When run bash -c "cat '$LIGHT_SCRIPT'"
-The output should include "Adwaita"
+The output should include "'Adwaita'"
 End
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/darkman_spec.sh` around lines 53 - 56, The test "It 'sets gtk-theme to
Adwaita'" in spec/darkman_spec.sh currently checks for a bare Adwaita token
which is too broad; update the assertion that runs bash -c "cat '$LIGHT_SCRIPT'"
to look for the exact quoted theme token (e.g. match '"Adwaita"' or use a regex
with word boundaries like \bAdwaita\b) so only an exact theme value passes;
modify the expectation line that currently uses The output should include
"Adwaita" to assert the exact quoted token instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@home-manager/modules/local-scripts/notify-local.sh`:
- Around line 26-48: The script currently exits after selecting a backend even
if the notification command fails, because each backend block ends with an
unconditional exit and uses "|| true" to swallow runtime failures; update each
backend block (the osascript display notification branch, the notify-send
branch, and the terminal-notifier branch) to attempt the notification, check its
exit status, and only exit 0 when the command actually succeeds—otherwise
continue to the next backend. Concretely: remove the "|| true" and the
unconditional exit inside each detected-backend block, run the notification
(redirecting output as needed), test the command's return code (e.g. if command
succeeds then exit 0), and only fall through to subsequent backends when the
notification failed.

---

Nitpick comments:
In `@spec/darkman_spec.sh`:
- Around line 53-56: The test "It 'sets gtk-theme to Adwaita'" in
spec/darkman_spec.sh currently checks for a bare Adwaita token which is too
broad; update the assertion that runs bash -c "cat '$LIGHT_SCRIPT'" to look for
the exact quoted theme token (e.g. match '"Adwaita"' or use a regex with word
boundaries like \bAdwaita\b) so only an exact theme value passes; modify the
expectation line that currently uses The output should include "Adwaita" to
assert the exact quoted token instead.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a35bfc8c-2364-446a-8fb2-9ca51bf1e684

📥 Commits

Reviewing files that changed from the base of the PR and between 77b7f04 and aedc536.

📒 Files selected for processing (20)
  • config/claude/notify.sh
  • config/codex/config.toml
  • config/codex/config.tpl.toml
  • config/hyprland/hyprland.conf
  • home-manager/modules/default.nix
  • home-manager/modules/local-scripts/clipboard-copy.sh
  • home-manager/modules/local-scripts/default.nix
  • home-manager/modules/local-scripts/notify-local.sh
  • home-manager/programs/bash/default.nix
  • home-manager/programs/fish/default.nix
  • home-manager/programs/tmux/tmux.conf
  • home-manager/programs/zsh/default.nix
  • home-manager/services/darkman/dark-mode.sh
  • home-manager/services/darkman/default.nix
  • home-manager/services/darkman/light-mode.sh
  • spec/clipboard_copy_spec.sh
  • spec/coverage_spec.sh
  • spec/darkman_spec.sh
  • spec/notify_local_spec.sh
  • spec/notify_spec.sh
💤 Files with no reviewable changes (1)
  • config/hyprland/hyprland.conf
✅ Files skipped from review due to trivial changes (7)
  • home-manager/programs/zsh/default.nix
  • config/codex/config.tpl.toml
  • home-manager/programs/bash/default.nix
  • home-manager/services/darkman/light-mode.sh
  • home-manager/services/darkman/dark-mode.sh
  • home-manager/modules/local-scripts/clipboard-copy.sh
  • home-manager/modules/local-scripts/default.nix
🚧 Files skipped from review as they are similar to previous changes (6)
  • config/codex/config.toml
  • home-manager/modules/default.nix
  • spec/clipboard_copy_spec.sh
  • spec/notify_local_spec.sh
  • home-manager/programs/tmux/tmux.conf
  • home-manager/services/darkman/default.nix

shunkakinoki and others added 2 commits March 25, 2026 16:44
The darkman mode scripts were failing with "dconf: command not found"
because builtins.readFile doesn't interpolate Nix store paths.
Use builtins.replaceStrings with @dconf@ placeholders matching the
existing pattern in config/ccs/default.nix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@shunkakinoki
shunkakinoki merged commit 10f7cb1 into main Mar 25, 2026
30 of 31 checks passed
@shunkakinoki
shunkakinoki deleted the dankman branch March 25, 2026 07:50
@coderabbitai coderabbitai Bot mentioned this pull request Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants