Personal dotfiles optimized for macOS and zsh. Features modern shell tools, comprehensive git configuration, and a customized development environment.
curl -fsSL https://mise.run | sh
git clone https://github.com/ericboehs/dotfiles ~/Code/github.com/ericboehs/dotfiles
cd ~/Code/github.com/ericboehs/dotfiles && mise trust && mise bootstrapInstall mise from mise.run, not Homebrew. mise bootstraps itself, so it is
deliberately absent from [bootstrap.packages] — whichever copy you install by
hand is the one that runs. Homebrew's build disables mise self-update and
lags upstream, and because it lands in /opt/homebrew/bin instead of
~/.local/bin it papers over a real bug: mise's rubygems plugin shells out to
mise reshim after installing any gem with executables, so mason's gem-backed
packages fail on a mise.run machine unless that directory is on PATH.
Setup is declared in mise.toml rather than scripted, so it
converges — re-running only changes what has drifted. Requires mise 2026.8.4
or newer for the per-package os filters; older versions say so and stop.
Useful variations:
mise bootstrap -n # preview every change, touch nothing
mise bootstrap --only dotfiles # just the $HOME symlinks
mise bootstrap --skip macos-defaults # leave system preferences alone
mise bootstrap dotfiles status # what's linked, and what has driftedDotfile linking is all-or-nothing: if $HOME already has real files where
symlinks belong, mise names them and refuses the whole step. --force-dotfiles
overrides that, but it replaces those files rather than merging them — on a
machine where Homebrew or rbenv had written their own .zprofile, that content
is gone. Move anything you want to keep aside first.
One caveat on convergence: the tools step runs before the bootstrap task,
and a single failed download there — mise resolves runtime versions from
GitHub's releases API, so a GitHub incident is enough — aborts the run before
the task ever starts. The output still reads like a finished bootstrap. If
neovim and tmux look unwarmed, re-run; it picks up where it left off.
Configure git with your personal information:
cp ~/.gitconfig.private.example ~/.gitconfig.private
$EDITOR ~/.gitconfig.private- Prompt: Starship - Fast, customizable prompt
- Syntax highlighting: fast-syntax-highlighting
- Autosuggestions: zsh-autosuggestions
- Smart cd: zoxide - Directory jumper that learns your habits
- Abbreviations: Custom expansion system (see .zsh/abbreviations.zsh)
- Type abbreviation + space/enter to expand
- Extensive git shortcuts (e.g.,
gco→git checkout,gs→git status) - GitHub CLI helpers for PRs and workflow runs
- Notifications: Auto-notify for long-running commands
- Configuration: LazyVim
- Location:
.config/nvim/ - Custom plugins for CSV, Markdown, Tailwind, and GitHub integration
- Prefix:
Ctrl-B(default) - Plugins: vim-tmux-navigator, tmux-yank, tmux-copycat, tmux-floax
- Features:
- Vi-mode copy/paste
- Mouse support
- Activity and bell monitoring
- Custom status line with zoom indicator
- Auto-renumber windows
- Tool: mise (replaces asdf)
- Manages Node.js, Ruby, Python, and other language runtimes
- Also drives machine setup — packages,
$HOMEsymlinks, macOS defaults and git checkouts are all declared in mise.toml and applied withmise bootstrap
- Tool: fzf
- Keybindings:
Ctrl-R: Command history search (with regex support)Ctrl-T: File search
- Enhanced with preview windows and custom options
- Pager: Delta - Syntax-highlighted diffs
- Features:
- GPG signing enabled
- Conditional includes for different organizations
- GitHub CLI credential helpers
- Verbose commits
- Rebase by default for pulls
Enhanced replacements for common commands:
ls→lsd(modern ls with icons and colors)cd→zoxide(smart directory jumping)
Collection of utility scripts in bin/ including:
- Claude Code helpers: claude-man, claude-notify, claude-resume, claude-watcher
- GitHub CLI extensions: gh-pm, gh-reruns, gh-reviews-by-user, gh-labeler, ghb
- Tmux utilities: toggle_notes_pane, monitor_tmux_pane, notes
- Development tools: refresh_safari, colors, true-colors, utcdate
- Throwaway macOS VMs:
vm(see below)
bin/vm wraps tart to give you disposable macOS guests on
Apple Silicon — useful for testing this bootstrap against a genuinely clean
machine.
brew install cirruslabs/cli/tart
vm new # clone a fresh VM named "clean"
vm up # boot it in a GUI window (-d to detach)
vm ssh # shell in as admin, no password
vm reset # wipe it and re-clone — back to pristine, ~3 seconds
vm ls / vm ip / vm down / vm rm / vm seedEvery command takes an optional VM name, so vm new sandbox && vm up sandbox
runs a second one alongside. Defaults come from VM_CPU, VM_MEM, VM_DISK,
VM_NAME, VM_DISPLAY, VM_SSH_KEY, and VM_BASE_OCI.
Two golden images sit behind this and are never booted for day-to-day work.
sequoia-base is the pulled upstream image; sequoia-base-keyed is a clone of
it with your public key appended to authorized_keys, built once by vm seed.
new and reset clone from the keyed image, which is why a reset VM is both
instant and still passwordless — pushing a key per-VM would mean re-injecting it
after every reset. Re-run vm seed after changing VM_SSH_KEY.
Clones are APFS copy-on-write, so a 28GB VM costs almost no disk until it diverges. Treat these as disposable rather than something to repair.
Worth knowing, both imposed by Apple's Virtualization.framework: at most two macOS guests may run at once, and guests cannot sign in to iCloud or the App Store. Anything needing an Apple ID has to be tested on real hardware.
Esc: Enter vi command modeCtrl-Y: Copy current command to clipboardCtrl-R: Fuzzy search command historyCtrl-Alt-L: Clear screen (zsh built-in; prompt only — seeCtrl-Shift-Lfor anything else)
Ctrl-h/j/k/l: Navigate between vim and tmux panesCtrl-Shift-L: Clear screen and scrollbackAlt-h/l: Previous/next windowAlt-j/k: Previous/next session
.
├── .config/nvim/ # Neovim configuration
├── .zsh/ # Zsh configuration modules
│ ├── abbreviations.zsh
│ ├── keybindings.zsh
│ ├── history.zsh
│ └── fzf.zsh
├── bin/ # Utility scripts
├── .gitconfig # Git configuration
├── .tmux.conf # Tmux configuration
├── .zshrc # Zsh initialization
└── mise.toml # Declarative machine setup (`mise bootstrap`)
MIT