Repository structure
arch-install-kit/
├── install.sh # entry point: flags, module order
├── installer/ # everything install.sh reads
│ ├── lib/ # shared functions used by the modules
│ │ ├── log.sh # output and log file
│ │ ├── run.sh # run (with --dry-run), module runner
│ │ ├── sudo.sh # refuse root, sudo handling
│ │ ├── ui.sh # gum prompts: group picker, confirmation
│ │ ├── pkg.sh # reading lists, installing via yay
│ │ ├── hw.sh # CPU, GPU, bootloader, kernels
│ │ └── fs.sh # backups, deploying dotfiles
│ ├── modules/ # install steps, run in numeric order (00-preflight … 99-finish)
│ ├── packages/ # package lists per group
│ ├── services.txt # which systemd units to enable
│ └── system/ # files for /etc and /usr/lib, laid out like their targets:
│ # SDDM, Plymouth, reflector, makepkg, zram + sysctl, zswap,
│ # systemd-oomd, Timeshift, polkit, sleep hook
├── dotfiles/ # mirror of $HOME: .config/, .local/, bin/, .gtkrc-2.0
├── assets/ # wallpapers and screenshots
├── docs/ # documentation
├── website/ # VitePress site built from docs/
├── tests/ # bats, bun and Lua tests (see testing.md)
├── .github/ # CI workflows, contributing guide, security policy
└── package.json, mise.toml # dev tools: lint, tests, docs site (configs live in package.json)How install.sh works
- Sources every
installer/lib/*.sh. - Parses the flags (
--minimal,--only,--dry-run…). - Installs its own dependencies from
installer/packages/bootstrap.txt(pkg_bootstrap). - Unless
--yesis given or there's no terminal, lets you pick optional groups and confirm the plan (installer/lib/ui.sh, gum). - Runs
installer/modules/NN-name.shone by one. Each module runs in its own subshell in strict mode (set -Eeuo pipefail), so an error only stops that module. - If a critical module fails (
preflight,pacman,aur-helper), the install aborts. Anything else can be re-run with--only.
Module rules
- One module, one job. File name is
NN-name.sh; the number sets the order. - Anything that changes the system goes through
run. That's what makes--dry-runwork. - Idempotency. Before changing something, check whether it's already done (
grep -q,is_installed) so re-runs don't break anything. - Edit system files only after
backup_once. When possible, write a drop-in instead (/etc/modprobe.d/,/etc/mkinitcpio.conf.d/) withwrite_root_file. - Finish with
ok "…". That way the output shows the step completed.
The shell style (quoting, set -e gaps, temp files, traps) is in the style guide.
Adding a module
cat > installer/modules/55-example.sh <<'EOF'
#!/usr/bin/env bash
# One line: what this module does.
if ! is_installed example; then
pkg_install example
fi
ok "Example configured"
EOFIt shows up in ./install.sh --help right away and is available as --only example.
Dotfiles
dotfiles/ mirrors your home folder:
| In the repo | Ends up in |
|---|---|
dotfiles/.config/hypr/ | ~/.config/hypr/ (hyprland.lua, conf/*.lua, hypridle/hyprlock/hyprpaper/hyprsunset .conf) |
dotfiles/.config/theme/ | ~/.config/theme/ (kanagawa.css: the shared palette, see Theming) |
dotfiles/.config/waybar/ | ~/.config/waybar/ (style.css imports style/{base,left,center,right}.css) |
dotfiles/.config/swaync/ | ~/.config/swaync/ (style.css imports style/*.css) |
dotfiles/.config/waybar-weather/ | ~/.config/waybar-weather/ (config.toml; the installer writes cityname from your timezone) |
dotfiles/.config/MangoHud/ | ~/.config/MangoHud/ (the in-game overlay, see Gaming) |
dotfiles/bin/ | ~/bin/ |
dotfiles/.gtkrc-2.0 | ~/.gtkrc-2.0 |
dotfiles/.local/share/applications/ | ~/.local/share/applications/ (hides helper apps from the launcher) |
The dotfiles module deploys them in one of two ways:
copy (default) —
rsync --backup: replaced files go to~/.config-backup/<date>/;symlinks (
--link) — GNU Stow:~/.config/hyprpoints into the repo, so edits show up ingit statusright away.Some apps rewrite their own config when you change a setting: nwg-look (
gtk-3.0,gtk-4.0,.gtkrc-2.0), waypaper (waypaper/config.ini, which gains an absolute/home/…path) and Thunar (xfce4/…/thunar.xml). In link mode those writes land in the repo — review them ingit diffand commit orgit restorethem.
No secrets live in the repo, and none are needed: the weather module works without an API key.
Theme
Every app shares one Kanagawa palette, ~/.config/theme/kanagawa.css. The colors, roles and the files that copy them are in Theming.
Services
installer/services.txt: unit, system/user, package. A unit is enabled only if its package is installed:
docker.socket system docker