In this article
- What does XMonad handle?
- Where is the file, and how does it begin?
- Tall and Full: What do the numbers mean?
- The important keybindings in my file
- What do the hooks do?
- Exercise: Change one border colour
- Returning to the previous configuration
- Local configuration and your next step
- Source code and documentation
Open a window, work beside it with a keypress and switch applications without reaching for the mouse: that is the starting point for XMonad. My small Debian X11 example puts the important pieces into a manageable xmonad.hs. You do not need to understand an entire Haskell project to read it.
We will read the file in sections and then change just one border colour. The exercise assumes a working XMonad session, the required Haskell libraries and access to the active configuration file. Installing the whole desktop is a separate step; Gruvnode describes my complete laptop setup.
What does XMonad handle?
XMonad is a window manager for X11. It controls window position, size and focus. A layout divides the screen automatically. A complete desktop also needs a terminal, application launcher, audio, networking and possibly a status bar.
Kitty, dmenu and feh fill some of those roles here. They are separate programs. A line launching Kitty does not install it. Many components that an integrated desktop supplies are chosen explicitly in this setup. For the Wayland approach, continue with the Sway introduction.
Where is the file, and how does it begin?
XMonad supports locations including ~/.config/xmonad/xmonad.hs, the older ~/.xmonad/xmonad.hs and explicitly configured directories. Check your existing setup first. The backup commands below use the usual XDG location; adapt both filenames if your active configuration is elsewhere.
import lines load functions from libraries. Below them, main puts the configuration together. My example builds on def, XMonad's default settings, and replaces individual fields:
{ terminal = "kitty"
, modMask = mod4Mask
, borderWidth = 2
, focusedBorderColor = "#89b4fa"
, normalBorderColor = "#1e1e2e"
, layoutHook = myLayout
, manageHook = myManageHook
, startupHook = myStartupHook
}
This is an excerpt from the existing def block, not a complete file. mod4Mask selects Super, usually the Windows key. The functions myLayout, myManageHook and myStartupHook are defined further down, keeping the different topics readable.
Tall and Full: What do the numbers mean?
The published file defines this sequence of layouts:
myLayout =
smartBorders
$ spacingWithEdge 6
$ Tall 1 (3 / 100) (1 / 2)
||| Full
Tall provides a master area and a stack for additional windows. The 1 selects one window in the master area. 3 / 100 is the width adjustment step; 1 / 2 is its initial screen share. ||| connects layouts you can cycle through.
spacingWithEdge 6 adds spacing, while smartBorders adjusts borders according to the situation. Full displays one window at a large size within the layout. An application's actual fullscreen request is also handled by fullscreen hooks; the two concepts are not always identical.
The important keybindings in my file
additionalKeysP adds or replaces keybindings. M means the selected modifier and S means Shift. These are the bindings actually present in the source:
| Keys | Action |
|---|---|
| Super + Enter | Launch Kitty |
| Super + D | Open dmenu |
| Super + J / K | Move focus between windows |
| Super + Shift + J / K | Swap window positions |
| Super + H / L | Shrink or expand the master area |
| Super + Space | Cycle to the next layout |
| Super + Q | Close the focused window |
| Super + Shift + R | Compile and restart after successful compilation |
Super + Q is explicitly assigned to closing a window here. Use the bindings in your own configuration rather than assuming that another tutorial's defaults apply. Super + Shift + Q exits the XMonad session; save open work first.
What do the hooks do?
layoutHook chooses window arrangement. manageHook handles new windows; my short version lets detected fullscreen windows float over the screen. startupHook runs startup actions. Here, spawnOnce sets a wallpaper using feh.
The wallpaper path must exist on your machine. The same applies to launched applications such as Chrome and to volume/brightness helpers. This file uses pamixer and brightnessctl. Gruvnode instead controls volume through wpctl.
ewmh and ewmhFullscreen improve cooperation with applications expecting the corresponding desktop and fullscreen information. The additional setWMName "LG3D" line is a personal compatibility setting. Its presence does not establish that it fixes any arbitrary Wine or Proton problem.
Exercise: Change one border colour
Back up the active file. This command uses the standard XDG location and preserves an existing backup destination as a numbered copy:
cp -a --backup=numbered ~/.config/xmonad/xmonad.hs ~/.config/xmonad/xmonad.hs.before-tutorial
Change only focusedBorderColor inside the existing block, for example from blue to green:
, focusedBorderColor = "#93dfc1"
Keep the comma and quotation marks. Check the configuration before restarting the running session:
xmonad --recompile
If compilation fails, read the reported line and correct it. Common causes include a missing comma, an unknown name or an unavailable library. Only after successful compilation, run:
xmonad --restart
Open two windows in the Tall layout and switch focus using Super + J or K. The visible border of the focused window should use the new colour. With one window or Full, smart borders may hide the border entirely.
Returning to the previous configuration
To undo only the exercise, restore the old colour value. Alternatively, copy back your saved file if doing so will not discard later edits:
cp -a ~/.config/xmonad/xmonad.hs.before-tutorial ~/.config/xmonad/xmonad.hs
Compile the restored configuration again:
xmonad --recompile
Restart after the check succeeds:
xmonad --restart
Start with one setting at a time. If colour, layouts, startup commands and libraries change together, identifying the source of an error becomes much harder.
Local configuration and your next step
Reading, editing and compiling this file requires no upload. Installing packages contacts repositories; browsers and other launched applications have their own data handling. Keybindings can contain personal paths, so review them before publishing your configuration.
This small file leaves out many everyday laptop components. The Gruvnode guide combines XMonad with Xmobar, Rofi, audio and networking and explains the installer for my current X1 Carbon.
Source code and documentation
The bindings and excerpts were checked against the source on 7 October 2026.