On many systems xmonad is available as a binary package in your distribution (Debian, Ubuntu, Fedora, Arch, Gentoo, …). It’s by far the easiest way to get xmonad, although you’ll miss out on the latest features and fixes that may not have been released yet.
If you do want the latest and greatest, continue reading. Those who install from distro can skip this and go straight to the XMonad Configuration Tutorial.
$ sudo apt install \
> git \
> libx11-dev libxft-dev libxinerama-dev libxrandr-dev libxss-dev
$ sudo dnf install \
> git \
> libX11-devel libXft-devel libXinerama-devel libXrandr-devel libXScrnSaver-devel
$ sudo pacman -S \
> git \
> libx11 libxft libxinerama libxrandr libxss \
> pkgconf
We’ll use the XDG directory specifications here, meaning our
configuration will reside within $XDG_CONFIG_HOME
, which is
~/.config
on most systems. Let’s create this directory and move to
it:
$ mkdir -p ~/.config/xmonad && cd ~/.config/xmonad
If you already have an xmonad.hs
configuration, you can copy it over
now. If not, you can use the defaults: create a file called xmonad.hs
with the following content:
import XMonad
main :: IO ()
main = xmonad def
Older versions of xmonad used ~/.xmonad
instead.
This is still supported, but XDG is preferred.
Still in ~/.config/xmonad
, clone xmonad
and xmonad-contrib
repositories
using git:
$ git clone https://github.com/xmonad/xmonad
$ git clone https://github.com/xmonad/xmonad-contrib
This will give you the latest HEAD
; if you want you can also check
out a tagged release, e.g.:
$ git clone --branch v0.15 https://github.com/xmonad/xmonad
$ git clone --branch v0.16 https://github.com/xmonad/xmonad-contrib
(Sources and binaries don’t usually go into ~/.config
. In our case,
however, it avoids complexities related to Haskell build tools and lets us
focus on the important bits of XMonad installation.)
There are two widely used Haskell build tools:
We include instructions for both. Unless you already know which one you prefer, use Stack, which is easier.
The easiest way to get stack is probably via your system’s package manager:
$ sudo apt install haskell-stack # Debian, Ubuntu
$ sudo dnf install stack # Fedora
$ sudo pacman -S stack # Arch
If you install stack via this method, it is advisable that you run
stack upgrade
after installation. This will make sure that you are on
the most recent version of the program, regardless of which version your
distribution actually packages.
If your distribution does not package stack, you can also easily install it via the following command (this is the recommended way to install stack via its documentation):
$ curl -sSL https://get.haskellstack.org/ | sh
Yet another way would be via ghcup; this is similar to installers like
rustup
, in case you prefer that.
Let’s create a stack project. Since we’re already in the correct
directory (~/.config/xmonad
) with xmonad
and xmonad-contrib
subdirectories, starting a new stack project is as simple as running stack
init
.
Stack should now inform you that it will use the relevant stack
and
cabal
files from xmonad
and xmonad-contrib
to generate its
stack.yaml
file. At the time of writing, this looks a little bit like
this:
$ stack init
Looking for .cabal or package.yaml files to use to init the project.
Using cabal packages:
- xmonad-contrib/
- xmonad/
Selecting the best among 19 snapshots...
* Matches https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/9.yaml
Selected resolver: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/9.yaml
Initialising configuration using resolver: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/9.yaml
Total number of user packages considered: 2
Writing configuration to file: stack.yaml
All done.
If you look into your current directory now, you should see a freshly
generated stack.yaml
file:
$ ls
xmonad xmonad-contrib stack.yaml xmonad.hs
The meat of that file (comments start with #
, we’ve omitted them here)
will look a little bit like
resolver:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/9.yaml
packages:
- xmonad
- xmonad-contrib
With stack.yaml
alongside xmonad.hs
, xmonad now knows that it needs to use
stack ghc
instead of just ghc
when (re)compiling its configuration.
If you want to keep xmonad sources and the stack project elsewhere, but still
use xmonad --recompile
, symlink your real stack.yaml
into the xmonad
configuration directory, or use a custom build script.
Installing things is as easy as typing stack install
. This will
install the correct version of GHC, as well as build all of the required
packages (stack build
) and then copy the relevant executables
(xmonad
, in our case) to ~/.local/bin
. Make sure to add that
directory to your $PATH
!
If you’re getting build failures while building the X11
package it may
be that you don’t have the required C libraries installed. See
above.
The easiest way to get cabal-install is probably via your system’s package manager:
$ sudo apt install cabal-install # Debian, Ubuntu
$ sudo dnf install cabal-install # Fedora
$ sudo pacman -S cabal-install # Arch
If your distribution does not package cabal-install, ghcup is another option. See also https://www.haskell.org/cabal/#install-upgrade.
Let’s create a cabal project. Since we’re already in the correct
directory (~/.config/xmonad
) with xmonad
and xmonad-contrib
subdirectories, we’ll instruct cabal to use them. Create a file named
cabal.project
containing:
packages: */*.cabal
(If you skip this step, cabal will use the latest releases from Hackage instead.)
You’ll need to update the cabal package index, build xmonad and xmonad-contrib libraries and then build the xmonad binary:
$ cabal update
$ cabal install --package-env=$HOME/.config/xmonad --lib xmonad xmonad-contrib
$ cabal install --package-env=$HOME/.config/xmonad xmonad
This will create a GHC environment in ~/.config/xmonad
so that the libraries
are available for recompilation of the config file, and also install the
xmonad binary to ~/.cabal/bin/xmonad
. Make sure you have that directory in
your $PATH
!
If you’re getting build failures while building the X11
package it may
be that you don’t have the required C libraries installed. See
above.
This step varies depending on your distribution and X display manager (if any).
/etc/X11/xinit/xinitrc
runs /etc/X11/Xsession
which runs ~/.xsession
, so
you probably want to put exec xmonad
there (don’t forget the shebang and chmod).
(Tested with startx
, xdm
, lightdm
.)
By using ~/.xsession
, the distro takes care of stuff like dbus, ssh-agent, X
resources, etc. If you want a completely manual X session, use ~/.xinitrc
instead. Or invoke startx
/xinit
with an explicit path.
Some newer display managers require an entry in /usr/share/xsessions
.
To use your custom ~/.xsession
, put these lines to
/usr/share/xsessions/default.desktop
:
[Desktop Entry]
Name=Default X session
Type=Application
Exec=default
(Tested with sddm
.)
/etc/X11/xinit/xinitrc
runs ~/.Xclients
, so you probably want to put exec
xmonad
there (don’t forget the shebang and chmod). Like in Debian, this can
be overridden by having a completely custom ~/.xinitrc
or passing arguments
to startx
/xinit
.
X display managers (e.g. lightdm
) usually invoke /etc/X11/xinit/Xsession
instead, which additionally redirects output to ~/.xsession-errors
and also
tries ~/.xsession
before ~/.Xclients
.
Newer display managers require an entry in /usr/share/xsessions
, which is
available in the xorg-x11-xinit-session
package.
/etc/X11/xinit/xinitrc
runs twm
, xclock
and 3 xterm
s; users are
meant to just copy that to ~/.xinitrc
and
customize it: replace the
last few lines with exec xmonad
.
Display managers like lightdm
have their own Xsession
script which invokes
~/.xsession
. Other display managers need an entry in
/usr/share/xsessions
, https://aur.archlinux.org/packages/xinit-xsession/
provides one.
If you need to customize what happens during xmonad --recompile
(bound to
M-q
by default), perhaps because your xmonad configuration is a whole
separate Haskell package, you need to create a so-called build
file. This
is quite literally just a shell script called build
in your xmonad directory
(which is ~/.config/xmonad
for us) that tells xmonad how it should build its
executable.
A good starting point (this is essentially what xmonad would do
without a build file, with the exception that we are invoking stack
ghc
instead of plain ghc
) would be
#!/bin/sh
exec stack ghc -- \
--make xmonad.hs \
-i \
-ilib \
-fforce-recomp \
-main-is main \
-v0 \
-o "$1"
Don’t forget to mark the file as +x
: chmod +x build
!
By default, xmonad always recompiles itself when a build script is used
(because the build script could contain arbitrary code, so a simple
check whether the xmonad.hs
file changed is not enough). If you find
that too annoying, then you can use the xmonad-ARCH
executable that
xmonad --recompile
generates instead of xmonad
in your startup. For
example, instead of writing
exec xmonad
in your ~/.xinitrc
, you would write
exec $HOME/.cache/xmonad/xmonad-x86_64-linux
The ~/.cache
prefix is the $XDG_CACHE_HOME
directory. Note that
if your xmonad configuration resides within ~/.xmonad
, then the
executable will also be within that directory and not in
$XDG_CACHE_HOME
.