Meta-repo that ties together my dwm, st, slock, and slstatus builds (each its own repo, pulled in as a git submodule), plus a dotfiles set and one installer script, so a fresh Arch install can be turned into this whole desktop with a single command.
This repo has no source code of its own. Everything patch- or config-related lives in the submodule it belongs to; see that submodule's own README for version, patches, and modifications. What follows is specific to the orchestration layer: the dotfiles, install.sh, and how the pieces actually fit together.
suckless-btw/
├── dwm/ (submodule)
├── st/ (submodule)
├── slstatus/ (submodule, ships its own scripts/ for bar segments and click handlers)
├── slock/ (submodule)
├── dotfiles/
├── install.sh
└── .gitmodules
There's no top-level scripts/ directory anymore. The status bar's click handlers and status scripts moved inside slstatus/scripts/ a few commits back; if you're looking for discord-status.sh or audio-device-selector-handler.sh, that's where they are now.
.gitmodules pins each one to a branch:
dwm→mainst→masterslstatus→mainslock→master
dotfiles/ covers the shell (zsh as the daily driver, with a bash fallback for bash_profile/bashrc), tmux.conf, a rofi config (drun/window/run modes, Papirus icons, the android_notification theme), and Neovim built on LazyVim with Mason, Telescope, Treesitter, and Gruvbox. Yazi gets its own directory with a gruvbox-dark flavor under themes/flavors/.
dotfiles/nvim/README.md still lists NeoTree as the file explorer plugin. It isn't anymore, lua/plugins/ui/snacks-tree.lua swapped it for snacks.nvim's tree a few commits ago (see "Neotree replaced by snacks-tree" in the git log), and that inner README never got updated to match.
dotfiles/xinitrc is the actual entry point: it kills the X bell, sets the wallpaper with feh --bg-scale, toggles US/ES keyboard layouts on Alt+Shift, ties slock to xss-lock so the screen locks before systemd suspends the machine, starts picom, dunst, and slstatus, then execs dwm. Picom's job here is compositing for st's alpha patch, not dwm, this dwm build doesn't have a transparency patch of its own.
detect_machine() reads /sys/class/dmi/id/product_version for a ThinkPad T480 match and /sys/class/dmi/id/board_name (falling back to /proc/cpuinfo) for a Ryzen desktop match, then picks which extra dotfile symlinks to apply on top of the base set. check_dependencies() only checks for make, gcc, and git, nothing checks for the Xlib, Xinerama, Xft, Imlib2, or libXrandr headers the four suckless projects actually link against, so a missing library shows up as a compiler error partway through install_suckless, not as an upfront warning.
For each of dwm, st, slock, and slstatus, install_suckless() runs make clean && make && sudo make install inside that submodule's directory, unless a binary of the same name is already on PATH, in which case it skips straight past with a log line telling you to pass --force. That also means editing a submodule's config.h and rerunning install.sh without --force won't rebuild anything, the script sees dwm (or whichever) already on PATH and skips it.
Flags: --dry-run logs what would happen without touching anything, --force recompiles every project regardless of what's already installed, --uninstall removes the dotfile symlinks and restores the .bak backups.
- Two unrelated machine-detection systems exist side by side.
install.shpicks dotfiles based on DMI/CPU hardware info. The dwm and slstatus Makefiles decide whether to defineBUILD_DESKTOPbased on$(hostname)matching the literal stringarchlinux-desktop, a completely different signal. Worse, that hostname check has a syntax mistake (documented in both of those repos' READMEs) that makes it always evaluate true, soBUILD_DESKTOPisn't actually gated on the hostname at all right now. THINKPAD_LINKSmaps a keyxinitrc_thinkpadto$HOME/.xinitrc, but there's nodotfiles/xinitrc_thinkpadfile, onlydotfiles/xinitrc.backup_and_link()prints "Fuente no encontrada" and skips it, so on an actual T480 that override never applies, you get the same basexinitrcas everyone else.dotfiles/xinitrcpointsfehat~/dev/suckless-btw/background.png, butbackground.pngis in.gitignoreand isn't part of this repo. Drop your own image there before starting X, or that line just fails quietly in the background.
Requirements, laptop (Intel):
sudo pacman -S base-devel git xorg-server xorg-xinit rofi pamixer xss-lock inetutils gsimplecal \
xclip maim less
yay -S vesktop ttf-jetbrains-mono-nerd
paru -S vesktop ttf-jetbrains-mono-nerdRequirements, desktop (AMD CPU and GPU):
sudo pacman -S base-devel git xorg-server xorg-xinit rofi pamixer xss-lock inetutils gsimplecal \
mesa vulkan-radeon xf86-video-amdgpu lm_sensors xclip maim less
yay -S vesktop ttf-jetbrains-mono-nerd
paru -S vesktop ttf-jetbrains-mono-nerdYazi needs its own set for previews to work:
sudo pacman -S yazi ffmpeg jq poppler fd ripgrep fzf zoxide imagemagick chafa 7zip
yay -S ueberzugpp resvg
paru -S ueberzugpp resvg| Package | What it's for |
|---|---|
ffmpeg |
video and audio previews |
7zip |
archive previews |
jq |
JSON previews |
poppler |
PDF previews |
fd |
file search |
ripgrep |
text search |
fzf |
fuzzy search |
zoxide |
smarter cd |
imagemagick |
image conversion |
chafa |
terminal image previews |
ueberzugpp |
higher-quality image previews |
resvg |
SVG previews |
Clone and pull in the submodules:
mkdir -p ~/dev && cd ~/dev
git clone git@github.com:MartoNievas/suckless-btw.git
cd suckless-btw
git submodule update --init --recursiveRun the installer:
chmod +x install.sh
./install.sh./install.sh --dry-run simulates the run without changing anything, ./install.sh --force recompiles every project even if it's already installed, ./install.sh --uninstall tears down the symlinks and restores whatever .bak files it made.
Bump one after pushing changes inside it:
cd <submodule>
git push
cd ..
git add <submodule>
git commit -m "Bump <submodule>"
git pushUpdate all of them at once:
git submodule update --remote --merge
git commit -am "Update all submodules"
git pushdwm, st, slock, and slstatus are written and maintained by suckless.org; each submodule's own README covers its version, patches, and the changes specific to that build.