Installation

This guide covers installing bspwm on various Linux distributions, from package managers to building from source. bspwm is a minimal window manager, so you'll also need companion tools for a complete desktop experience.

Understanding What You're Installing

bspwm follows the UNIX philosophy of doing one thing well. It only manages windows—it doesn't handle keybindings, status bars, or application launching. This means you'll need additional tools:

Component Purpose Recommended Tools
Window Manager Arrange and manage windows bspwm
Hotkey Daemon Keyboard shortcuts sxhkd (same author as bspwm)
Compositor Transparency, shadows, animations picom, compton
Status Bar System info, workspace indicators polybar, lemonbar, tint2
Launcher Application menu rofi, dmenu, wofi
Notification Desktop notifications dunst, mako
Wallpaper Background image feh, nitrogen, hsetroot

This modular approach means you can swap any component without affecting the others.

Dependencies

Required Libraries

bspwm requires these X11/XCB libraries:

  • libxcb - X protocol C-language Binding
  • xcb-util - XCB utility libraries
  • xcb-util-wm - Window manager utilities for XCB
  • xcb-util-keysyms - Keysym utilities for XCB

These are typically installed automatically as dependencies when installing bspwm from a package manager.

For a functional desktop, you'll want at minimum:

  • sxhkd - Simple X hotkey daemon (essential—without it, you have no keybindings)
  • A terminal emulator - alacritty, kitty, urxvt, st, xterm
  • A launcher - rofi or dmenu for launching applications

For a polished experience, also consider:

  • picom - Compositor for transparency, shadows, and vsync (reduces screen tearing)
  • polybar or lemonbar - Status bar showing workspaces, time, system info
  • dunst - Notification daemon
  • feh or nitrogen - Wallpaper setter
  • xclip or xsel - Clipboard utilities

Package Installation

Arch Linux

# Essential
pacman -S bspwm sxhkd

# Recommended extras
pacman -S picom polybar rofi dunst feh alacritty

The Arch packages include example configuration files in /usr/share/doc/bspwm/examples/.

Debian / Ubuntu

# Essential
apt install bspwm sxhkd

# Recommended extras
apt install picom polybar rofi dunst feh

Note: Debian stable may have older versions. For newer releases, consider building from source or using backports.

Fedora

# Essential
dnf install bspwm sxhkd

# Recommended extras
dnf install picom polybar rofi dunst feh

openSUSE

# Essential
zypper install bspwm sxhkd

# Recommended extras
zypper install picom polybar rofi dunst feh

Gentoo

Gentoo provides fine-grained control through USE flags:

# Basic installation
emerge x11-wm/bspwm x11-misc/sxhkd

Available USE flags for bspwm:

USE Flag Description
examples Install example configuration files (recommended for first-time users)
doc Install documentation

To enable USE flags, add to /etc/portage/package.use/bspwm:

x11-wm/bspwm examples doc

Then emerge:

emerge --ask x11-wm/bspwm x11-misc/sxhkd

Recommended companion packages for Gentoo:

emerge --ask x11-misc/picom x11-misc/polybar x11-misc/rofi x11-misc/dunst media-gfx/feh

Setting up the session:

Create a .desktop file for your display manager:

cat > /usr/share/xsessions/bspwm.desktop << 'EOF'
[Desktop Entry]
Name=bspwm
Comment=Binary space partitioning window manager
Exec=bspwm
Type=Application
EOF

Void Linux

# Essential
xbps-install -S bspwm sxhkd

# Recommended extras
xbps-install -S picom polybar rofi dunst feh

FreeBSD

# Essential
pkg install bspwm sxhkd

# Recommended extras
pkg install picom polybar rofi dunst feh

Alpine Linux

# Essential
apk add bspwm sxhkd

# Recommended extras
apk add picom polybar rofi dunst feh

NixOS

Add to your configuration.nix:

services.xserver.windowManager.bspwm = {
  enable = true;
  configFile = "/home/youruser/.config/bspwm/bspwmrc";
  sxhkd.configFile = "/home/youruser/.config/sxhkd/sxhkdrc";
};

# Or for home-manager users
programs.bspwm = {
  enable = true;
};

