Layered keyboard layout with KMonad on Linux (i3)
January 14, 2025This note documents how I use KMonad, a cross-platform, user-space keyboard remapping daemon written in Haskell, to implement a layered keymap on a Linux workstation. The configuration lives alongside my window manager setup in this i3 repository.
Compared to QMK/ZMK firmware, KMonad runs in user space on the host OS, which makes it easy to iterate on declarative layout definitions without flashing hardware. The mental model is similar to embedded keymaps: layers, tap-hold behaviors, and modifier chords, expressed as structured configuration rather than ad hoc desktop shortcuts.
KMonad configuration overview
KMonad exposes a layer-based model: the same physical key can emit different symbols depending on the active layer. I modeled the layout after the lily58 split keyboard and the Corne-style 3×5+1 patterns described here.
The stack has three layers:
-
Default QWERTY layer.
-
Lower layer: numerics and related symbols on the home row.
-
Raise layer: navigation-style bindings (e.g.,
h/j/k/las directional keys).
Space bar: tap versus hold (layer toggle)
In the QWERTY layer:
-
Tap: ordinary
Space. -
Hold (longer than ~150 ms): toggles into the Lower layer while held.
If the active layer is Raise or Lower:
-
Tap
Space: still emitsSpace. -
Hold
Space: returns to QWERTY (this path is rarely needed in practice).
Beyond toggle (layer active only while a key is held), KMonad also supports switch semantics (latch a layer until another switch fires). In this configuration:
-
F1switches between QWERTY and Lower. -
F2switches between QWERTY and Raise.
In day-to-day use, Lower is accessed primarily via the thumb toggle on Space; releasing the thumb drops back to QWERTY without an explicit layer exit.
I also map home-row modifiers using the same tap-hold pattern: short presses type letters; sustained presses register as Shift, Ctrl, Alt/Meta, or Super (Windows / OS key), which keeps hands on the home row during terminal and editor sessions.
Home row modifiers
Modifier placement on the home row follows this ordering:
-
Pinky:
Shift -
Ring:
Ctrl -
Middle:
Alt/Meta -
Index:
Super(Windows / OS key)
Tap produces the normal home-row letters; hold (>150 ms before release) registers the modifier for chorded shortcuts (for example Ctrl+T in Firefox or the terminal multiplexer).
Rationale: throughput in CLI-centric workflows
The design goal is to reduce context switching between typing, navigation, and modifier-heavy shortcuts—common when living in i3, Neovim, tmux, and browser-based tooling. Thumb-driven layer access mirrors how firmware splits offload numerics to a second plane; here the same idea is applied at the OS boundary.
In QWERTY, holding Space with the left thumb exposes the Lower layer so the right hand can type:
`!@#$%`
`12345`
`_-+[{`,
Releasing Space returns to QWERTY. Holding Space with the right thumb exposes Lower for the left hand:
`^&*()`
`67890`
`}],.=`,
Functionally, the thumb acts like a context switch for symbol planes—similar in spirit to holding Shift, but backed by explicit layers and deterministic timing thresholds rather than a single modifier bit.