I wrote ev-cmd because I didn't have an easy way to bind commands to my Koolertron macropad.
Add this flake as an input to your NixOS configuration flake:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
ev-cmd = {
url = "github:danhab99/ev-cmd"; # Update with your GitHub path
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, ev-cmd, ... }: {
nixosConfigurations.yourhostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
{
environment.systemPackages = [
ev-cmd.packages.x86_64-linux.default
];
}
];
};
};
}Or use it directly with nix run:
nix run github:danhab99/ev-cmd -- --helpOr install it to your profile:
nix profile install github:danhab99/ev-cmdInstall from the AUR using
yay -S ev-cmd
Build using cargo build --release
ev-cmd listens to input events from a specified device (like a macropad or keyboard) and executes shell commands when keys are pressed.
ev-cmd --device-path /dev/input/by-id/YOUR_DEVICEOptions:
-d, --device-path <DEVICE_PATH> Path to the input device (required)
-c, --config-path <CONFIG_PATH> Path to config file (optional)
-h, --help Print help
ev-cmd uses a TOML configuration file that maps key codes to shell commands. The program searches for ev-cmd.toml in the following locations (in order):
- Path specified with
--config-path - Current working directory (
./ev-cmd.toml) - User config directory (
~/.config/ev-cmd.tomlon Linux) /etc/ev-cmd.toml
The config file maps evdev key codes to shell commands:
# Key code = "shell command"
30 = "notify-send 'Key A pressed'"
48 = "firefox"
46 = "alacritty"
32 = "rofi -show drun"To find the key codes for your device:
-
List available input devices:
ls -l /dev/input/by-id/
-
Run
ev-cmdwith an empty or minimal config to see key codes:ev-cmd --device-path /dev/input/by-id/YOUR_DEVICE
-
Press keys on your device - the program will output:
Caught keycode 30 Caught keycode 48 -
Use these key codes in your config file
See templates/ev-cmd.toml.koolertron-ae-smkd for a complete example mapping all keys on a Koolertron macropad.
Example config for common tasks:
# Row 1: Applications
30 = "firefox"
48 = "alacritty"
46 = "code"
32 = "nautilus"
# Row 2: Media controls
35 = "playerctl play-pause"
23 = "playerctl next"
36 = "playerctl previous"
37 = "pactl set-sink-volume @DEFAULT_SINK@ +5%"
# Row 3: System commands
38 = "systemctl suspend"
50 = "loginctl lock-session"
49 = "notify-send 'System Info' \"$(uname -a)\""
# Row 4: Custom scripts
25 = "/home/user/scripts/backup.sh"
16 = "rofi -show run"To run ev-cmd automatically on system start, create a systemd user service:
# ~/.config/systemd/user/ev-cmd.service
[Unit]
Description=Event Command Daemon
After=default.target
[Service]
Type=simple
ExecStart=/usr/bin/ev-cmd --device-path /dev/input/by-id/YOUR_DEVICE
Restart=on-failure
[Install]
WantedBy=default.targetEnable and start the service:
systemctl --user enable ev-cmd.service
systemctl --user start ev-cmd.service- Only one instance of
ev-cmdcan run at a time (enforced by PID lock) - Commands are executed in separate threads, so they don't block event processing
- Only key press events (state = 1) trigger commands; key releases are ignored
- Unmapped keys are silently ignored