Personal dotfiles managed with chezmoi and bootstrapped with Homebrew/Linuxbrew.
workstation- macOS desktop/laptop with GUI apps, casks, Aerospace, SketchyBar, Cursor, Zed and Claude config.homelab- headless Debian/Ubuntu with CLI and shell config only. No casks, GUI apps, fonts, window manager or status bar tooling.
The active profile is stored in ~/.config/chezmoi/chezmoi.toml:
[data]
profile = "homelab"
setapp = falseSet setapp = true on a macOS workstation to include the Setapp cask.
Setapp manages its own apps after login. Track expected apps in docs/setapp-apps.md and check them with:
scripts/list-setapp-apps.sh
scripts/check-setapp-apps.shFrom this checkout:
./bootstrap.sh workstation
./bootstrap.sh homelabOn a new machine, set DOTFILES_REPO if the default SSH URL is not available:
DOTFILES_REPO=git@github.com:zalewskigrzegorz/dotfiles.git ./bootstrap.sh homelabbootstrap.sh installs chezmoi if needed, writes the profile config, runs chezmoi init, then chezmoi apply.
git pull
syncIf lazygit has auto-migrated ~/.config/lazygit/config.yml, chezmoi may ask whether to overwrite it. Either answer yes once, or run chezmoi apply --force to take the version from this repo.
sync runs chezmoi apply, which runs run_after_05-restore-private-files.sh and restores private files from 1Password:
- Install
op(brew install 1password-clior viabrew bundlefrom the Linux Brewfile). - Reload the shell (
exec nuor new SSH session) soPATHincludes Linuxbrew. - Run
git pull, thensync. Ifophas an account but no active session,syncstartsop signinand uses that session for the restore.
If no 1Password account is configured, run op account add once. On a headless server, export OP_SERVICE_ACCOUNT_TOKEN before sync; if a TTY is available, sync can also prompt for that token.
Until op is on PATH and authenticated, sync will apply public dotfiles and skip only the private restore.
The Mac multiplexer is now herdr (
hd); tmux is kept only as a cold backup. This applies if you revert to tmux (git checkout pre-herdr) or are on the lab, where tmux is still active.
Tab labels with icons come from TPM plugin tmux-nerd-font-window-name plus ~/.config/tmux/tmux-nerd-font-window-name.yml. After a fresh machine or chezmoi migration:
- Run
chezmoi applyonce sorun_once_after_45-install-tmux-plugins.shcan clone TPM and install plugins (or inside tmux press prefix + capital I to install TPM plugins manually). - Restart tmux (or
tmux source-file ~/.config/tmux/tmux.conf). - Your terminal profile must use a Nerd Font (otherwise icons render as empty boxes or disappear).
Package installation is driven by ~/.Brewfile, rendered from dot_Brewfile.tmpl. The first apply installs Homebrew/Linuxbrew when missing, but brew bundle is opt-in while the app list is being reviewed:
brew bundle --global
# or
DOTFILES_RUN_BREW_BUNDLE=1 chezmoi applyThis repo used to be managed with GNU Stow. Before the first chezmoi apply on an existing host, remove legacy symlinks that point back into this repo:
legacy/migrate-stow-links-to-chezmoi.sh
legacy/migrate-stow-links-to-chezmoi.sh --applyThe script removes only symlinks whose targets are inside the current dotfiles checkout. It does not touch real files or directories.
Single-source-of-truth folders at repo root hold what's shared between both agents. chezmoi apply renders/syncs them into ~/.cursor/* and ~/.claude/*.
| Folder | Lives in repo as | Pushed to | Rendered by |
|---|---|---|---|
| Skills (shared, both agents) | agent-skills/<name>/SKILL.md |
~/.cursor/skills/ + ~/.claude/skills/ |
run_onchange_after_30-agent-skills-sync.sh.tmpl (rsync) |
| Rules (global) | agent-rules/<name>.md (+ Cursor-style frontmatter) |
~/.cursor/rules/<name>.mdc + ~/.claude/CLAUDE.md (only alwaysApply: true) |
run_onchange_after_31-agent-rules-sync.sh.tmpl |
| MCP servers (global) | agent-mcp/mcp-servers.json.tmpl |
~/.cursor/mcp.json (via dot_cursor/mcp.json.tmpl) + Claude user-scope via claude mcp add |
run_onchange_after_32-agent-mcp-sync.sh.tmpl |
| Cursor-only skills | dot_cursor/skills-cursor/<name>/SKILL.md |
~/.cursor/skills-cursor/ (chezmoi-managed) |
chezmoi default |
| Claude global file | (auto) | ~/.claude/CLAUDE.md (auto-generated from agent-rules/) |
rules sync |
Project-scoped configs are not touched: <repo>/.cursor/rules/, <repo>/CLAUDE.md, <repo>/.mcp.json stay per-project.
Add or change shared content, then chezmoi apply — both agents pick it up. For an ad-hoc skill resync without other chezmoi changes:
sync-agent-skillsSee docs/agents-sync.md for details (adding a new skill/rule/MCP server, secrets via 1Password, troubleshooting).
After first chezmoi apply on macOS, register the Claude session watchers:
cp ~/.config/launchd/com.greg.claude-watcher.plist ~/Library/LaunchAgents/
cp ~/.config/launchd/com.greg.claude-idle-timer.plist ~/Library/LaunchAgents/
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.greg.claude-watcher.plist
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.greg.claude-idle-timer.plistVerify with launchctl list | grep com.greg (PIDs should be > 0).
- Agent config (shared + per-agent):
docs/agents-sync.md - MCP client setup (Raycast/Cursor/Claude):
docs/mcp-clients-setup.md - Brew bundle reference:
docs/brew-snapshot-20260503.md - Stow link inventory:
docs/stow-links-before-chezmoi.md - Dotfiles inventory:
docs/dotfiles-inventory.md - Legacy Stow scripts:
legacy/