Personal dotfiles for macOS setup with shell configurations, git settings, and development tools.
- Prerequisites
- Quick Start
- Neovim Setup (Automatic)
- Directory Structure
- What Gets Installed
- Selective Installation
- Manual Installation Steps
- Troubleshooting
- Uninstalling
Before installing these dotfiles, you need:
- macOS - This setup is designed for macOS
- Xcode Command Line Tools - Required for git and other build tools
- Homebrew - Package manager for macOS
- mise - Version manager for tools (neovim, node, ruby, etc.)
- Developer directory - The repo should be cloned to
~/Developer/dotfiles
- 1Password CLI (
op) - Required if you want to use theclaudecommand wrapper for automatic API key loading
If you're setting up a brand new Mac, run the bootstrap script first:
curl -o bootstrap.sh https://raw.githubusercontent.com/YOUR_USERNAME/dotfiles/main/install/bootstrap.sh
bash bootstrap.shThis will install:
- ✅ Xcode Command Line Tools
- ✅ Homebrew
- ✅ mise (version manager)
⚠️ Warns about 1Password CLI (optional)
- Create the Developer directory:
mkdir -p ~/Developer
cd ~/Developer- Clone this repository:
git clone https://github.com/YOUR_USERNAME/dotfiles.git
cd dotfiles- Run the installation script:
bash install/install.sh-
Follow the interactive menu to choose what to install
-
Install version-locked tools with mise:
mise installThis installs: neovim 0.11.5, node 20, ruby 3.4.0, and usage (latest)
- Restart your terminal:
exec zsh- Verify everything is working:
shell-doctorIf you already have the dotfiles installed and want to update:
cd ~/Developer/dotfiles
git pull
bash install/install.shThe Neovim configuration includes fully automatic plugin management. On a fresh machine, when you first launch nvim:
- Packer plugin manager auto-installs (if not present)
- All plugins auto-install via PackerSync
- LSP servers auto-install via Mason (
lua_ls,rust_analyzer,ts_ls) - Treesitter grammars compile automatically (requires
nodefrom mise)
nvimExpected behavior:
- First launch takes 30-60 seconds (plugins installing)
- You may see informational messages about installations
- Some minor errors are normal during initial setup
- Close and reopen nvim after the first launch completes
No manual steps required! Everything installs itself.
The auto-bootstrap is embedded in config/nvim/lua/kerams/packer.lua:
- Checks if Packer exists on startup
- If missing, clones Packer from GitHub
- Automatically runs
PackerSyncto install all plugins - LSPs and Treesitter grammars install on subsequent startup
This makes the Neovim setup completely reproducible on fresh machines without any manual intervention.
dotfiles/
├── config/ # All configuration files
│ ├── git/ # Git configuration and hooks
│ ├── shell/ # Zsh configuration, aliases, functions
│ ├── vim/ # Vim configuration
│ └── nvim/ # Neovim configuration
├── scripts/ # Executable scripts and utilities
│ ├── git/ # Git-related scripts
│ ├── shell/ # Shell functions
│ └── utils/ # General utilities
├── install/ # Installation scripts
│ ├── bootstrap.sh # Prerequisites installer
│ ├── install.sh # Main installer
│ └── lib/
│ ├── helpers.sh # Shared helper functions
│ └── manifest.sh # Single source of truth for all symlinks
├── brew/ # Homebrew configuration
│ └── Brewfile # Homebrew packages list
└── README.md
install/lib/manifest.sh- Defines all config files that should be symlinked. This is the single source of truth used by both the installer andshell-doctorscripts/utils/shell-doctor- Diagnostic tool to verify your setupconfig/shell/.zshenv- Sets up PATH to include all script directoriesconfig/shell/.mise.toml- Version-locked tools managed by mise (neovim, node, etc.)brew/Brewfile- System utilities and GUI apps managed by Homebrew
The dotfiles use a single source of truth approach for easy maintenance:
-
New config file:
- Add file to appropriate
config/subdirectory - Add one line to
install/lib/manifest.sh - Done! Both installer and
shell-doctorwill automatically handle it
- Add file to appropriate
-
New script: Add to appropriate
scripts/subdirectory (automatically in PATH) -
New shell function: Add to
scripts/shell/(one function per file, auto-loaded) -
New Homebrew package: Add to
brew/Brewfile
The manifest file (install/lib/manifest.sh) is the single place where all symlinks are defined. This ensures the installer and diagnostic tool stay in sync automatically.
This dotfiles setup uses a hybrid approach for managing tools:
Tools managed by mise are pinned to specific versions to avoid breaking changes:
- neovim 0.11.5 - Locked to ensure plugin compatibility
- node 20 - Required for nvim-treesitter to compile grammars
- ruby 3.4.0 - Locked to specific version
- usage - Latest version (flexible tool)
Configuration: config/shell/.mise.toml (symlinked to ~/.config/mise/config.toml)
Why mise?
- ✅ Version pinning prevents surprise breakage
- ✅ Reproducible across machines
- ✅ No auto-updates without explicit action
- ✅ Per-project overrides available
- ✅ Essential for nvim-treesitter (needs node to compile)
Tools managed by Homebrew are system utilities and apps that update safely:
- CLI utilities (git, fzf, tree, jq, etc.)
- Libraries (tree-sitter)
- GUI applications (casks)
- Development tools (swiftlint, gh, etc.)
Configuration: brew/Brewfile
Why Homebrew?
- ✅ Best for macOS system integration
- ✅ GUI apps and casks
- ✅ Tools with stable APIs
The installer creates symlinks from your home directory to this repo:
| Config File | Location | Purpose |
|---|---|---|
.zshrc |
config/shell/zshrc |
Main zsh configuration |
.zshenv |
config/shell/zshenv |
Environment variables and PATH |
.p10k.zsh |
config/shell/.p10k.zsh |
Powerlevel10k theme config |
.gitconfig |
config/git/gitconfig |
Main git configuration |
.gitconfig-* |
config/git/ |
Work/personal git configs |
.gitpairs |
config/git/gitpairs |
Pair programming git config |
.gitmessage |
config/git/.gitmessage |
Git commit message template |
.gvimrc |
config/vim/gvimrc |
Vim configuration |
~/.config/nvim |
config/nvim/ |
Neovim configuration |
.macos |
config/shell/.macos |
macOS system defaults |
~/Brewfile |
brew/Brewfile |
Homebrew packages |
All scripts in scripts/ subdirectories are automatically added to your PATH:
Git Scripts (scripts/git/):
git-ui.zsh- Open git repo in Fork.appfuzzy-checkout- Fuzzy find and checkout git branchesfetch-and-merge-origin-main- Fetch and merge from origin/mainlist-authors- List git commit authorspull-push- Pull and push in one commandreset-to-server- Reset local branch to match remote
Shell Functions (scripts/shell/):
anka-connect- Connect to Anka VMarduino-compile/arduino-upload- Arduino development toolscheck-if-vpn- Check VPN connection statusdelete-derived-data- Clean Xcode derived datadelete-gps- Delete iOS GPS simulator datadelete-simulator-cookies- Clear simulator cookiesdiskspace- Show disk usageload-anthropic-key- Load Anthropic API key from 1Password (on-demand)makeSmallVideo- Compress video filesrotate-video/rotate-video-180- Rotate videossearch_code- Search codebaseyoutube-dl-aria2- Download videos with aria2
Utility Scripts (scripts/utils/):
bbpaste- BBEdit clipboard utilitybman- View man pages in BBEditcheck-arm-and-install-rosetta2- Install Rosetta 2 if neededclean-simulator- Clean iOS simulatorclaude- Claude Code wrapper (auto-loads API key from 1Password)shell-doctor- Diagnostic tool to verify dotfiles setupspinner- Display loading spinnerinstall-bbedit-lsp.sh- Install language servers for BBEdit
The Brewfile installs numerous development tools and applications:
Command Line Tools:
asdf- Version manageraria2- Download utilitybat- Better cat with syntax highlightingexa- Modern ls replacementfzf- Fuzzy findergh- GitHub CLIgit-delta- Better git diffsjq- JSON processorswiftlint- Swift lintertree- Directory tree viewerwget- File downloader- And more...
Cask Applications:
xcodes- Xcode version managervisual-studio-code- Code editorkeycastr- Keystroke visualizer
Fonts:
font-meslo-lg-nerd-font- Nerd Font for terminal
Mac App Store:
- BBEdit, DaisyDisk, Keynote, and more (see
brew/Brewfilefor full list)
The installer provides a simple interactive menu:
bash install/install.shOptions:
- Full installation - Everything (configs + brew + macos)
- Configs only - All configuration files and symlinks
- Brew only - Just Homebrew packages
- macOS defaults only - Just apply system preferences
- Verify installation - Check if everything is properly configured
- Exit
The simplified menu gives you control over the two main installation categories (configs vs packages) without overwhelming granularity.
Some applications need to be installed manually as they're not available via Homebrew or the Mac App Store:
- 1Password / 1Password for Safari
- Acorn
- AirBuddy
- Amphetamine
- Bartender 4
- Battery Buddy
- Cardhop
- Discord
- Drafts
- DuckDuckGo Privacy for Safari
- Fantastical
- Firefox
- Itsycal
- Keyboard Maestro
- Kite
- krisp
- MarsEdit
- Micro.blog
- NetNewsWire
- Notchmeister
- Nova
- Proxyman
- QLMarkdown
- Rectangle
- Retrobatch
- Rocket
- SF Symbols
- Slack
- Snk
- Soulver 2 / Soulver 3
- SoundSource
- Tweetbot
- Unexpectedly
- VLC
- WWT Timex
- xScope
After running the installer:
- Powerlevel10k - Run
p10k configureto customize your prompt - Git - Update git configs with your name and email
- Fork.app - Set up
EDITOR_GITpath in.zshenvif you use a different git GUI - iTerm2 - Import your iTerm2 profile if you have one
- BBEdit - Run
install-bbedit-lsp.shfor LSP support (if needed) - SSH Keys - Set up your SSH keys for git authentication
If symlinks fail, you might have existing files:
# Backup existing files
mv ~/.zshrc ~/.zshrc.backup
mv ~/.gitconfig ~/.gitconfig.backup
# Re-run installer
bash install/install.shThe installer automatically backs up existing files with timestamps.
If your shell isn't loading the new configs:
# Restart shell
exec zsh
# Or close and reopen your terminalIf you see errors about missing colorschemes, plugins, or treesitter:
# 1. Ensure mise tools are installed (neovim 0.11.5, node 20)
mise install
# 2. Verify neovim and node are available
which nvim # Should show: ~/.local/share/mise/installs/neovim/...
which node # Should show: ~/.local/share/mise/installs/node/...
# 3. Restart shell to pick up mise shims
exec zsh
# 4. Launch nvim (auto-bootstrap will run if needed)
nvimIf auto-bootstrap doesn't run or errors persist, try the manual steps below.
If auto-bootstrap fails or you want to manually trigger it:
# Open nvim and run PackerSync
nvim
:PackerSync
# Wait for all plugins to install, then restart nvim
:qa
nvimIf Neovim is completely broken or won't start:
# 1. Back up current state (optional)
mv ~/.local/share/nvim ~/.local/share/nvim.backup
mv ~/.cache/nvim ~/.cache/nvim.backup
# 2. Remove all Neovim data and cache
rm -rf ~/.local/share/nvim
rm -rf ~/.cache/nvim
# 3. Restart shell
exec zsh
# 4. Launch nvim (auto-bootstrap will start fresh)
nvim
# Auto-bootstrap will:
# - Install Packer
# - Install all plugins
# - Install LSPs and Treesitter grammars
#
# This may take 30-60 seconds on first launch.
# Close and reopen nvim after it completes.| Error | Cause | Fix |
|---|---|---|
"tree-sitter generate" errors |
Node not found | Run mise install to install node 20 |
"colorscheme 'rose-pine' not found" |
Plugins not installed | Run :PackerSync in nvim |
"module 'harpoon.mark' not found" |
Plugins not installed | Run :PackerSync in nvim |
"lualine" not found |
Plugins not installed | Run :PackerSync in nvim |
LSP not working |
LSP not installed | Run :Mason and press i to install |
deprecation warning about lspconfig |
Known issue with lsp-zero v3.x | Harmless, will be fixed in lsp-zero update |
PackerSync command not found |
Packer not installed | Delete nvim data (see reset steps above) |
To test your Neovim config and see errors without getting stuck in the editor:
# This loads config, prints any errors, and exits immediately
nvim --headless -c 'quitall'If there are no errors, it exits silently. If there are errors, they'll be printed to the terminal. This is perfect for testing after changes or during fresh setup.
You can run any Neovim command from the terminal using --headless mode. This is incredibly useful for automation, troubleshooting, and CI/CD pipelines.
Install/Update All Plugins (PackerSync)
# Run PackerSync and wait for completion before quitting
nvim --headless -c 'autocmd User PackerComplete quitall' -c 'PackerSync'Install Specific LSP Servers
# Install one LSP
nvim --headless -c 'MasonInstall lua_ls' -c 'quitall'
# Install multiple LSPs at once
nvim --headless -c 'MasonInstall lua_ls rust_analyzer ts_ls' -c 'quitall'Update Treesitter Parsers
# Update all treesitter parsers
nvim --headless -c 'TSUpdateSync' -c 'quitall'
# Install specific parser
nvim --headless -c 'TSInstall swift' -c 'quitall'Generate Health Check Report
# Output checkhealth to a file for review
nvim --headless -c 'checkhealth' -c 'write! /tmp/nvim-health.txt' -c 'quitall'
cat /tmp/nvim-health.txt
# Or check specific health (e.g., just LSP or Treesitter)
nvim --headless -c 'checkhealth lsp' -c 'write! /tmp/lsp-health.txt' -c 'quitall'General Pattern
# Basic pattern for any command
nvim --headless -c '<command>' -c 'quitall'
# Alternative shorter syntax
nvim --headless +'<command>' +qa
# Chain multiple commands
nvim --headless -c '<command1>' -c '<command2>' -c 'quitall'Practical Examples
# Full plugin setup from scratch (automated)
nvim --headless -c 'autocmd User PackerComplete quitall' -c 'PackerSync'
nvim --headless -c 'MasonInstall lua_ls rust_analyzer ts_ls' -c 'quitall'
nvim --headless -c 'TSUpdateSync' -c 'quitall'
# Verify setup without opening editor
nvim --headless -c 'checkhealth' -c 'write! /tmp/health.txt' -c 'quitall' && cat /tmp/health.txt
# Test config loads without errors
nvim --headless -c 'quitall' && echo "✓ Config loaded successfully"To diagnose issues, use Neovim's built-in health check:
nvim
:checkhealthThis will show:
- Which LSPs are installed
- Treesitter parser status
- Plugin manager status
- Required dependencies
# Check what mise has installed
mise list
# Should show:
# neovim 0.11.5
# node 20.x.x
# ruby 3.4.0
# usage latest
# Check if they're in PATH
which nvim # Should be mise path, not homebrew
which node # Should be mise pathIf scripts aren't found:
- Check that
.zshenvis symlinked:ls -la ~/.zshenv - Verify PATH in new shell:
echo $PATH - Make sure you restarted your shell after installation
If brew bundle fails with permissions errors:
# Fix Homebrew permissions
sudo chown -R $(whoami) /opt/homebrew/*Use the shell-doctor diagnostic tool:
shell-doctorThis will check:
- All symlinks are correct
- PATH includes script directories
- Environment variables are set
- Key commands are available
- Shell functions are loaded
- Script permissions are correct
Or run the installer's verification option:
bash install/install.sh
# Choose option 5: Verify installationOr use the dedicated diagnostic tool:
shell-doctorIf git configs aren't working:
# Check if files are symlinked
ls -la ~/.gitconfig
# Verify git is reading the config
git config --list --show-originTo remove dotfiles and restore your system:
- Remove symlinks:
rm ~/.zshrc ~/.zshenv ~/.gitconfig ~/.gitconfig-* ~/.p10k.zsh ~/.gvimrc ~/.gitpairs ~/.gitmessage ~/.macos ~/Brewfile
rm -rf ~/.config/nvim- Restore backups if you have them:
mv ~/.zshrc.backup ~/.zshrc
mv ~/.gitconfig.backup ~/.gitconfig-
Remove from PATH by editing
/etc/pathsor removing the dotfiles directory -
Optionally uninstall Homebrew packages:
# This will remove ALL Homebrew packages, not just ones from the Brewfile
# brew bundle cleanup --force --file=~/BrewfilePersonal dotfiles - use at your own discretion.
This is a personal dotfiles repository, but feel free to fork and adapt for your own use!