Both run_once_20-install-user-packages-gentoo.sh.tmpl and
run_once_40-install-sway-gentoo.sh.tmpl were missing the os_family
template guard (the overlays script got it in the previous fix but
these two slipped through). On non-gentoo boxes — arch, debian —
chezmoi apply would run them and they'd try to 'emerge', failing
with 'sudo: emerge: command not found' and exit status 1, which
breaks topgrade.
Wrap each body in '$0{ if eq .os_family "gentoo" }' / '$0{ else }',
mirroring the chaotic-aur script's pattern and the overlays fix from
the previous commit. On non-gentoo boxes the rendered script reduces
to a single 'skipping' log line and exits 0; on gentoo boxes the full
body (including the existing .sway_setup gate on the sway script) is
preserved.
Verified by rendering both scripts with a gentoo-config override:
arch (live) -> 'skipping gentoo user-packages' / 'skipping sway'
gentoo -> full body (293 / 87 lines)
Both pass bash -n and actually exit 0 when run on this arch box.
|
||
|---|---|---|
| dot_config | ||
| dot_local/bin | ||
| dot_omp/agent | ||
| .chezmoi.yaml.tmpl | ||
| .chezmoiignore | ||
| dot_gitconfig.tmpl | ||
| dot_tmux.conf | ||
| dot_zshrc.tmpl | ||
| README.md | ||
| run_once_00-install-bootstrap-tools.sh.tmpl | ||
| run_once_05-install-hosts.sh.tmpl | ||
| run_once_10-add-chaotic-aur.sh.tmpl | ||
| run_once_10-add-gentoo-overlays.sh.tmpl | ||
| run_once_20-install-user-packages-gentoo.sh.tmpl | ||
| run_once_20-install-user-packages.sh.tmpl | ||
| run_once_40-install-sway-gentoo.sh.tmpl | ||
| run_once_40-install-sway.sh.tmpl | ||
| run_onchange_30-ensure-cargo.sh.tmpl | ||
| run_onchange_35-ensure-omp-secret-perms.sh.tmpl | ||
gnu-plus-dotfiles
Chezmoi-managed dotfiles synced across all your linux boxes.
Source of truth: ~/.local/share/chezmoi on your main workstation.
Remote: https://git.melonbread.xyz/rain/gnu-plus-dotfiles.git (HTTPS for bootstrap, SSH from your main workstation for push — see Onboarding below).
Branches
main— current, bootstrap-enabled. All active work.legacy-2025— frozen snapshot of the pre-chezmoi-bootstrap config. Read-only.
What's in here
.chezmoi.yaml.tmpl os_family detection (debian | arch | gentoo)
dot_zshrc.tmpl zsh config with os_family-conditional aliases
dot_tmux.conf tmux + tpm + gruvbox plugin stack
dot_gitconfig.tmpl git + delta
dot_config/
bat/ bat config
btop/ btop theme + options
ghostty/ ghostty terminal + gruvbox themes
kitty/ kitty terminal + gruvbox themes
nvim/ LazyVim + custom plugins
paru/ (arch-only) paru config
sway/ sway + wofi + foot configs (desktops only)
foot/ foot terminal config
wofi/ wofi launcher configs + CSS
waybar/ waybar status bar
mako/ (arch-only) mako notification daemon
run_once_00-install-bootstrap-tools.sh.tmpl age, curl, git, base-devel (pacman/apt/emerge)
run_once_05-install-hosts.sh.tmpl merge LAN host entries into /etc/hosts
run_once_10-add-chaotic-aur.sh.tmpl (arch-only) chaotic-aur + paru
run_once_10-add-gentoo-overlays.sh.tmpl (gentoo-only) enable GURU overlay
run_once_20-install-user-packages.sh.tmpl (arch+debian) user package set
run_once_20-install-user-packages-gentoo.sh.tmpl (gentoo-only) user package set via emerge
run_onchange_30-ensure-cargo.sh.tmpl rustup + bat/topgrade/cargo-update (all 3 OSes)
run_once_40-install-sway.sh.tmpl (arch+debian) sway + wofi + foot
run_once_40-install-sway-gentoo.sh.tmpl (gentoo-only) sway stack via emerge
Gentoo notes
Gentoo support was added 2026-06-23 with the GURU overlay requirement. Key differences from arch/debian:
- No binary packages by default —
emergecompiles from source. The bootstrap scripts set--ask=n --nospinner --quiet-build --keep-goingso installs don't prompt and don't abort on a single failure. - USE flags matter —
run_once_20-install-user-packages-gentoo.shwrites to/etc/portage/package.use/zz-gentoo-bootstrapBEFORE emerging, so the right features are enabled foreza,foot,waybar, etc. - GURU overlay is required —
run_once_10-add-gentoo-overlays.shrunseselect repository enable guru+emaint sync -r guru. Many user packages (eza, lazygit, topgrade) live in GURU; the main tree alone won't suffice. - Per-machine os-release parsing — Gentoo's
/etc/os-releaseuses single-quoted values (e.g.ID='gentoo'), and the parser doesn't strip them, so theos_familytemplate strips them withtrimAll "'". Without that fix,.chezmoi.osRelease.idreturns'gentoo'(with literal quotes), and theeq "gentoo"test fails. - bun is not in any gentoo overlay — the official curl installer (
curl -fsSL https://bun.sh/install | bash) is the fallback path, just like debian.
Onboarding a new box
One command. Copy/paste this on a fresh debian-stable or arch-base install:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/...")" -- -b "$HOME/.local/bin" \
&& export PATH="$HOME/.local/bin:$PATH" \
&& chezmoi init --apply https://git.melonbread.xyz/rain/gnu-plus-dotfiles.git
Or as a heredoc that installs chezmoi then runs the bootstrap (more verbose, easier to read):
export PATH="$HOME/.local/bin:$PATH"
sh -c "$(curl -fsSL get.chezmoi.io)" -- -b "$HOME/.local/bin"
chezmoi init --apply https://git.melonbread.xyz/rain/gnu-plus-dotfiles.git
The bootstrap scripts run automatically as part of chezmoi init --apply. They will:
- run_once_00: install
age,git,curl,ca-certificatesvia the OS package manager - run_once_05: merge LAN host entries (
miche.local,kaiser.local, etc.) into/etc/hostsso omp/curl can resolve them - run_once_10 (arch only): add Chaotic-AUR repo + signing key, install
paru - run_once_20: install zsh, tmux, neovim (binary tarball, arch-aware URL), oh-my-zsh + plugins (autosuggestions, syntax-highlighting, history-substring-search, fzf-tab), tpm, all modern CLI tools (
batvia cargo or PM,btop,eza,fzf,fd,ripgrep,zoxide,starship,lazygit,yt-dlp,jq, etc.), set zsh as login shell (viasudo chsh), install Maple Mono NF font (GitHub release zip) - run_onchange_30: ensure rustup/cargo; install topgrade (
pacmanon arch via chaotic-aur,cargoon debian) and cargo-update
After bootstrap completes (~5-10 min on x86_64, longer on aarch64 with cargo install bat):
exec zsh
fastfetch will run on shell start, starship prompt active, all tools on PATH.
Per-machine age key (required to decrypt secrets)
The repo contains encrypted secrets (~/.omp/agent/zai.key, ~/.omp/agent/.env, ~/.omp/agent/models.yml) that only your per-machine age key can decrypt. After bootstrap, generate the key on this box:
age-keygen -o ~/.config/chezmoi/key.txt
# Paste the printed public key into ~/.local/share/chezmoi/.chezmoi.yaml.tmpl
# under the recipients list, then:
cd ~/.local/share/chezmoi
git pull
# (You'll be prompted to add --force if you have local changes)
chezmoi apply
If you skip this step, the omp config files will still land (they're not encrypted), but zai.key and .env will be missing and omp won't be able to authenticate against providers.
Why models.yml is encrypted (and not in zai.key)
omp v16.1.16 has a quirk: the built-in zai provider routes to https://api.z.ai/api/anthropic (Anthropic-compatible endpoint) which requires x-api-key. omp only sends Authorization: Bearer, so the built-in provider always 401s on real Z.ai API keys.
Workaround: define a custom zai-coding provider in ~/.omp/agent/models.yml pointing at the OpenAI-compatible endpoint https://api.z.ai/api/coding/paas/v4 (which DOES accept Authorization: Bearer).
Gotcha: omp's apiKey: field in custom providers expects a literal key value — NOT an env var name. apiKey: ZAI_CODING_API_KEY was being treated as the literal string ZAI_CODING_API_KEY and sent as Authorization: Bearer ZAI_CO...KEY → 401. The encrypted models.yml in this repo contains the literal Z.ai API key in apiKey: (same key that's in zai.key).
All three omp secrets (zai.key, .env, models.yml) are committed as encrypted_private_*.age. The prefix order matters: chezmoi parses attribute prefixes left-to-right, and encrypted_ must precede private_. encrypted_private_foo.age decrypts and lands at 0600; the reversed private_encrypted_foo.age makes chezmoi consume private_ and then treat encrypted_foo.age as a literal filename (no decryption — the file is copied verbatim, which is how a stale encrypted_models.yml.age blob ended up in ~/.omp/agent/). As belt-and-suspenders for boxes where a secret already sits at umask 0644 from a prior apply, run_onchange_35-ensure-omp-secret-perms.sh normalizes all three back to 600. Never rely on the enclosing ~/.omp/agent/ directory being 700 to protect these; the files carry their own mode.
Sway / Wayland desktop stack
Sway + wofi + foot + waybar + swaybg/lock/idle + grim/slurp + wl-clipboard is opt-in at bootstrap time. The user decides per-box.
Bootstrap prompt: when you run chezmoi init for the first time on a new box, you'll be asked:
sway_setup (default false)? [y/N]
Answer y to install the packages + write the configs. Answer N (or just press enter) to skip. The answer is captured in data.sway_setup in the rendered ~/.config/chezmoi/chezmoi.yaml and never re-asked.
Subsequent flips (per box, takes precedence over the bootstrap answer):
# Enable sway after the fact:
touch ~/.config/chezmoi/features/sway
chezmoi apply
# Disable sway (e.g. running a desktop headless as a server):
touch ~/.config/chezmoi/features/no-sway
rm -f ~/.config/chezmoi/features/sway
chezmoi apply
Migration from hostname-allowlist: the previous design auto-enabled sway on hostnames matching miche/byte/kaiser. That was removed. Existing desktops that already had sway installed kept the ~/.config/chezmoi/features/sway marker, which now serves as the override-on signal — so they still have sway_setup: true without re-prompting.
Migration of chezmoi.yaml: if you ran the new template via SSH (no TTY), the prompt fails with "could not open a new TTY". Run it interactively (chezmoi init) from a real terminal, OR pass --promptBool sway_setup=true|false to set the value without prompting.
The run_once_40-install-sway.sh script:
- exits 0 with no side effects on non-sway boxes
- installs
sway wofi foot swaybg swaylock swayidle grim slurp waybar wl-clipboardviapacman(arch) orapt(debian) - adds
dunstinstead ofmakoon debian (mako isn't packaged for debian) - creates the
~/.config/chezmoi/features/swaymarker so subsequent applies know it's enabled
The configs in dot_config/{sway,foot,wofi,waybar,mako}/ are placed unconditionally — they're harmless on Pis (no tools to read them).
Sway is NOT auto-launched. It's installed as a tool you run manually from a TTY (sway from TTY1) for light desktops. The install and configs sit ready; launching is your call.
Editing dotfiles
chezmoi edit ~/.zshrc # opens in $EDITOR, auto-applies on save
chezmoi diff # see what's pending
chezmoi apply # apply pending changes
chezmoi cd # jump to the source repo
From inside ~/.local/share/chezmoi, you can git status, git diff, git push like any normal repo.
Common gotchas
- Neovim too old on Debian:
run_once_20detects this and installs the official binary. If you see "Edit: command not found" inside LazyVim, neovim <0.9. - zsh plugins not loading: check
~/.oh-my-zsh/custom/plugins/exists. Bootstrap installs them. - paru 404 on arch: Chaotic-AUR mirrors occasionally lag. Re-run
sudo pacman -Syuthenchezmoi apply. - fastfetch not running: command not found, install via package manager. Debian needs
apt install fastfetch(bookworm+). Maple Mono NFfont warning in nvim: bootstrap should have installed it. Verify withfc-list | grep -i maple. If missing, see runbook skillchezmoi-bootstrap-runbookfor manual install.
Out of scope (intentionally not in repo)
~/.config/zsh/functions.zsh— host-specific (reads~/AI/llama.cpp/key.txt). Recreate per host.- KDE plasma configs (kwinrc, kdeglobals, etc.) — live state, varies wildly per host.
- Alacritty, foot, fish — not in use, drop if you want.
- mpv, topgrade, mako — out of scope unless re-added.