Files
dotconfs/README.md
T
thomas.koppandClaude Opus 5 4594ad337a docs: the nvim plugins have to be installed, not worked around
silent! on the colorscheme stops nvim erroring on a machine where PlugInstall
has never run, but it does not give you gruvbox - it gives you the default
theme without saying so. That is a safety net for the gap between checkout and
install, not a fix.

Setting up a machine now lists both steps: packages.sh for the system packages
and PlugInstall for the ten nvim plugins. Also noted that firenvim reports "No
config detected" for every browser on a headless host, which looks like a
failure and is not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 23:55:23 +02:00

176 lines
6.2 KiB
Markdown

# dotconfs
Configuration for three machines out of one repository: an Arch desktop, an
Arch server and a Mac. The role is decided when the shell starts, not when
files are deployed.
The bare-repository technique is from
[an Atlassian post](https://developer.atlassian.com/blog/2016/02/best-way-to-store-dotfiles-git-bare-repo/):
a git directory in `$HOME/.cfg` with `$HOME` as its work tree, driven by an
alias. No symlinks, no extra tooling.
## Roles
| Role | Machine | Prompt |
|---|---|---|
| `desktop` | beastix — Arch, KDE | powerlevel10k, blue |
| `server` | shron — Arch, headless | powerlevel10k, ASCII, **red** |
| `mobile` | the Mac — macOS, Apple Silicon | ys, green once p10k is there |
Red on the server is a guard, not decoration. shron carries mail, web and
cloud, and the prompt should answer "which machine is this" before the next
command is typed.
The role lives in `~/.config/dotconfs/role`, one word, and is **not** tracked —
a shared copy would defeat the purpose. Write it before the first login.
Without it the shell falls back to `desktop`.
## Layout
```
.zshrc stub: role, then oh-my-zsh, then the fragments
.zprofile login shells only; Homebrew's shellenv
.config/zsh/rc.d/
05-pre-omz.zsh theme and plugins - must precede oh-my-zsh
10-aliases.zsh shared
20-functions.zsh shared
30-path.zsh shared
50-desktop.zsh exactly one of these is sourced
50-server.zsh
50-mobile.zsh
90-local.zsh machine-local, never committed
.config/zsh/p10k-server.zsh the server's prompt, ASCII and font-agnostic
packages/ one plain list per platform and role
.scripts/packages.sh check | install
.scripts/curate.sh derive a package list from usage
```
Every machine checks out every file. A KDE configuration on the server is a few
inert kilobytes and costs less than the machinery needed to avoid it.
### Load order
It matters, and getting it wrong fails quietly:
1. powerlevel10k instant prompt — must be first, it may print
2. role
3. `05-pre-omz.zsh`**theme and plugins**, because oh-my-zsh consumes both
while it is being sourced. Set afterwards, they are ignored: an early
attempt reported `ZSH_THEME=powerlevel10k` from a shell running without it.
4. oh-my-zsh
5. `10-` to `40-` — shared
6. `50-<role>.zsh`**the prompt colour**, because `~/.p10k.zsh` assigns
`POWERLEVEL9K_CONTEXT_BACKGROUND` itself and is sourced in `30-path.zsh`
7. `90-local.zsh` — last, so it can override anything
Theme before oh-my-zsh, colour after `.p10k.zsh`. Two constraints pulling in
opposite directions.
## Portability
Anything that depends on a command is guarded by whether that command exists,
rather than duplicated per role:
```sh
(( $+commands[lsd] )) && alias ls='lsd'
```
Without the guard, `alias ls='lsd'` turns `ls` into a broken command on a
machine without lsd. The Mac is such a machine.
Plugins are assembled per role and then filtered by what is installed. Naming
a plugin that is absent produces an oh-my-zsh warning at every single login.
## Packages
Lists are plain names, one per line — data, not code, so they port to
`home-manager` and `environment.systemPackages` almost unchanged.
```
.scripts/packages.sh what is missing, what is extra
.scripts/packages.sh install install what is missing
```
**It never removes anything.** Extras are reported and left alone: on a server,
individual packages carry mail and web services.
`curate.sh` derives a candidate list from four usage signals, because each one
alone is blind to something — shell history sees no GUI application, KDE's
activity database sees no chat client, autostart sees only what starts by
itself, and flatpaks never appear in `pacman -Qqe`. On beastix that turned 512
explicit packages into 62.
## Secrets
Credentials live beside the code that reads them and are never committed. The
waybar mail module imports from `mailsecrets.py`; `.gitignore` covers that,
private keys, `.netrc`, `.pgpass`, and `.config/kdeconnect/`, which holds the
device certificate.
Machine-local overrides and anything sensitive belong in
`.config/zsh/rc.d/90-local.zsh`, which is sourced last and never tracked.
`config add -f` still bypasses all of it. The ignore list guards against
carelessness, not intent.
## Setting up a new machine
```sh
curl -Ls https://ls.shron.de/dotconf | /bin/bash
```
The installer clones into `$HOME/.cfg`, defines the alias and moves anything in
the way to `.config-backup`. Write the role file before the first login:
```sh
mkdir -p ~/.config/dotconfs && echo server > ~/.config/dotconfs/role
```
Then, by hand:
```sh
config config --local status.showUntrackedFiles no
config checkout master
```
Then install what the configuration files expect but do not carry:
```sh
.scripts/packages.sh install # system packages for the role
nvim --headless "+PlugInstall --sync" +qall # the nvim plugins
```
The nvim step matters more than it looks. gruvbox is a plugin, and until
`PlugInstall` has run, nvim comes up in the default theme. The `colorscheme`
line is wrapped in `silent!` so a fresh machine does not error before then —
that is a safety net for the gap, not a substitute for installing them.
On a headless machine `firenvim` will report "No config detected" for every
browser it looks for. That is expected and harmless.
> Earlier revisions of this file used `curl -Lks`. The `-k` disables
> certificate verification against a host that has a valid certificate,
> removing precisely the protection that matters when piping a remote script
> into a shell. It is gone.
## Day to day
```sh
config status
config add .zshrc
config commit -m "..."
config push
```
`status.showUntrackedFiles=no` keeps `$HOME` from drowning the output.
Servers pull over HTTPS rather than SSH: a machine that only consumes
configuration has no business holding push credentials.
## History
Everything before 2026-08-07 is on `archive/2021-i3-sway`. That tree described
an i3/sway desktop that no longer exists — its display menu drove `xrandr`
outputs the machine does not have — while the live files had moved on by years.
`master` was rebuilt from the running configuration rather than merged with it.