diff --git a/hosts/marr/default.nix b/hosts/marr/default.nix
index 4ebd685..892a5ba 100644
--- a/hosts/marr/default.nix
+++ b/hosts/marr/default.nix
@@ -40,6 +40,12 @@
         enable = true;
         tags = [ "client" ];
       };
+      udev = {
+        enable = true;
+        libvirtHotplug."archlinux" = [
+          "303a/1001/*" # Espressif JTG debug unit
+        ];
+      };
     };
   };
 
@@ -180,9 +186,7 @@
     brightnessctl
     pop-icon-theme
 
-    bottles
-    wine64
-    ghidra
+    kicad-small
   ];
 
   system.stateVersion = "24.11";
diff --git a/hosts/marr/home.nix b/hosts/marr/home.nix
index 549d428..61cf0ce 100644
--- a/hosts/marr/home.nix
+++ b/hosts/marr/home.nix
@@ -13,7 +13,7 @@
 
   home-manager.users.${username} = {
     imports = [
-      ../../home/themes/catppuccin.nix
+      ../../home/themes/vanilla.nix
       ../../home
     ];
 
diff --git a/options/services/default.nix b/options/services/default.nix
index 807556c..14a70f3 100644
--- a/options/services/default.nix
+++ b/options/services/default.nix
@@ -4,5 +4,6 @@
     ./tailscale.nix
     ./rsync-backup
     ./cliphist.nix
+    ./udev
   ];
 }
diff --git a/options/services/udev/default.nix b/options/services/udev/default.nix
new file mode 100644
index 0000000..978ed14
--- /dev/null
+++ b/options/services/udev/default.nix
@@ -0,0 +1,67 @@
+{
+  lib,
+  config,
+  pkgs,
+  ...
+}:
+let
+  inherit (lib)
+    mkIf
+    mkEnableOption
+    mkOption
+    concatMapStrings
+    attrsToList
+    ;
+  inherit (lib.types)
+    str
+    attrsOf
+    listOf
+    ;
+  inherit (lib.my) getExe;
+
+  cfg = config.modules.services.udev;
+
+  bindUsb = pkgs.writers.writeBashBin "mount-usb" {
+    makeWrapperArgs = [
+      "--prefix"
+      "PATH"
+      ":"
+      "${lib.makeBinPath [ pkgs.libvirt ]}"
+    ];
+  } ./hotplug.sh;
+
+  mkUdevHotplug = domain: product: ''
+    ENV{PRODUCT}=="${product}", \
+            SUBSYSTEMS=="usb", \
+            RUN+="${getExe bindUsb} ${domain}"
+  '';
+in
+{
+
+  options.modules.services.udev = {
+    enable = mkEnableOption "";
+    libvirtHotplug = mkOption {
+      default = [ ];
+      type = attrsOf (listOf str);
+      description = ''
+        The udev rules used to match USB devices, all normal udev patterns are usable.
+      '';
+      example = ''[ "303a/1001/*" ]'';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.udev = {
+      enable = true;
+      packages = [
+        (pkgs.writeTextFile {
+          name = "udev-vm-hotplug-rules";
+          text = concatMapStrings (
+            { name, value }: concatMapStrings (product: mkUdevHotplug name product) value
+          ) (attrsToList cfg.libvirtHotplug);
+          destination = "/etc/udev/rules.d/99-hotplug.rules";
+        })
+      ];
+    };
+  };
+}
diff --git a/options/services/udev/hotplug.sh b/options/services/udev/hotplug.sh
new file mode 100644
index 0000000..b88a9fd
--- /dev/null
+++ b/options/services/udev/hotplug.sh
@@ -0,0 +1,42 @@
+# Refer to https://github.com/olavmrk/usb-libvirt-hotplug/blob/master/usb-libvirt-hotplug.sh
+
+set -e
+exec > >(systemd-cat -t "$0") 2>&1
+
+PROG="$(basename "$0")"
+DOMAIN="$1"
+
+if [ -z "${DOMAIN}" ]; then
+    echo "Missing libvirt domain parameter for $PROG." >&2
+    exit 1
+fi
+
+if [ "$ACTION" == 'add' ]; then
+    COMMAND='attach-device'
+elif [ "$ACTION" == 'remove' ]; then
+    COMMAND='detach-device'
+else
+    echo "Invalid udev ACTION: $ACTION" >&2
+    exit 1
+fi
+
+if [ -z "$BUSNUM" ]; then
+    echo "Missing udev BUSNUM environment variable." >&2
+    exit 1
+fi
+
+if [ -z "$DEVNUM" ]; then
+    echo "Missing udev DEVNUM environment variable." >&2
+    exit 1
+fi
+
+BUSNUM=$((10#$BUSNUM))
+DEVNUM=$((10#$DEVNUM))
+
+virsh -c qemu:///system $COMMAND archlinux --live --file /dev/stdin <<END
+<hostdev mode="subsystem" type="usb">
+    <source>
+        <address bus="$BUSNUM" device="$DEVNUM"/>
+    </source>
+</hostdev>
+END
diff --git a/options/system/roles/desktop.nix b/options/system/roles/desktop.nix
index d4b3c30..cc33981 100644
--- a/options/system/roles/desktop.nix
+++ b/options/system/roles/desktop.nix
@@ -50,6 +50,7 @@ in
     environment.systemPackages = [
       cfg.terminal
       cfg.filemanager
+      pkgs.zotero
     ];
   };
 }