Personal dotfiles for macOS. Configuration for zsh, neovim, git, tmux, and various CLI tools.
Note: These are my personal dotfiles. Feel free to read and take inspiration, but make your own edits - there's a lot of me-specific configuration here.
# Clone to home directory
git clone https://github.com/chetmancini/dotfiles.git ~/dotfiles
# Run install scriptcd~/dotfiles
./install.sh --plan
./install.sh
# Verify the installed state
doctor| Tool | Config | Description |
|---|---|---|
| zsh | .zshrc + zsh/ | Modular shell (aliases, functions, tools) |
| neovim | nvim/ | Modular config (vim.pack + plugin/*.lua) |
| git | .gitconfig | Aliases, delta pager, conventional commits |
| tmux | .tmux.conf | Terminal multiplexer |
| yazi | yazi/ | File browser |
| ghostty | ghostty/ | Terminal emulator |
Packages are split into core and optional profiles:
| File | Purpose | Default install |
|---|---|---|
Brewfile | Daily CLI, languages, k8s, Ghostty, fonts | Yes (install.sh / brew bundle) |
Brewfile.optional | AI IDEs, messaging, heavy casks, fun extras | Opt-in |
# Core (default)
brew bundle --file=~/dotfiles/Brewfile
brew bundle check --file=~/dotfiles/Brewfile
# Optional apps/tools
brew bundle --file=~/dotfiles/Brewfile.optional
# Via install.sh
./install.sh --yes --skip-brew # no brew
./install.sh --with-optional-brew # core + optional
./install.sh --with-legacy-vim # also symlink legacy Vim# Drift against core only (optional packages ignored as "extras")
brew-sync- CLI Tools: eza, bat, fzf, zoxide, atuin, direnv, jq, htop, yazi, shellcheck, shfmt
- Development: neovim, gh, git-delta, awscli, mise
- Kubernetes: kubectl, kubectx, k9s, helm
- Languages: Mise (Node/Python runtimes), OpenJDK, Bun, uv, pnpm
- Databases: postgresql, redis, sqlite
- Apps: Ghostty, 1Password CLI
- Fonts: Monaspace, Hack (+ Nerd Font variants)
Optional includes AI apps (Claude, Cursor, Zed, …), messaging, Adobe, MacTeX, etc.
- Thin
.zshrcorchestrator sourcing modules underzsh/ - Custom theme with git status (
chetmancini.zsh-theme) - Homebrew zsh plugins: autosuggestions, history-substring-search, syntax-highlighting
- Vi mode with visual cursor indicator
- mise for Node/Python versions (see
mise/config.toml); uv / pnpm / bun for packages - zoxide for smart directory jumping
- fzf integration for fuzzy finding (Ctrl-T files, Alt-C dirs)
- atuin for shell history search (Ctrl-R); up-arrow stays history-substring
- direnv for per-project env (
.envrc+direnv allow; never commit secrets)
install.shsupports interactive, preview, and headless installs (--plan,--yes,--skip-brew,--with-optional-brew,--with-legacy-vim, etc.)doctorverifies core symlinks, zsh modules, TPM, and repo health checks (legacy Vim not required)statusprovides fast, unified health checks across symlinks, repos, and Homebrew drift (dot status/dot status --deep)dotdispatchesbin/tools (dot help,dot status,dot doctor,dot brew-sync, …); scripts also stay on PATHdocs/package-managers.mddefines the preferred owner for runtimes, native apps, and global JavaScript CLIs; usepackage-sync --updateto refresh npm and pnpm globals- GitHub Actions smoke-tests the installer and doctor in a temporary
HOME make formatformats shell scripts withshfmt;make checkruns formatting, syntax, ShellCheck, TOML, zsh checks, and bats tests (tests/)
- Preferred: copy
api_keys_1password.sh.template→api_keys_1password.sh(gitignored), setop://item refs viaop_secret - Install 1Password CLI (
1password-clicask), enable app Settings → Developer → Integrate with 1Password CLI, unlock the app, checkop whoami - Bootstrap only:
api_keys.shfromapi_keys.sh.templatefor machines without 1Password - Shell loads plaintext first, then 1Password (so 1P can override during migration) — see
zsh/secrets.zsh - Never commit real keys; never put secrets in tracked templates
- Conventional commit aliases:
git cc <type>,git feat,git fix,git chore, etc. - Conditional includes for work vs personal repos
- git-delta for beautiful diffs
gs # git status -sb
ll # eza with icons and git status
vi # neovim
y # yazi file browser (with cd on exit)cd# zoxide (smart directory jumping)
fzfp # fzf with bat preview- Daily CLI →
Brewfile; experimental/GUI apps →Brewfile.optional - Run
brew bundle --file=…for the right profile - If config needed, add symlink to
bin/lib/symlinks.sh(+ install/doctor) - Add any shell integration under
zsh/(and one line in.zshrcif a new module)
See docs/package-managers.md before choosing an installer. One executable should have one preferred owner.
~/dotfiles/
├── .zshrc # Thin shell orchestrator
├── zsh/ # Modular shell config (aliases, tools, plugins)
├── .gitconfig # Git config (uses conditional includes)
├── .tmux.conf # tmux config
├── Brewfile # Core Homebrew packages
├── Brewfile.optional # Optional apps/tools (opt-in)
├── install.sh # Setup script
├── chetmancini.zsh-theme # Custom λ theme
├── bin/ # Custom scripts + `dot` (see bin/README.md)
├── nvim/ # Neovim (vim.pack + plugin/*.lua)
├── atuin/ # Atuin history config
├── vim/ # Legacy Vim runtime (not installed by default)
├── iterm/ # Legacy iTerm prefs (Ghostty is primary)
├── yazi/ # Yazi file browser
├── ghostty/ # Ghostty terminal
├── claude/ # Claude Code agents & commands (see docs/agents.md)
├── mcp.json.example # MCP servers example (copy to mcp.json, gitignored)
├── plans/ # Implementation plans
├── docs/ # Extended documentation
├── api_keys_1password.sh.template # Preferred secrets template
├── api_keys.sh.template # Bootstrap plaintext template
└── api_keys*.sh # Live secrets (gitignored)
Legacy: vim/ and iterm/ remain in the repo for reference but are not required. Primary stack is Ghostty + Neovim. Pass --with-legacy-vim to symlink Vim config.
MIT - do whatever you want with it.
-Chet