keyd: Layers, macros, and remaps, even on laptop keyboards


2025-10-23 // 347 words // ~2 minutes



Remapping my mechanical keyboard knob to more useful stuff. Also, I can use hjkl keys everywhere now!
Photo of my keyboard taken under pretty bad lighting.
Photo of my keyboard taken under pretty bad lighting.

I have a mechanical keyboard (blue switches) with a volume knob. These things have pretty satisfying tactile feedback which makes them fun to play with.

I felt that I wasn't using it enough, so I decided that once I get some free time, I'll find a way to remap it to something more useful than adjusting volume.

On one lazy day (ie, just before one of the uni exams), I decided to look more closely at the knob. Turns out, when it's rotated clockwise, it simulates pressing the Volume Up key, and vice versa counter-clockwise.

Now all I had to do was remap these keys to something more useful.

Since my keyboard doesn't support QMK or VIA, I had to find something that works on all keyboards.

That's when I stumbled on keyd. It's a wonderful little daemon that intercepts keypresses and lets you do things like remap buttons (CapsLk to Ctrl when held, Esc when tapped being a common one), create layers, and more.

It works by spinning up a daemon that reads from a config file, after which it happily does its thing in the background.

I mapped my volume knob to up/down arrow keys by default, and left/right arrow keys when shift is held.

I also created a global config that lets me use AltGr+h/j/k/l instead of arrow keys (on all keyboards, including my laptop's). I also use AltGr as my compose key, which I didn't want to break. Turns out, you can specify that you want to overload a key in the keyd config file. This makes it behave like normal AltGr when tapped, but changes to a special nav layer when held. This layer then lets me use my h/j/k/l keys for navigating around.

This is what my global config looks like:

[ids]
*

# AltGr will be RightAlt/Compose on press, nav layer on hold. 
altgr = overload(nav, rightalt)

[nav]
h = left
j = down
k = up
l = right

And this is what the config for my mechanical keyboard looks like:

[ids]
1a2c:7fff:3c9dd5ab

[main]
volumeup = down
volumedown = up

[shift]
volumeup = right
volumedown = left

[control]
volumeup = volumeup
volumedown = volumedown

[alt]
volumeup = brightnessup
volumedown = brightnessdown

Comments

Comment via