anchor.diff:  
     keyboard = {
       options = {
  -      device = mkOption {
  -        type = types.str;
  -        example = "/dev/input/by-id/usb-0000_0000-event-kbd";
  -        description = lib.mdDoc "Path to the keyboard device.";
  +      devices = mkOption {
  +        type = types.addCheck (types.listOf types.str)
  +          (devices: (length devices) > 0);
  +        example = [ "/dev/input/by-id/usb-0000_0000-event-kbd" ];
  +        # TODO replace note with tip, which has not been implemented yet in
  +        # nixos/lib/make-options-doc/mergeJSON.py
  +        description = mdDoc ''
  +          Paths to keyboard devices.
  +
  +          ::: {.note}
  +          To avoid unnecessary triggers of the service unit, unplug devices in
  +          the order of the list.
  +          :::
  +        '';
         };
         config = mkOption {
           type = types.lines;
  
positive.code: { config, lib, pkgs, ... }:
  
  with lib;
  
  
negative.code:     };
    };
  
    mkPathName = i: name: "${mkName name}-${toString i}";
  
    mkPath = name: n: i: device:
      nameValuePair (mkPathName i name) {
        description =
          "${toString (i+1)}/${toString n} kanata trigger for ${name}, watching ${device}";
        wantedBy = optional (i == 0) "multi-user.target";
        pathConfig = {
          PathExists = device;
          # (ab)use systemd.path to construct a trigger chain so that the
          # service unit is only started when all paths exist
          # however, manual of systemd.path says Unit's suffix is not ".path"
          Unit =
            if (i + 1) == n
            then "${mkName name}.service"
            else "${mkPathName (i + 1) name}.path";
        };
        unitConfig.StopPropagatedFrom = optional (i > 0) "${mkName name}.service";
      };
  
    mkPaths = name: keyboard:
      let
        n = length keyboard.devices;
      in
      imap0 (mkPath name n) keyboard.devices
    ;
  in
  {
    options.services.kanata = {
  