$linuxjunkies
>

Custom Keybinds: Caps as Esc/Ctrl, Sticky Keys, Macros

Remap Caps Lock to Esc/Ctrl, set up hyperkeys, sticky keys, and macros using xkb, keyd, input-remapper, and kanata—covering X11 and Wayland.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • A running Linux desktop (X11 or Wayland) with sudo access
  • systemd-based init system
  • Basic familiarity with editing text files and running commands in a terminal
  • For keyd/kanata: kernel with uinput module available (standard on all major distros)

Keyboard remapping on Linux ranges from trivial (swapping two keys) to sophisticated (tap-vs-hold logic, layer switching, macros). This guide covers four tools—xkbcomp/xkb, keyd, input-remapper, and kanata—so you can pick the right level of complexity. All methods work on a modern systemd-based distro; Wayland compatibility is noted throughout.

Choosing the Right Tool

Before diving in, match your need to the tool:

  • xkb / xkbcompX11 only; great for simple remaps (Caps→Esc, swap Alt/Meta) without installing anything extra.
  • keydkernel-level daemon; works on X11, Wayland, and even TTY. Best for tap-vs-hold (Caps = Esc on tap, Ctrl on hold), layers, and hyperkey setups.
  • input-remapper — GUI-driven; handles mice and gamepads too; good for macros and sticky-key-style remaps. X11 and Wayland (partial, via uinput).
  • kanata — cross-platform Rust daemon; same uinput approach as keyd but with a richer configuration language borrowed from QMK firmware.

Method 1 — xkb (X11, No Extra Software)

XKB rules live in /usr/share/X11/xkb/. The fastest one-session remap uses setxkbmap or xkbcomp.

Caps Lock → Escape (one-liner)

setxkbmap -option caps:escape

To make it permanent, add the option to your X11 server config:

sudo mkdir -p /etc/X11/xorg.conf.d
sudo tee /etc/X11/xorg.conf.d/90-custom-kbd.conf <<'EOF'
Section "InputClass"
    Identifier "keyboard defaults"
    MatchIsKeyboard "on"
    Option "XkbOptions" "caps:escape"
EndSection
EOF

Caps Lock as both Escape and Ctrl (xkb option)

setxkbmap -option caps:escape_shifted_capslock

This uses the upstream caps:escape_shifted_capslock option: tap Caps = Escape, Shift+Caps = CapsLock. True tap-vs-hold (Caps = Ctrl when held) requires keyd or kanata—XKB alone cannot express timing.

Inspecting and patching with xkbcomp

# Dump the current keymap
xkbcomp $DISPLAY keymap.xkb
# Edit keymap.xkb, then reload it
xkbcomp keymap.xkb $DISPLAY

This is useful for one-off experiments. The file is plain text; look for the key <CAPS> stanza and change its symbols entry.

Method 2 — keyd (Kernel-Level, Wayland-Safe)

keyd intercepts events through /dev/input and re-emits them via uinput before any display server sees them. Install it from source or from your distro's repos:

# Debian/Ubuntu (not yet in main repos as of Ubuntu 24.04 — build from source)
git clone https://github.com/rvaiya/keyd
cd keyd && make && sudo make install
sudo systemctl enable --now keyd
# Fedora / RHEL 9+ (available in COPR)
sudo dnf copr enable alternateved/keyd
sudo dnf install keyd
sudo systemctl enable --now keyd
# Arch Linux
yay -S keyd   # or paru, or build from AUR manually
sudo systemctl enable --now keyd

Caps = Esc on tap, Ctrl on hold

Create /etc/keyd/default.conf:

sudo tee /etc/keyd/default.conf <<'EOF'
[ids]
*

[main]
capslock = overload(control, esc)
EOF
sudo keyd reload

overload(layer, key) means: activate layer while held, emit key on tap. This is the canonical "Caps as Esc/Ctrl" setup used by Vim and Emacs power users alike.

Hyperkey Setup (Caps → Meta+Ctrl+Alt+Shift)

A hyperkey gives you a dedicated modifier for app shortcuts that never conflict with anything else.

sudo tee /etc/keyd/default.conf <<'EOF'
[ids]
*

[main]
capslock = overload(hyper, esc)

[hyper:C-M-A-S]
EOF
sudo keyd reload

Now Caps+H, Caps+J, etc., are free real estate for your window manager or custom shortcuts. The layer hyper:C-M-A-S means every key inside it is automatically prefixed with Ctrl+Meta+Alt+Shift.

Sticky / One-Shot Keys

sudo tee -a /etc/keyd/default.conf <<'EOF'
# One-shot shift: tap left shift, then next key is shifted
leftshift = oneshot(shift)
EOF
sudo keyd reload

One-shot keys are useful for accessibility or reducing RSI. After the tap, the modifier fires once then releases automatically.

