Single source of truth for my machine config, managed with chezmoi. Works across the Cegeka work Mac and the personal Mac; everything that differs between them differs by template variable, not by having two copies of a file.
# 1. Homebrew, if it isn't there yet
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 2. chezmoi + this repo. Asks three questions, then does everything else.
brew install chezmoi
chezmoi init --source ~/dotfiles --apply https://github.com/stijnj/dotfiles.gitThe three questions:
| Prompt | Meaning |
|---|---|
| Is this a work machine (Cegeka) | Gates Cegeka packages, Teams/Outlook/Jira bindings, the mysql-client PATH |
| Work git email | Used for repos with a gitlab.cegeka.* remote |
| Personal git email | Used for everything else |
Then:
dotfiles-doctor # pass/fail on everything a script can checkNothing below can be scripted. dotfiles-doctor reports each one.
-
Karabiner-Elements —
brew install --cask karabiner-elementsneeds an interactive sudo, so it can fail during an unattendedchezmoi apply. Run it by hand, then open the app once and approve the driver extension: System Settings › General › Login Items & Extensions › Driver Extensions. The Caps Lock → Super rule is already inkarabiner.json— you do not need to add it from the UI. -
Mission Control spaces (optional, not set up) — there are no workspaces any more; macOS tiling has no such concept. If you want something like them: System Settings › Keyboard › Keyboard Shortcuts › Mission Control to bind
⌃1..⌃9, then Dock › right-click an app › Options › Assign To to pin apps to a space. Undecided — the old assignments are recorded indocs/rejected/. -
Raycast hotkeys — main hotkey to Caps+Space (
⌘⌃⌥Space), clipboard history to Caps+V. Leave⌘Spaceon Spotlight so corporate search still works. Add~/.config/raycast/scriptsunder Script Commands (⇧⌘Gin the file picker —.configis hidden) and give "Keybindings" the hotkey Caps+K. -
Raycast Window Management — the whole window keymap. Raycast stores hotkeys in its own database with no supported export, so this cannot be scripted or committed and must be redone on every machine. Raycast Settings › Extensions › Window Management, then record each hotkey:
| Command | Hotkey | |---|---| | Left Half / Right Half | `Super ←` / `Super →` | | Top Half / Bottom Half | `Super ↑` / `Super ↓` | | Previous Display / Next Display | `Super ⇧ ←` / `Super ⇧ →` | | Maximize | `Super F` | | Center | `Super C` | | Restore | `Super R` | Karabiner must not bind these — `dotfiles-doctor` fails if it does. -
Reduce Motion — System Settings › Accessibility › Display › Reduce Motion: OFF. It was only ever on to hide AeroSpace's workspace-switch animation. The apply script attempts to turn it off, but the domain is TCC-protected and the write can fail silently.
-
npm tokens — create the 1Password item that
~/.npmrcreads:op item create --category="API Credential" --vault=Employee \ --title="npm-registry-tokens" \ "npmjs_token[password]=<token>" "fontawesome_token[password]=<token>"
| Path | What |
|---|---|
.chezmoi.toml.tmpl |
The three init prompts, and sourceDir — this repo lives at ~/dotfiles, not chezmoi's default ~/.local/share/chezmoi |
.chezmoitemplates/Brewfile |
Package list, rendered inline by the brew script — never written to $HOME |
.chezmoiscripts/ |
Homebrew, macOS defaults, VS Code extensions, the manual checklist |
dot_zshrc.tmpl |
zsh + oh-my-zsh + starship |
dot_gitconfig.tmpl |
Identity split by remote URL |
private_dot_config/ |
ghostty, karabiner (Caps Lock → Super, nothing else), starship, git, raycast |
docs/rejected/ |
Things deliberately removed, kept as a record — not config |
dot_claude/ |
Claude Code settings, statusline, skills |
dot_local/bin/ |
dotfiles-doctor |
- Prompt is starship, not powerlevel10k. Omarchy's
starship.tomlis used unchanged. This drops the kubecontext/Azure/gcloud/exit-code indicators p10k showed on demand — a deliberate trade. If they turn out to be missed, add starship's ownkubernetes/azure/gcloud/cmd_durationmodules rather than going back to p10k. - Git identity by remote, not path.
~/Developeris a flat mix of Cegeka GitLab and GitHub checkouts. Threehasconfigpatterns are needed because the remotes come in three URL shapes. - No window manager; Raycast does the window keys. AeroSpace was removed:
the tree model didn't match how I think about windows and there was too much
vocabulary to learn. Raycast was already installed, and its positioning is
fractional ("left half of whatever screen this is"), so layouts survive
docking and undocking where saved pixel coordinates do not.
Cost, stated plainly: the window keymap is no longer in this repo. Raycast
keeps hotkeys in an internal database with no supported export, so it is a
manual step per machine — the one place this repo stops being the single
source of truth. Karabiner forwarding to macOS's own
⌃ globetiling shortcuts was built and reverted (8939b76) rather than tested; if the Raycast hotkeys ever become tiresome to re-enter, that commit is the way back. What is simply gone — workspaces, auto-placement,close, resize keys — is written down indocs/rejected/, not replaced. - The Karabiner rule is inlined into
karabiner.json, not dropped intoassets/complex_modifications/. The latter only makes a rule available and still needs enabling by hand on every machine. Caps Lock → Super is now the only rule; the app launchers and the terminal paste shim were removed (docs/rejected/karabiner-super-rules.md), which emptied the.workconditional, so this is plain JSON rather than a template. Cost: Karabiner rewrites this file when you change settings in its UI, sochezmoi diffwill occasionally show drift — butchezmoi re-addnow absorbs it, which it refused to do while the file was a template. - No mise, no colima, though Omarchy ships both — they would collide with pyenv/fnm and Docker Desktop. Listed commented-out in the Brewfile.
.macoswas discarded, not migrated. 150 of its 175 keys read UNSET on the work Mac: it had never been applied. The replacement script encodes the 9 settings actually in use plus 15 added deliberately.
Nothing sensitive is committed. ~/.npmrc is the only file with credentials
and it is templated through onepasswordRead. Verified with git log -S over
every commit patch, not just the tree.