For a declarative configuration with home-manager:

xsession.windowManager.bspwm = {
  enable = true;
  monitors = {
    eDP-1 = [ "I" "II" "III" "IV" "V" ];
  };
  settings = {
    border_width = 2;
    window_gap = 10;
    focused_border_color = "#7aa2f7";
  };
};

Building from Source

Building from source gives you the latest features and is required if your distribution doesn't package bspwm.

Prerequisites

Install build dependencies:

Debian/Ubuntu:

apt install build-essential git libxcb1-dev libxcb-util0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libxcb-randr0-dev libxcb-xinerama0-dev libxcb-ewmh-dev libxcb-shape0-dev

Fedora:

dnf install gcc make git xcb-util-devel xcb-util-keysyms-devel xcb-util-wm-devel libxcb-devel

Arch:

pacman -S base-devel git libxcb xcb-util xcb-util-wm xcb-util-keysyms

Building bspwm

git clone https://github.com/baskerville/bspwm.git
cd bspwm
make
sudo make install

The default installation prefix is /usr/local. To install elsewhere:

make PREFIX=/usr install

Building sxhkd

git clone https://github.com/baskerville/sxhkd.git
cd sxhkd
make
sudo make install

Installing Example Configs

After building from source, manually copy examples:

mkdir -p ~/.config/bspwm ~/.config/sxhkd
cp /usr/local/share/doc/bspwm/examples/bspwmrc ~/.config/bspwm/
cp /usr/local/share/doc/bspwm/examples/sxhkdrc ~/.config/sxhkd/
chmod +x ~/.config/bspwm/bspwmrc

Updating

To update to the latest version:

cd bspwm
git pull
make clean
make
sudo make install

Then restart bspwm: bspc wm -r

Removal

If installed from source:

cd bspwm
sudo make uninstall

If installed from package manager, use the appropriate removal command (pacman -R, apt remove, etc.).


Initial Configuration

Create the configuration directories:

mkdir -p ~/.config/bspwm ~/.config/sxhkd

Copy the example configurations:

install -Dm755 /usr/share/doc/bspwm/examples/bspwmrc ~/.config/bspwm/bspwmrc
install -Dm644 /usr/share/doc/bspwm/examples/sxhkdrc ~/.config/sxhkd/sxhkdrc

Add to your ~/.xinitrc:

sxhkd &
exec bspwm

Essential Keybindings (default sxhkdrc)

Keys Action
super + Return Open terminal
super + space Program launcher
super + Escape Reload sxhkd config
super + alt + q Quit bspwm
super + alt + r Restart bspwm
super + w Close window
super + {h,j,k,l} Focus window in direction
super + {1-9} Switch to desktop

Note: The default sxhkdrc uses urxvt as terminal. Edit to use your preferred terminal.


Multi-Monitor Setup

The default bspwmrc configures ten desktops on one monitor:

bspc monitor -d I II III IV V VI VII VIII IX X

For multiple monitors, configure each separately:

# Find monitor names
xrandr -q | grep " connected"
# Or: bspc query -M --names

# Configure desktops per monitor
bspc monitor HDMI-1 -d I II III IV V
bspc monitor eDP-1 -d VI VII VIII IX X

Setting Monitor Order

Explicitly set monitor order for consistent desktop indexing:

# Set order before configuring desktops
bspc wm -O HDMI-1 eDP-1

bspc monitor HDMI-1 -d I II III IV V
bspc monitor eDP-1 -d VI VII VIII IX X

Special Characters in Monitor Names

Escape names containing special characters with %:

bspc monitor %DVI-I-1.5 -d I II III IV V

Dynamic Monitor Configuration

Use conditionals in bspwmrc for different setups:

#!/bin/bash

if [[ $(xrandr -q | grep "HDMI-1 connected") ]]; then
    xrandr --output HDMI-1 --primary --mode 1920x1080 --pos 0x0 \
           --output eDP-1 --mode 1920x1080 --pos 1920x0
    bspc wm -O HDMI-1 eDP-1
    bspc monitor HDMI-1 -d I II III IV V
    bspc monitor eDP-1 -d VI VII VIII IX X