Method 3 — input-remapper (GUI, Macros)

input-remapper provides a GTK interface and handles complex macros (key sequences, delays, mouse buttons). It works on both X11 and Wayland via uinput.

# Debian/Ubuntu
sudo apt install input-remapper
sudo systemctl enable --now input-remapper
# Fedora
sudo dnf install input-remapper
sudo systemctl enable --now input-remapper
# Arch
yay -S input-remapper-git
sudo systemctl enable --now input-remapper

Launch the GUI:

input-remapper-gtk

Creating a Macro

In the GUI: select your keyboard device, click Add, press the key you want to remap (e.g., Caps Lock), then in the output field enter a macro. Macro syntax example — type a fixed string on one key:

# Macro syntax in the output field (not a shell command):
key(h).key(e).key(l).key(l).key(o)

For a real productivity macro like expanding a snippet, use key() chains or the type("text") helper. Click Save, then Apply. The preset auto-starts at login via the systemd service.

Method 4 — kanata (Advanced Tap/Hold, Layers)

kanata uses an S-expression config syntax similar to QMK. It runs as a user or system daemon and supports everything keyd does plus combo keys, sequences, and fine-grained timing.

# Download the pre-built binary (check GitHub for latest release)
curl -Lo kanata https://github.com/jtroo/kanata/releases/latest/download/kanata
chmod +x kanata
sudo mv kanata /usr/local/bin/

kanata needs uinput access. Add yourself to the input and uinput groups (or run as root for testing):

sudo usermod -aG input,uinput $USER
# Log out and back in, or:
newgrp input

Caps = Esc/Ctrl + a Macro Layer

mkdir -p ~/.config/kanata
tee ~/.config/kanata/kanata.kbd <<'EOF'
(defsrc
  caps
)

(deflayer base
  (tap-hold 200 200 esc lctl)
)
EOF

Test it interactively first:

sudo kanata --cfg ~/.config/kanata/kanata.kbd

Running kanata as a systemd User Service

mkdir -p ~/.config/systemd/user
tee ~/.config/systemd/user/kanata.service <<'EOF'
[Unit]
Description=kanata keyboard remapper
After=graphical-session.target

[Service]
ExecStart=/usr/local/bin/kanata --cfg %h/.config/kanata/kanata.kbd
Restart=on-failure

[Install]
WantedBy=default.target
EOF
systemctl --user enable --now kanata

Verifying Your Remaps

Use evtest (root required) to watch raw events, or xev on X11 to see what keysyms land in applications:

# X11 — watch keypresses in a window
xev | grep -A2 KeyPress

# Kernel level — works on Wayland and TTY
sudo evtest

evtest lists devices; pick your keyboard's number. Tap Caps Lock — you should see KEY_ESC or KEY_LEFTCTRL events from the virtual device, not KEY_CAPSLOCK.

Troubleshooting

  • keyd not remapping in Wayland: Confirm the service is running (systemctl status keyd) and that no other remapper (like input-remapper) is running simultaneously—they will conflict.
  • Caps Lock LED stays on: keyd suppresses the capslock event, so this is expected. You can use keyd -m to monitor what keyd is seeing.
  • kanata permission denied on /dev/uinput: Run ls -l /dev/uinput; if group is not uinput, create a udev rule: KERNEL=="uinput", GROUP="uinput", MODE="0660" in /etc/udev/rules.d/99-uinput.rules, then reload udev.
  • input-remapper not persisting across reboots: Make sure you clicked Save in the GUI and that the systemd service is enabled, not just started.
  • xkb options reset after suspend: Add the setxkbmap call to your display manager's session startup script or use the xorg.conf.d approach instead.
tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

Frequently asked questions

Will keyd or kanata work on a Wayland compositor like GNOME or KDE?
Yes. Both intercept events at the kernel uinput level, before any display server sees them. They work identically under X11, Wayland, and a bare TTY.
Can I use these remaps in a login screen (GDM, SDDM)?
keyd works at the system level and is active as soon as the service starts, so it covers login screens. XKB options only take effect after X starts. input-remapper and kanata user services start after login.
What is a hyperkey and why would I want one?
A hyperkey is a single key (usually Caps Lock) that acts as Ctrl+Alt+Meta+Shift when held. Because almost no application uses all four modifiers together, you get a clean namespace of shortcuts that never clash with system or app defaults.
Do tap-vs-hold remaps introduce typing lag?
They can if the hold timeout is too long. keyd and kanata both let you tune the tap timeout (typically 150–250 ms). Fast typists often set it to 175 ms. The key is also released on the next keypress, not just on timeout, which minimises perceived delay.
Can input-remapper remap mouse buttons as well as keyboard keys?
Yes, it is one of input-remapper's strengths over keyd. You can bind mouse buttons to key sequences, macros, or even other mouse buttons, and it handles gamepad axes too.

Related guides