Config-driven macOS dotfiles. One file rules everything: edit config.json, run bootstrap.sh.
# 1. Clone (HTTPS if SSH not set up yet)
git clone https://github.com/YOUR_USERNAME/dotfiles.git ~/dotfiles
# 2. Copy example config
cp ~/dotfiles/config.example.json ~/dotfiles/config.json
# 3. Fill in your details
code ~/dotfiles/config.json
# 4. Run bootstrap
bash ~/dotfiles/bootstrap.sh| Field | What to fill in |
|---|---|
git.accounts |
Your GitHub usernames, emails, preferred SSH key names |
node.version |
Specific version like "20", or "lts" for latest LTS |
python.version |
Specific version like "3.11.9", or "latest" |
gcloud.enabled |
true if you use Google Cloud, false otherwise |
brew.packages.extras |
Any brew packages beyond the defaults |
brew.casks.extras |
Any brew casks beyond the defaults |
npm_globals.packages |
e.g. ["@anthropic-ai/claude-code", "typescript"] |
pip_globals.packages |
e.g. ["playwright", "black"] |
mas.apps |
Mac App Store apps with their IDs |
manual_installs |
Anything that can't be automated — shown in final checklist |
aliases.custom |
Your own shell aliases |
- Add an entry to
git.accountsinconfig.json - Run:
bash install/ssh.sh && bash generate/ssh_config.sh && bash generate/zshrc.sh && bash symlink.sh
- Change the version in
config.json - Run:
bash install/node.shorbash install/python.sh
bash generate/zshrc.sh
bash generate/gitconfig.sh
bash generate/ssh_config.sh
bash symlink.shconfig.json is the single source of truth. Every script reads from it via jq. Nothing is hardcoded in any script.
config.json → generate/*.sh → config/ → symlink.sh → ~/.zshrc, ~/.gitconfig, etc.
install/*.sh (brew, node, python, gcloud, ssh)
The config/ directory is auto-generated — never edit those files directly.
git clone git@github.com-personal:YOUR_USERNAME/dotfiles.git ~/dotfiles
cd ~/dotfiles
bash bootstrap.shAdd to brew.packages.extras in config.json, then:
bash bootstrap.sh --only=brewEdit node.version in config.json, then:
bash bootstrap.sh --only=nodeUse "lts" or "latest" to auto-resolve.
Edit python.version in config.json, then:
bash bootstrap.sh --only=pythonUse "latest" to auto-resolve to the latest 3.x.
Add an entry to git.accounts in config.json:
{
"name": "YourGitHubUsername",
"email": "you@example.com",
"host_alias": "github.com-work",
"key_name": "id_ed25519_work",
"default": false
}Then re-run:
bash bootstrap.shThis will generate the SSH key, update ~/.ssh/config, and print the public key to add to GitHub.
Add to aliases.custom in config.json:
"custom": {
"myalias": "some command"
}Then regenerate:
bash generate/zshrc.sh && bash symlink.shAfter setup, switch identity per-repo:
cd ~/work/some-repo
git-work # sets user.name + user.email to work accountcd ~/personal/some-repo
git-personal # sets user.name + user.email to personal accountUse the host alias instead of github.com:
# Personal account
git clone git@github.com-personal:YOUR_PERSONAL_USERNAME/repo.git
# Work account
git clone git@github.com-work:YOUR_WORK_USERNAME/repo.gitbash bootstrap.sh --only=brew
bash bootstrap.sh --only=node
bash bootstrap.sh --only=python
bash bootstrap.sh --only=gcloud
bash bootstrap.sh --only=sshbash generate/zshrc.sh && bash symlink.sh
bash generate/gitconfig.sh && bash symlink.sh
bash generate/ssh_config.sh && bash symlink.shOr all at once:
bash generate/zshrc.sh && bash generate/gitconfig.sh && bash generate/ssh_config.sh && bash symlink.shFor each SSH key, copy its public key and add it to the corresponding GitHub account:
# Personal account key
cat ~/.ssh/id_ed25519_personal.pub
# → Add at: https://github.com/settings/ssh/new (logged in as your personal account)
# Work account key
cat ~/.ssh/id_ed25519_work.pub
# → Add at: https://github.com/settings/ssh/new (logged in as your work account)Test connections:
ssh -T git@github.com-personal
ssh -T git@github.com-work| File | Purpose |
|---|---|
config.json |
Single source of truth — edit this |
bootstrap.sh |
Full setup entry point |
symlink.sh |
Creates symlinks from config/ to ~/ |
install/brew.sh |
Installs brew packages and casks |
install/node.sh |
Installs nvm + Node.js |
install/python.sh |
Installs pyenv + Python |
install/gcloud.sh |
Installs Google Cloud SDK |
install/ssh.sh |
Generates SSH keys for each git account |
generate/zshrc.sh |
Generates config/.zshrc |
generate/gitconfig.sh |
Generates config/.gitconfig + config/.gitignore_global |
generate/ssh_config.sh |
Generates config/.ssh/config |
config/ |
Auto-generated — do not edit manually |