else
    bspc monitor eDP-1 -d I II III IV V VI VII VIII IX X
fi

Per-Host Configuration

#!/bin/bash

case "$HOSTNAME" in
    desktop)
        bspc wm -O DP-1 HDMI-1
        bspc monitor DP-1 -d I II III IV V
        bspc monitor HDMI-1 -d VI VII VIII IX X
        ;;
    laptop)
        bspc monitor eDP-1 -d I II III IV V VI VII VIII IX X
        ;;
esac

Updating sxhkdrc for Named Desktops

When using named desktops across monitors:

# Focus or send to desktop by name
super + {_,shift + }{1-9,0}
    bspc {desktop -f,node -d} '{I,II,III,IV,V,VI,VII,VIII,IX,X}'

Panel Setup

Polybar

Add to your bspwmrc:

# Kill existing bars and start polybar
killall -q polybar
polybar mybar &

Reserve space for the bar:

bspc config top_padding 30

Lemonbar

The bspwm repository includes an example panel script:

cp /usr/share/doc/bspwm/examples/panel ~/.config/bspwm/
chmod +x ~/.config/bspwm/panel

Add to bspwmrc:

~/.config/bspwm/panel &

Autostart Applications

Add applications to bspwmrc:

#!/bin/sh

# Hotkey daemon
pgrep -x sxhkd > /dev/null || sxhkd &

# Compositor
picom &

# Notification daemon
dunst &

# Wallpaper
feh --bg-scale ~/Pictures/wallpaper.jpg &

# Panel
polybar mybar &

# ... rest of bspwm configuration

Complete Example Configuration

Here's a complete, well-commented bspwmrc suitable for a first-time user. This configuration provides a good starting point that you can customize.

Example bspwmrc

#!/bin/bash
#
# bspwmrc - bspwm configuration file
# This file is executed as a shell script on bspwm startup.
#

#
# ─── AUTOSTART ──────────────────────────────────────────────────────────────────
#

# Start the hotkey daemon (essential - without this, no keybindings work)
# The pgrep check prevents starting multiple instances on restart
pgrep -x sxhkd > /dev/null || sxhkd &

# Compositor for transparency, shadows, and vsync
# Remove if you don't want visual effects
pgrep -x picom > /dev/null || picom --config ~/.config/picom/picom.conf &

# Notification daemon
pgrep -x dunst > /dev/null || dunst &

# Set wallpaper
# Replace with your wallpaper path
~/.fehbg &

# Start polybar
# Kill any existing instances first to handle restarts cleanly
~/.config/polybar/launch.sh &

# Set cursor (X uses an ugly X cursor by default)
xsetroot -cursor_name left_ptr &

# Disable screen blanking (optional)
xset s off
xset -dpms

#
# ─── MONITOR CONFIGURATION ──────────────────────────────────────────────────────
#

# Detect connected monitors and configure accordingly
# This handles both single and multi-monitor setups

# Get list of connected monitors
MONITORS=($(xrandr --query | grep " connected" | cut -d" " -f1))

