{ config , lib , pkgs , ... }: let cfg = config.services.kanata; driverPkg = pkgs.fetchurl { url = "https://github.com/pqrs-org/Karabiner-DriverKit-VirtualHIDDevice/releases/download/v6.0.0/Karabiner-DriverKit-VirtualHIDDevice-6.0.0.pkg"; sha256 = "sha256-S14c06v/L/PraLekzIroG6FQnV5dpx0cyJNb9ylB458="; }; configFile = lib.mkIf (cfg.config != "") "${pkgs.writeScript "kanata.kbd" ("\n" + cfg.config + "\n")}"; in { options.services.kanata = { enable = lib.mkEnableOption "kanata, a tool to improve keyboard comfort and usability with advanced customization"; package = lib.mkPackageOption pkgs "kanata" { example = [ "kanata-with-cmd" ]; extraDescription = '' ::: {.note} If {option}`danger-enable-cmd` is enabled in any of the keyboards, the `kanata-with-cmd` package should be used. ::: ''; }; errorLogFile = lib.mkOption { type = lib.types.path; default = "/Library/Logs/Kanata/kanata.err.log"; example = "/Users/jsmith/Library/Logs/kanata.err.log"; description = "Path to the Kanata error log file"; }; outLogFile = lib.mkOption { type = lib.types.path; default = "/Library/Logs/Kanata/kanata.out.log"; example = "/Users/jsmith/Library/Logs/kanata.out.log"; description = "Path to the Kanata stdout log file"; }; config = lib.mkOption { type = lib.types.str; default = ""; description = ""; }; }; config = lib.mkIf cfg.enable { environment.systemPackages = [ cfg.package ]; # Install the driver during activation system.activationScripts.preActivation.text = '' echo "Installing Karabiner DriverKit VirtualHIDDevice..." >&2 # Check if already installed by looking for the system extension if ! systemextensionsctl list 2>/dev/null | grep -q "org.pqrs.Karabiner-DriverKit-VirtualHIDDevice"; then echo "Installing driver package..." >&2 installer -pkg ${driverPkg} -target / # Give it a moment to install sleep 2 # Try to activate the system extension if [ -f "/Applications/.Karabiner-VirtualHIDDevice-Manager.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Manager" ]; then echo "Activating system extension..." >&2 /Applications/.Karabiner-VirtualHIDDevice-Manager.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Manager activate || { echo "System extension activation requires user approval in System Settings > Privacy & Security" >&2 } fi else echo "Karabiner DriverKit already installed" >&2 fi ''; # Cleanup when disabled system.activationScripts.postActivation.text = lib.mkIf (!cfg.enable) '' echo "Cleaning up Karabiner DriverKit..." >&2 # Stop and remove launchd services for service in org.nixos.karabiner-vhiddaemon org.nixos.karabiner-vhidmanager; do launchctl unload "/Library/LaunchDaemons/$service.plist" 2>/dev/null || true rm -f "/Library/LaunchDaemons/$service.plist" 2>/dev/null || true done # Remove the manager app copy rm -rf /Applications/.Nix-Karabiner-DriverKit/ 2>/dev/null || true # Note: We don't uninstall the system extension as that requires manual user action # and the extension can be shared with other apps echo "Note: Karabiner system extension remains installed (can be removed manually in System Settings)" >&2 ''; launchd.daemons.karabiner-vhiddaemon.serviceConfig = { Label = "org.nixos.karabiner-vhiddaemon"; ProgramArguments = [ "/Library/Application Support/org.pqrs/Karabiner-DriverKit-VirtualHIDDevice/Applications/Karabiner-VirtualHIDDevice-Daemon.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Daemon" ]; RunAtLoad = true; KeepAlive = true; }; launchd.daemons.karabiner-vhidmanager.serviceConfig = { Label = "org.nixos.karabiner-vhidmanager"; ProgramArguments = [ "/Applications/.Karabiner-VirtualHIDDevice-Manager.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Manager" "activate" ]; RunAtLoad = true; }; launchd.daemons.kanata.serviceConfig = { Label = "org.nixos.kanata"; ProgramArguments = [ "${lib.getExe cfg.package}" "--port" "10000" # "--debug" ] ++ lib.optionals (cfg.config != "") [ "-c" configFile ]; RunAtLoad = true; KeepAlive = true; StandardOutPath = cfg.outLogFile; StandardErrorPath = cfg.errorLogFile; }; }; meta.maintainers = [ ]; }