Makima is a daemon for Linux to remap keyboards, mice, controllers and tablets.\
It works on both Wayland and X11 as it relies on the evdev kernel interface.
KEY/BTN input events present inside /usr/include/linux/input-event-codes.h.ABS and REL events, like analog stick movements and mouse scroll wheels.Makima can be installed automatically or manually. It can also be installed from the AUR.
To install and run Makima automatically as a systemd service:
- Download the executable from the Releases page.
- Retrieve install.sh, makima.service and optionally 50-makima.rules from this repo and put them in the same folder as the executable.
- Make sure that install.sh is executable (chmod +x ./install.sh or right click > properties > execute as a program).
- Run sudo ./install.sh username where username is the name of the user you're installing it for.
- Skip the rest of the "Installation" and "Running Makima" paragraphs and go directly to "Configuration".
Arch users can instead install makima-bin from the AUR, then enable makima.service.
To install and run Makima manually, refer to the following sections.
rustup using your distro's package manager or refer to the official docs if your distro doesn't ship rustup.rustup default stable which will automatically install Cargo (Rust's package manager) and the Rust toolchain.git clone https://github.com/cyber-sushi/makima
cd makima
cargo build --release
Once Cargo is done compiling, you should find Makima's executable inside ~/makima/target/release/.
Make sure that the executable has permissions to run as a program with chmod +x makima or with Right Click > Properties > "allow executing as program" or something like that, depending on your file manager.
There are two recommended ways to execute Makima:
- Run Makima as a systemd service.\
Move the executable into /usr/bin/.\
Grab makima.service from this repo and edit the User= line with your username.\
Move the file into /etc/systemd/system, then run systemctl daemon-reload.\
After this, you can start and stop Makima with systemctl start/stop makima or you can enable/disable it on startup with systemctl enable/disable makima. If you change the config files and you want the changes to take place, restart Makima with systemctl restart makima.
[!NOTE] When running as a systemd service, Makima inherits your systemd user environment, not your shell environment (you can see it with
systemctl --user show-environment). If you need to pass env variables to it, do so by adding them to the unit file withEnvironment=VARIABLE=value.
sudo -E makima.\
Navigate into the directory of the executable and use sudo -E ./makima.\
Alternatively, add Makima to a directory that's in PATH, possibly /usr/bin or ~/.local/bin and simply use sudo -E makima from anywhere.[!NOTE] The
-Eargument is necessary because it allows Makima to inherit your user environment instead of the root environment when running withsudo. You can also add the-bargument (sudo -Eb makima) to detach if from the terminal and make it run in the background.
You can find a bunch of example config files on this repo, either pick one of them or create your own from scratch.\
Makima's config directory defaults to $HOME/.config/makima but can be changed through the MAKIMA_CONFIG environment variable (if you run Makima as a system service, add it directly to the systemd unit).\
Each time you make changes to the config file, Makima must be restarted with systemctl restart makima.
To associate a config file to an input device, the file name should be identical to that of the device, plus .toml at the end. If your device's name includes a /, just omit it.
All config files will be parsed automatically when makima is launched.\
Files that don't end with .toml and files that start with . (dotfiles) won't be parsed, so you can add a dot at the beginning of the filename to mask them from Makima.
[!TIP] Example: you run
evtestand see that your Dualshock 4 controller is namedSony Interactive Entertainment Wireless Controller. All you have to do is rename your config file toSony Interactive Entertainment Wireless Controller.toml.
To apply a config file only to a specific application, just put ::<window_class> at the end of their filename, before .toml.
[!TIP] Example: you want your DS4 controller to have a specific set of keybindings for Firefox, name that file
Sony Interactive Entertainment Wireless Controller::firefox.toml.\ To retrieve the window class of a specific application, refer to your compositor's documentation, e.g. on Hyprland typehyprctl clientsin your terminal while that application is open.[!IMPORTANT] App-specific bindings are currently only supported on Hyprland, Sway, Niri, Plasma Wayland and all X11 sessions.\ Some applications, like Flatpaks for example, will have names like
org.mozilla.firefox.\ On Wayland, make sure that theXDG_CURRENT_DESKTOPenvironment variable is set, othewise Makima won't be able to use application-specific bindings.On Plasma Wayland, Makima uses
kdotool(Github repo or AUR package) to retrieve the active window instead of doing so internally, which means that you also need that installed. Sorry about this, but I didn't want to hardcode JavaScript snippets inside of Makima just to communicate with KWin.[!WARNING] It's been reported that active window retrieval through
kdotoolon Plasma might introduce performance issues, if you experience problems, removekdotool's executable fromPATHuntil I figure out how a solution.
To declare multiple layouts, similarly to app-specific bindings, put ::<int> at the end of a config file, where int is an integer value between 0 and 3, representing the layout number. If not specified, Makima will assume 0.\
When pressing the key configured in the settings through the LAYOUT_SWITCHER parameter, Makima will automatically cycle through the available layouts. If a layout isn't set, e.g. you're on 0 and you switch to the next layout, but number 1 isn't found, Makima will automatically skip to layout 2 and so on.\
You can also combine layouts and per application bindings by simply putting them both in the config file name.
[!TIP] Example: declare layout 2 in Nautilus by setting
Wireless Controller::2::org.gnome.Nautilus.tomlorWireless Controller::org.gnome.Nautilus::2.toml.[!NOTE] Keep in mind that while bindings and commands are read from each config file independently, settings are only read from the main config file, the one with no layout and associated application specified. If such file isn't present, Makima will use the default values.
The config file is divided into multiple sections:
- [remap], where you can rebind keys, buttons, combinations and some axis events to other keys, buttons and combinations.
- [commands], where you can rebind keys, buttons, combinations and some axis events to shell commands.
- [movements], where you can rebind keys, buttons, combinations and some axis events to cursor movements and scrolling.
- [settings], where you can configure a few settings.
# Remap a key to another key
KEY1 = ["KEY2"]
# Remap a key to a key sequence
KEY1 = ["KEY2", "KEY3", "KEY4"]
# Remap a key sequence to a single key
MODIFIER1-MODIFIER2-MODIFIER3-KEY1 = ["KEY1"]
# Remap a key sequence to another key sequence
MODIFIER1-MODIFIER2-MODIFIER3-KEY1 = ["KEY1", "KEY2", "KEY3"]
# Use a key to invoke a shell command
KEY1 = ["command1"]
# Use a key to invoke a list of shell commands
KEY1 = ["command1", "command2", "command3"]
# Use a key sequence to invoke a shell command
MODIFIER1-MODIFIER2-MODIFIER3-KEY1 = ["command1"]
# Use a key sequence to invoke a list of shell commands
MODIFIER1-MODIFIER2-MODIFIER3-KEY1 = ["command1", "command2", "command3"]
# Use a key to move the cursor in a direction
KEY1 = "CURSOR_UP/DOWN/LEFT/RIGHT"
# Use a key sequence to move the cursor in a direction
MODIFIER1-MODIFIER2-MODIFIER3-KEY1 = "CURSOR_UP/DOWN/LEFT/RIGHT"
# Use a key to scroll in a direction
KEY1 = "SCROLL_UP/DOWN/LEFT/RIGHT"
# Use a key sequence to scroll in a direction
MODIFIER1-MODIFIER2-MODIFIER3-KEY1 = "SCROLL_UP/DOWN/LEFT/RIGHT"
There are 8 available movements available:\
- CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT
- SCROLL_UP, SCROLL_DOWN, SCROLL_LEFT, SCROLL_RIGHT
[!NOTE] To make movements work, you also have to set a speed value using
CURSOR_SPEEDorSCROLL_SPEEDin the[settings]section.[!NOTE] It's preferable not to use CTRL and ALT as modifiers for scrolling because they'll get interpreted by the application as zoom in/out and forward/back instead of an actual scroll movement.
You can find the KEY names inside /usr/include/linux/input-event-codes.h, or launch evtest to see the events emitted by your devices.\
Remember that keys like Ctrl and Alt have names like KEY_LEFTCTRL, KEY_LEFTALT etc. Just using KEY_CTRL and KEY_ALT will throw a parsing error because the key code does not exist.
Axis events such as scroll wheels and analog stick movements are hardcoded, currently you can use the following:
- SCROLL_WHEEL_UP, SCROLL_WHEEL_DOWN - for a mouse's scroll wheel
- BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT - for a game controller's D-Pad
- ABS_Z, ABS_RZ - for a game controller's triggers, respectively left and right
- LSTICK_UP, LSTICK_DOWN, LSTICK_LEFT, LSTICK_RIGHT, RSTICK_UP, RSTICK_DOWN, RSTICK_LEFT, RSTICK_RIGHT - for a game controller's analog sticks
- ABS_WHEEL_CW, ABS_WHEEL_CCW - for a tablet's wheel, respectively clockwise and counterclockwise
Refer to the sample config files for more information.
You can use as many modifiers as you want when declaring a binding, but the last key has to be a non-modifier key.
Non-modifier keys (e.g. KEY_A) can be set in place of a modifier, automatically changing the behavior of that key: when used in combination with other keys, it will only act as a modifier, but when used alone, it will retain its default functionality, although the input event will be dispatched on key-up instead of key-down.
If you want a non-modifier key to act as a modifier without remapping it for that device (e.g. you need it as a modifier when used in combination with another device), you can add it to the CUSTOM_MODIFIERS setting. Refer to the [settings] section for more info.
Keep in mind that if you want to use modifiers across multiple devices (e.g. KEY_LEFTCTRL on your keyboard and BTN_RIGHT on your mouse), both devices will have to be read by Makima and thus both will need a config file, even if empty. Having a config file is just a way to tell Makima "Hey, read this device!".
When declaring a binding, you can put a dash (-) in front of it (e.g. -KEY_A = ["KEY_B"]) to tell Makima that it's not a standalone binding and it should instead be chained at the end of another sequence.\
Exam
$ claude mcp add makima \
-- python -m otcore.mcp_server <graph>