if [ ${#MONITORS[@]} -eq 1 ]; then
    # Single monitor setup
    bspc monitor "${MONITORS[0]}" -d 1 2 3 4 5 6 7 8 9 10
elif [ ${#MONITORS[@]} -eq 2 ]; then
    # Dual monitor setup
    # Adjust order based on your physical layout
    bspc wm -O "${MONITORS[0]}" "${MONITORS[1]}"
    bspc monitor "${MONITORS[0]}" -d 1 2 3 4 5
    bspc monitor "${MONITORS[1]}" -d 6 7 8 9 10
else
    # Fallback: configure the first monitor only
    bspc monitor -d 1 2 3 4 5 6 7 8 9 10
fi

#
# ─── APPEARANCE ─────────────────────────────────────────────────────────────────
#

# Border width in pixels
bspc config border_width         2

# Gap between windows in pixels
bspc config window_gap          12

# Padding around the edges (space for panels, etc.)
bspc config top_padding         32  # Space for top bar
bspc config bottom_padding       0
bspc config left_padding         0
bspc config right_padding        0

# Border colors
bspc config normal_border_color   "#44475a"   # Unfocused windows
bspc config active_border_color   "#6272a4"   # Focused on inactive monitor
bspc config focused_border_color  "#bd93f9"   # Focused window
bspc config presel_feedback_color "#50fa7b"   # Preselection indicator

#
# ─── BEHAVIOR ───────────────────────────────────────────────────────────────────
#

# Split ratio for new windows (0.5 = equal split)
bspc config split_ratio          0.52

# How new windows are inserted
# longest_side: split perpendicular to longest side (most intuitive)
# alternate: alternate between horizontal/vertical
# spiral: classic bspwm spiral pattern
bspc config automatic_scheme     longest_side

# What to do when a window is removed
bspc config removal_adjustment   true

# Focus behavior
bspc config focus_follows_pointer  true   # Hover to focus
bspc config pointer_follows_focus  false  # Don't warp cursor on focus change
bspc config pointer_follows_monitor true  # Warp cursor when changing monitors

# Click behavior
bspc config click_to_focus       button1     # Left click to focus
bspc config swallow_first_click  false       # Pass the focusing click to the app

# Pointer actions (mod + mouse button)
bspc config pointer_modifier     mod4        # Super key
bspc config pointer_action1      move        # Super + left click = move
bspc config pointer_action2      resize_side # Super + middle click = resize edge
bspc config pointer_action3      resize_corner # Super + right click = resize corner

#
# ─── MONOCLE MODE ───────────────────────────────────────────────────────────────
#

# Remove borders when in monocle (single window) mode
bspc config borderless_monocle   true

# Remove gaps when in monocle mode
bspc config gapless_monocle      true

# Keep padding (for bars) even in monocle mode
bspc config paddingless_monocle  false

# Automatically use monocle when only one window exists
bspc config single_monocle       false

#
# ─── EXTERNAL RULES ─────────────────────────────────────────────────────────────
#

# Path to external rules script (for complex dynamic rules)
# Uncomment and set path if you use external rules
# bspc config external_rules_command "$HOME/.config/bspwm/external_rules"

#
# ─── WINDOW RULES ───────────────────────────────────────────────────────────────
#
# Rules define automatic behavior for specific applications.
# Find window class with: xprop | grep WM_CLASS
#

# Floating applications
bspc rule -a Pavucontrol state=floating center=on
bspc rule -a Lxappearance state=floating center=on
bspc rule -a Arandr state=floating center=on
bspc rule -a Gpick state=floating center=on
bspc rule -a Nm-connection-editor state=floating center=on
bspc rule -a File-roller state=floating center=on

# Picture-in-picture (floating, sticky, always on top)
bspc rule -a "*:*:Picture-in-Picture" state=floating sticky=on layer=above

# Applications assigned to specific desktops
# bspc rule -a Firefox desktop='^2' follow=on
# bspc rule -a Code desktop='^3' follow=on
# bspc rule -a Spotify desktop='^10' follow=off

# Don't manage certain windows
bspc rule -a Conky state=floating manage=off

# Force some apps to tile even if they request floating
bspc rule -a Steam state=tiled

#
# ─── CLEANUP ────────────────────────────────────────────────────────────────────
#

# Adopt any orphaned windows from a previous session
bspc wm -o

# Notify that bspwm is ready (optional, for debugging)
# notify-send "bspwm" "Configuration loaded"

Example sxhkdrc

Here's a matching sxhkdrc with explanations:

#
# sxhkdrc - sxhkd configuration file
# Hotkey definitions for bspwm
#

#
# ─── WM CONTROL ─────────────────────────────────────────────────────────────────
#

# Quit bspwm
super + alt + q
    bspc quit

# Restart bspwm (keeps windows, reloads config)
super + alt + r
    bspc wm -r

# Reload sxhkd configuration
super + Escape
    pkill -USR1 -x sxhkd; notify-send "sxhkd" "Configuration reloaded"

#
# ─── APPLICATIONS ───────────────────────────────────────────────────────────────
#

# Terminal
super + Return
    alacritty

# Application launcher
super + space
    rofi -show drun -show-icons

# Window switcher
super + Tab
    rofi -show window -show-icons

# File manager
super + e
    thunar

# Browser
super + b
    firefox

#
# ─── WINDOW CONTROL ─────────────────────────────────────────────────────────────
#

# Close window
super + w
    bspc node -c

# Kill window (force)
super + shift + w
    bspc node -k

# Toggle window states
super + t
    bspc node -t tiled

super + shift + t
    bspc node -t pseudo_tiled

super + s
    bspc node -t floating

super + f
    bspc node -t fullscreen

# Toggle monocle layout
super + m
    bspc desktop -l next

#
# ─── WINDOW FOCUS ───────────────────────────────────────────────────────────────
#

# Focus window in direction
super + {h,j,k,l}
    bspc node -f {west,south,north,east}

# Focus next/previous window
super + {comma,period}
    bspc node -f {prev,next}.local.!hidden.window

# Focus last window
super + grave
    bspc node -f last

# Focus urgent window
super + u
    bspc node -f any.urgent

#
# ─── WINDOW MOVEMENT ────────────────────────────────────────────────────────────
#

# Swap window in direction
super + shift + {h,j,k,l}
    bspc node -s {west,south,north,east}

# Send window to desktop
super + shift + {1-9,0}
    bspc node -d '^{1-9,10}'

# Send window to desktop and follow
super + ctrl + {1-9,0}
    bspc node -d '^{1-9,10}' --follow

# Send to next/previous desktop
super + shift + {Left,Right}
    bspc node -d {prev,next}.local --follow

#
# ─── DESKTOP CONTROL ────────────────────────────────────────────────────────────
#

# Focus desktop
super + {1-9,0}
    bspc desktop -f '^{1-9,10}'

# Focus next/previous desktop
super + bracket{left,right}
    bspc desktop -f {prev,next}.local

# Focus last desktop
super + BackSpace
    bspc desktop -f last

#
# ─── PRESELECTION ───────────────────────────────────────────────────────────────
#

# Preselect direction
super + ctrl + {h,j,k,l}
    bspc node -p {west,south,north,east}

# Preselect ratio
super + ctrl + {1-9}
    bspc node -o 0.{1-9}

# Cancel preselection
super + ctrl + space
    bspc node -p cancel

#
# ─── RESIZE ─────────────────────────────────────────────────────────────────────
#

# Expand window
super + alt + {h,j,k,l}
    bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}

# Contract window
super + alt + shift + {h,j,k,l}
    bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0}

# Move floating window
super + {Left,Down,Up,Right}
    bspc node -v {-20 0,0 20,0 -20,20 0}

# Balance all windows
super + equal
    bspc node @/ -B

#
# ─── TREE MANIPULATION ──────────────────────────────────────────────────────────
#

# Rotate tree
super + r
    bspc node @/ -R 90

# Flip tree horizontally/vertically
super + {_,shift +} y
    bspc node @/ -F {horizontal,vertical}

#
# ─── LAYERS AND FLAGS ───────────────────────────────────────────────────────────
#

# Toggle sticky (window follows to all desktops)
super + shift + s
    bspc node -g sticky

# Toggle hidden
super + shift + minus
    bspc node -g hidden

# Show hidden windows
super + shift + plus
    bspc node any.hidden.local -g hidden=off

# Toggle private (prevent auto-resize)
super + shift + p
    bspc node -g private

First Login Checklist

After setting up bspwm for the first time, verify these work:

  1. Can you open a terminal? Press Super + Return
  2. Can you close it? Press Super + w
  3. Can you launch apps? Press Super + Space for rofi/dmenu
  4. Can you switch desktops? Press Super + 1-9
  5. Can you move windows? Press Super + Shift + h/j/k/l
  6. Can you quit? Press Super + Alt + q

If any of these fail, check:

  • Is sxhkd running? Run pgrep sxhkd
  • Is the terminal emulator installed? Check your sxhkdrc
  • Check ~/.config/sxhkd/sxhkdrc for syntax errors

See Troubleshooting for more help.


Next Steps

After installation, explore:

  1. Commands Reference - Learn all bspc commands
  2. Settings Reference - Customize appearance and behavior
  3. Window Rules - Automate window placement
  4. Technical Background - Understand the binary tree model

Join the community: