Personal macOS dotfiles. Plain zsh, starship, mise, GNU Stow, 1Password CLI for secrets.
Last major refactor: April 2026. The repo has been around since 2017, but most of the structure here is new.
-
Update macOS to the latest version (App Store or System Settings).
-
Generate an SSH key and add it to GitHub:
curl https://raw.githubusercontent.com/bbohling/dotfiles/HEAD/ssh.sh | sh -s "<your-email-address>"
-
Clone this repo:
git clone git@github.com:bbohling/dotfiles.git ~/.dotfiles -
Run the bootstrap. Idempotent — safe to re-run.
cd ~/.dotfiles ./bootstrap.sh # brew bundle + stow home/ into $HOME ./bootstrap.sh --macos # also apply macOS defaults (reboot after) ./bootstrap.sh --clone # also clone personal repos via clone.sh
-
Open the 1Password app → Settings → Developer → enable "Connect with 1Password CLI", then run
load-secretsin a new shell. See Secrets below. -
Open a fresh terminal. Run
reloadwhenever you want to re-source the shell config (exec zshunder the hood).
~/.dotfiles/
├── home/ GNU Stow package — symlinked into $HOME
│ ├── .zshrc interactive shell config
│ ├── .zshenv env vars + PATH (loaded for every zsh invocation)
│ ├── .gitconfig base git config
│ ├── .gitconfig-work work identity (Intel email + signing key)
│ ├── .gitconfig-personal personal identity
│ ├── .inputrc
│ └── .npmrc gitignored
├── aliases.zsh sourced by .zshrc by absolute path
├── exports.zsh non-PATH shell env (history, kube, etc.)
├── extra.zsh local-only: 1Password-resolved secrets + Intel aliases
├── functions.zsh md/fs/extract
├── starship.toml prompt config (referenced via $STARSHIP_CONFIG)
├── Brewfile brew bundle dependencies
├── .macos curated macOS defaults (~50 settings)
├── bootstrap.sh run this once to set up a new Mac
├── clone.sh, ssh.sh optional helpers
└── .github/workflows/ CI: shellcheck + zsh -n + brew bundle parse
- Shell: plain zsh + 3 brew plugins (
zsh-autosuggestions,zsh-syntax-highlighting,zsh-completions). Replaced oh-my-zsh. - Prompt: starship. Replaced oh-my-posh. Config at
starship.toml(top level, referenced via$STARSHIP_CONFIGset in.zshenv). The file has a "minimal" layout active and a "common additions" layout commented out — swap by toggling two comment lines. - Runtime versions: mise for new projects. Volta is still installed as a fallback for projects with
voltablocks inpackage.json. Migrate per project:cd <project> && mise use node@<version>. - Secrets: 1Password CLI (
op). Secrets resolve from the Private vault at shell startup viaop read. Theextra.zshfile contains references likeop://Private/<item>/credential— never the actual values. - Dotfile deployment: GNU Stow. Files in
home/get symlinked into$HOME. Adding a new home-bound file: drop it inhome/and runstow -t ~ -d ~/.dotfiles home. - Modern CLI:
bat,eza,fzf,ripgrep,zoxide. SeeBrewfile.
Everything under ~/excl/ resolves to the work identity (brandon.bohling@intel.com, work GPG key, Intel HTTPS proxies enabled). Everything under ~/excl/🥃/ overrides back to personal (brandon@bohling.me, personal key, proxies unset). Everything else (e.g., ~/.dotfiles) uses personal as default. Implemented via [includeIf "gitdir:..."] blocks in home/.gitconfig; the override files are home/.gitconfig-work and home/.gitconfig-personal.
extra.zsh declares secret env vars but resolves them at shell startup via op read. Setup:
- Install 1Password desktop app (the cask is in
Brewfile). - Settings → Developer → enable "Connect with 1Password CLI".
- Make sure the relevant items exist in your Private vault. Field defaults to
credential(API Credential template); usepasswordfor Login items. - New shell, then
op whoamishould return your account info instantly. load-secretspopulates the env vars. Verify withenv | grep -E 'OPENAI|LB_TOKEN'.
If op is not signed in, extra.zsh skips silently (won't error). The auto-load is gated on env-vars-not-already-set, so reload/exec zsh inherits the secrets and skips re-probing — only the first shell of the day pays the timeout cost.
reload—exec zsh. Re-source the shell.dotfiles—cd ~/.dotfileswork—cd ~/exclls/ll/la/lt—ezawith--group-directories-first --gitmd <dir>— mkdir -p && cdextract <archive>— universal extractorfs [path]— file or directory sizeload-secrets— pullOPENAI_API_KEY/LB_TOKENfrom 1Password (see Secrets)z <fragment>/zi— zoxide jump / fzf pickerCtrl-R— fzf history searchCtrl-T— fzf file picker
GitHub Actions runs on every push and PR (.github/workflows/ci.yml):
shellcheckonbootstrap.sh,clone.sh,ssh.sh,.macoszsh -nparse check on every*.zshfilebrew bundle listto validateBrewfile
🙆 bob's your uncle 🙆