-
-
Save denniswon/584283a34ef44f493d297c153bede47e to your computer and use it in GitHub Desktop.
| MacBook migration is a surprisingly deep problem — it's not just copying files. You have layered state: dotfiles, package managers, | |
| language runtimes, auth tokens (which can't just be copied), MCP server configs, IDE state, and agent memories scattered across | |
| ~/.claude/, ~/.config/, keychains, and more. Getting this right upfront saves days of "why doesn't X work on my new machine." | |
| ★ Insight ───────────────────────────────────── | |
| Your environment is substantial — 176 Homebrew formulae, 74 casks, 5 language version managers, blockchain toolchains (Foundry, SP1, | |
| RISC0), Claude Code with 9 plugins, 6 MCP servers, and API keys hardcoded in .zshrc. The biggest risk areas are: (1) secrets | |
| management (API keys in plaintext), (2) auth tokens that can't be copied (need re-auth), and (3) the order of installation (version | |
| managers before languages before tools). | |
| ───────────────────────────────────────────────── | |
| Great — I've done a thorough audit of your current machine. Here's what I found at a high level: | |
| Current Environment Summary | |
| ┌─────────────────┬──────────────────────────────────────────────────────────────────────────────────────┐ | |
| │ Category │ What's There │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Shell │ Zsh + Zprezto (wikimatze theme), 5 config files, extensive aliases │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Terminal │ WezTerm with custom Lua config │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Git │ 65+ custom aliases, delta pager, LFS, interactive rebase tool │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Package Manager │ Homebrew: 176 formulae + 74 casks (no Brewfile exists yet) │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Languages │ fnm (Node), pyenv (Python), rbenv (Ruby), rustup (Rust + ZK toolchains), Go (system) │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Blockchain/ZK │ Foundry, SP1, RISC0, Wasmer, Circom │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Claude Code │ 9 plugins (OMC, superpowers, supermemory, etc.), 6 MCP servers, custom HUD │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ IDEs │ Cursor (primary), Windsurf, VS Code Insiders │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Cloud │ gcloud SDK, Azure CLI, GitHub CLI, Granted (AWS) │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Keys/Auth │ SSH (ed25519 + GCP + PEM keys), 1Password integration │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Secrets │ ~12 API keys hardcoded in .zshrc │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Dotfile mgmt │ stow installed but not configured; no active dotfile repo │ | |
| ├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤ | |
| │ Projects │ ~15 repos in ~/projects/, plus ~/magic/ │ | |
| └─────────────────┴──────────────────────────────────────────────────────────────────────────────────────┘ |
MacBook Migration Design Spec
Date: 2026-03-18
Goal: Migrate full development environment from MacBook Pro (M1 Pro, 16GB) to MacBook Pro (M1 Max, 64GB, 16") using a hybrid approach — Migration Assistant for macOS layer, manual scripted setup for dev tools.
Strategy: Hybrid Migration
- Migration Assistant handles: macOS preferences, apps, documents, 1Password, Raycast, Karabiner, Keychain
- Scripted setup handles: Homebrew, shell, language runtimes, Claude Code, blockchain toolchains
- rsync handles: project repositories with full git state
Phase 1: Prepare Old Machine
All preparation happens before powering on the new machine.
1a. Generate Brewfile
brew bundle dump --file=~/.dotfiles/homebrew/Brewfile --forceCaptures all 176 formulae + 74 casks. Review and remove anything no longer needed. Ensure vfox is included (it's sourced in .zshrc).
1b. Split Secrets from .zshrc
Before committing dotfiles, extract API keys into a separate file that will NOT be version-controlled:
# Create ~/.zsh_secrets with all API key exports
# Move these lines from .zshrc into .zsh_secrets:
# RECALL_API_KEY, RECALL_REDIS_URL, ANTHROPIC_API_KEY, OPENAI_API_KEY,
# XAI_API_KEY, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, SUPERMEMORY_CC_API_KEY,
# SUPERMEMORY_OPENCLAW_API_KEY, GITHUB_PERSONAL_ACCESS_TOKEN, DD_API_KEY, DD_APP_KEY
# Add this line to .zshrc where the keys used to be:
# [[ -f ~/.zsh_secrets ]] && source ~/.zsh_secretsTransfer ~/.zsh_secrets via AirDrop alongside SSH keys on migration day. This file is never committed to git.
1c. Create Dotfiles Repo with GNU Stow
Directory structure:
~/.dotfiles/
.gitignore # Excludes .zsh_secrets, SSH private keys, *.pem
zsh/
.zshrc
.zpreztorc
.zprofile
.zshenv
.zlogin
.zfunc/ # Custom completion functions (if any exist)
git/
.gitconfig
wezterm/
.wezterm.lua
ssh/
.ssh/config
.ssh/azure_known_hosts
.ssh/google_compute_known_hosts
karabiner/
.config/karabiner/karabiner.json
claude/
.claude/CLAUDE.md
.claude/settings.json
.claude/settings.local.json (if exists)
.claude/projects/ (entire directory)
.claude/agents/ (entire directory)
.claude/commands/ (entire directory)
.claude/skills/ (entire directory)
.claude/plugins/ (entire directory minus cache/)
.claude/hud/ (entire directory)
.claude/recall-mcp-setup.md
.claude/recall-proxy.mjs
bin/
bin/sync-claude.sh
bin/pull-claude.sh
bin/smart-sync-claude.sh
bin/vim # Wrapper script (document what it points to)
gh/
.config/gh/config.yml
.config/gh/hosts.yml
.gitignore contents:
.zsh_secrets
*.pem
id_*
google_compute_engine
google_compute_engine.pub
Commands:
cd ~
mkdir -p ~/.dotfiles
cd ~/.dotfiles
git init
# Create stow package directories and move files
# (setup script will automate this)
git remote add origin git@github.com:dennis-won/dotfiles.git # MUST be private repo
git add -A && git commit -m "Initial dotfiles snapshot for migration"
git push -u origin main1d. Export Language Runtime State
Create ~/.dotfiles/setup/language-versions.sh:
#!/bin/bash
mkdir -p ~/.dotfiles/setup
# Node.js (fnm)
fnm list > ~/.dotfiles/setup/node-versions.txt
fnm default # record default
npm list -g --depth=0 > ~/.dotfiles/setup/node-globals.txt
# Python (pyenv)
pyenv versions > ~/.dotfiles/setup/python-versions.txt
pipx list --short > ~/.dotfiles/setup/pipx-packages.txt
# Ruby (rbenv)
rbenv versions > ~/.dotfiles/setup/ruby-versions.txt
# Rust (rustup)
rustup toolchain list > ~/.dotfiles/setup/rust-toolchains.txt
cargo install --list > ~/.dotfiles/setup/cargo-packages.txt
# Go
go version > ~/.dotfiles/setup/go-version.txt1e. Clean Up Known .zshrc Issues
Before committing, fix these pre-existing issues in .zshrc:
-
Duplicate LDFLAGS/CPPFLAGS: Lines for postgresql@16 are overwritten by llvm. Combine them:
export LDFLAGS="-L/opt/homebrew/opt/postgresql@16/lib -L/opt/homebrew/opt/llvm/lib" export CPPFLAGS="-I/opt/homebrew/opt/postgresql@16/include -I/opt/homebrew/opt/llvm/include"
-
Duplicate Windsurf PATH entries: Lines 270 and 296 are identical. Remove one.
1f. Claude Code Snapshot
Key files/directories to preserve:
| Path | Contains | Priority |
|---|---|---|
~/.claude/CLAUDE.md |
OMC configuration | Critical |
~/.claude/settings.json |
Permissions, MCP servers, plugins | Critical |
~/.claude/projects/ |
Per-project CLAUDE.md, memory | Critical |
~/.claude/plugins/ |
Plugin manifests (not cache) | Critical |
~/.claude/agents/ |
Custom agent definitions | High |
~/.claude/commands/ |
Custom slash commands | High |
~/.claude/skills/ |
Custom skills | High |
~/.claude/hud/ |
HUD config + omc-hud.mjs | High |
~/.claude/recall-proxy.mjs |
Custom MCP proxy | High |
~/.claude/recall-mcp-setup.md |
MCP setup notes | Medium |
Exclude from dotfiles (ephemeral/regenerated):
~/.claude/cache/~/.claude/sessions/~/.claude/session-env/~/.claude/debug/~/.claude/file-history/~/.claude/paste-cache/~/.claude/shell-snapshots/~/.claude/telemetry/~/.claude/todos/~/.claude/tasks/~/.claude/history.jsonl~/.claude/mcp-refresh-*.lock~/.claude/plugins/cache/(plugins re-download on install)
Phase 2: Migration Assistant
Power on the new MacBook. During initial setup, choose "Transfer from another Mac" (Thunderbolt cable or Wi-Fi).
What it migrates:
- macOS system preferences (Dock, keyboard, trackpad, display, accessibility)
- Application binaries (Cursor, Windsurf, 1Password, Raycast, Docker Desktop, etc.)
- Documents, Photos, Desktop, Downloads
- 1Password vault (syncs via cloud, but app prefs transfer)
- Karabiner-Elements app (config handled by stow in Phase 3)
- Keychain (Wi-Fi passwords, certificates, web passwords)
- Raycast extensions and configuration
- iTerm2 settings
- Font files (Nerd Fonts)
What it does NOT reliably migrate (handled in Phase 3):
- Homebrew (
/opt/homebrew/— symlinks and cellar can break) - Shell configs (handled by stow)
- Language version managers and their installed versions
- Claude Code CLI and configuration
- Blockchain toolchains (Foundry, SP1, RISC0)
- SSH private keys (handle separately via secure transfer)
After Migration Assistant completes:
- Verify macOS apps launch
- Verify 1Password unlocks
- Verify Raycast works
- Check what Migration Assistant copied to Homebrew path:
ls /opt/homebrew/ # inspect before removing - Back up then remove Homebrew remnants (start fresh):
sudo mv /opt/homebrew /opt/homebrew.bak # safe backup # Delete after Phase 3 succeeds: sudo rm -rf /opt/homebrew.bak
Phase 3: Dev Environment Setup (New Machine)
Step 1: Xcode Command Line Tools
xcode-select --installStep 2: Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv)"Step 3: Install Homebrew Packages
brew bundle install --file=~/.dotfiles/homebrew/BrewfileThis installs: stow, fnm, pyenv, rbenv, direnv, fzf, git-delta, colorls, gh, azure-cli, docker (CLI), ffmpeg, buf, vfox, and all 74 casks.
Step 4: SSH Keys
Transfer securely via AirDrop (keys only — NOT ~/.ssh/config, which stow handles):
~/.ssh/id_ed25519+~/.ssh/id_ed25519.pub~/.ssh/google_compute_engine+~/.ssh/google_compute_engine.pub~/.ssh/newton.pem~/.ssh/tdx-prover-temp.pem
Also AirDrop ~/.zsh_secrets at the same time.
# After transfer, fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 600 ~/.ssh/google_compute_engine
chmod 600 ~/.ssh/newton.pem
chmod 600 ~/.ssh/tdx-prover-temp.pem
chmod 644 ~/.ssh/*.pubNote: ~/.ssh/1Password/ directory is created automatically by 1Password app — do not transfer manually.
Step 5: Clone Dotfiles and Stow
git clone git@github.com:dennis-won/dotfiles.git ~/.dotfiles
cd ~/.dotfiles
stow zsh git wezterm ssh karabiner claude bin ghThis symlinks all config files into their correct home directory locations.
Post-stow verification — check hardcoded paths:
# Verify SSH config paths match new machine's home directory
grep '/Users/' ~/.ssh/config
# If username differs, update paths accordinglyStep 6: Install Zprezto
git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"The rc files (.zpreztorc, .zlogin) are already symlinked from stow. Restart shell.
Step 7: Install Language Runtimes
# Node.js
fnm install 22.22.0
fnm default 22.22.0
fnm install 20.10.0
fnm install 24.11.1
# Python
pyenv install 3.13.11
pyenv global 3.13.11
# Ruby
rbenv install 3.3.5
rbenv global 3.3.5
# Rust (already installed via Homebrew rustup-init)
rustup-init -y
rustup toolchain install stable
rustup toolchain install nightly
# Specialized toolchains — reference exported list:
# cat ~/.dotfiles/setup/rust-toolchains.txt
# rustup toolchain install <specific versions as needed>Step 8: Install Global Packages
# Node globals
npm install -g openclaw corepack
# Enable pnpm via corepack (referenced in .zshrc)
corepack enable
# Generate OpenClaw completions
mkdir -p ~/.openclaw/completions
openclaw completions zsh > ~/.openclaw/completions/openclaw.zsh
# Python tools via pipx
pipx install poetry
pipx install jupyter-lab
pipx install towncrier
# Cargo tools — install from exported list for accuracy:
cat ~/.dotfiles/setup/cargo-packages.txt | awk '{print $1}' | xargs cargo install
# Or manually:
# cargo install cargo-edit cargo-pgrx cargo-shear circom cocogitto cross just svm-rs sqlx-cliStep 9: Install Blockchain Toolchains
# Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# SP1
curl -L https://sp1.succinct.xyz | bash
sp1up
# RISC0
curl -L https://risczero.com/install | bash
rzup install
# Wasmer
curl https://get.wasmer.io -sSfL | shNote: Any Wasmer packages installed on the old machine will need to be reinstalled separately.
Step 10: Install Claude Code
# Install Claude Code CLI
curl -fsSL https://claude.ai/install.sh | sh
# Verify stow placed configs correctly
ls -la ~/.claude/CLAUDE.md
ls -la ~/.claude/settings.json
# Install plugins (they'll re-download to cache)
claude plugins install oh-my-claudecode
claude plugins install superpowers
claude plugins install claude-supermemory
claude plugins install claude-md-management
claude plugins install claude-code-setup
claude plugins install plugin-dev
claude plugins install skill-creator
claude plugins install learning-output-style
claude plugins install rust-analyzer-lsp
# Verify MCP servers connect
claude mcp listStep 11: Google Cloud SDK
The SDK is installed at ~/google-cloud-sdk/ (standalone installer, not Homebrew). This requires a full reinstall on the new machine:
curl https://sdk.cloud.google.com | bash
# Restart shell, then:
gcloud init
gcloud auth login
gcloud auth application-default loginThe .zshrc already sources from ~/google-cloud-sdk/ — the fresh install creates this directory.
Step 12: Re-Authenticate Services
| Service | Command |
|---|---|
| GitHub CLI | gh auth login |
| Azure CLI | az login |
| Docker Hub | docker login |
| Google Cloud | gcloud auth login |
| Slack MCP | Re-OAuth via Claude Code |
| Anthropic API | Key already in ~/.zsh_secrets |
| OpenAI API | Key already in ~/.zsh_secrets |
Phase 4: rsync Projects
Connect both machines to the same network. On the old machine, enable Remote Login (System Settings > General > Sharing > Remote Login).
From the new machine:
# Find old machine's IP
# On old machine: ifconfig | grep "inet " | grep -v 127.0.0.1
rsync -aH --progress dennis.won@<OLD_IP>:~/projects/ ~/projects/
rsync -aH --progress dennis.won@<OLD_IP>:~/magic/ ~/magic/
rsync -aH --progress dennis.won@<OLD_IP>:~/go/ ~/go/
rsync -aH --progress dennis.won@<OLD_IP>:~/google-cloud-sdk/ ~/google-cloud-sdk/ # optional: skip if doing fresh gcloud installFlags:
-aarchive mode (preserves permissions, timestamps, symlinks)-Hpreserve hard links--progressshow transfer progress
Note: -A (ACLs) and -X (xattrs) flags omitted — they produce warnings on macOS and are not needed for development files. Extended attributes that matter (like Finder tags) are handled by Migration Assistant.
Phase 5: Verification Checklist
| Check | Command | Expected |
|---|---|---|
| Shell prompt | Open new terminal | Zprezto wikimatze theme renders |
| Zsh aliases | type cpush |
Shows alias definition |
| Secrets loaded | echo $ANTHROPIC_API_KEY |
Key value (from ~/.zsh_secrets) |
| Node.js | node -v |
v22.22.0 |
| pnpm | pnpm --version |
Version string |
| Python | python --version |
3.13.11 |
| Ruby | ruby -v |
3.3.5 |
| Rust | rustc --version |
stable |
| Go | go version |
1.23.1+ |
| vfox | vfox --version |
Version string |
| Git | git config user.email |
jhwon0820@gmail.com |
| Git delta | git log --oneline -5 (in any repo) |
Colored delta output |
| SSH | ssh -T git@github.com |
"Hi dennis-won!" |
| Foundry | forge --version |
Version string |
| Claude Code | claude --version |
2.x |
| Claude MCP | claude mcp list |
6 servers listed |
| Claude plugins | claude plugins list |
9 plugins |
| WezTerm | Open WezTerm | Custom config loads |
| Windsurf CLI | windsurf --version |
Version string |
| Karabiner | Check remappings | Active |
| Docker | docker --version |
29.x |
| Docker completions | ls ~/.docker/completions/ |
Completion files exist |
| GitHub CLI | gh auth status |
Authenticated |
| direnv | cd into a project with .envrc |
Loads environment |
| OpenClaw completions | ls ~/.openclaw/completions/ |
openclaw.zsh exists |
Security Notes
- API keys extracted from
.zshrcinto~/.zsh_secrets(not committed to git) ~/.zsh_secretstransferred via AirDrop (same secure channel as SSH keys)- SSH private keys must be transferred via secure channel (AirDrop or 1Password)
- Never commit SSH private keys or API keys to the dotfiles repo
- The dotfiles GitHub repo MUST be private
.dotfiles/.gitignoreexcludes:*.pem,id_*,google_compute_engine*,.zsh_secrets
Estimated Time
| Phase | Duration |
|---|---|
| Phase 1: Prepare old machine | 30-60 min |
| Phase 2: Migration Assistant | 1-3 hours (depends on data size) |
| Phase 3: Dev environment setup | 1-2 hours (mostly waiting for installs) |
| Phase 4: rsync projects | 30-60 min (depends on network speed) |
| Phase 5: Verification | 20-30 min |
| Total | 3-7 hours |
Post-Migration Cleanup
After verifying everything works on the new machine:
# Remove Homebrew backup from Phase 2
sudo rm -rf /opt/homebrew.bakRollback
The old machine remains untouched throughout. If anything goes wrong on the new machine:
- Old machine is still fully functional
- Dotfiles repo preserves all configs
- Can re-run any phase independently
MacBook Migration Implementation Plan
For agentic workers: This is a system administration runbook, not a code implementation plan. Steps are shell commands executed across two physical machines. Use superpowers:executing-plans to track progress. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Migrate full development environment from MacBook Pro (M1 Pro, 16GB) to MacBook Pro (M1 Max, 64GB, 16") with zero data loss and a working dev environment on day one.
Architecture: Hybrid approach — Migration Assistant for macOS layer (apps, prefs, documents), scripted Homebrew + stow for dev tools, rsync for project repos.
Spec: docs/superpowers/specs/2026-03-18-macbook-migration-design.md
Phase 1: Prepare Old Machine
All tasks in Phase 1 run on the current (old) MacBook.
Task 1: Generate Brewfile
Machine: Old MacBook
Files:
-
Create:
~/.dotfiles/homebrew/Brewfile -
Step 1: Create dotfiles directory structure
mkdir -p ~/.dotfiles/homebrew
mkdir -p ~/.dotfiles/setup- Step 2: Dump current Homebrew state
brew bundle dump --file=~/.dotfiles/homebrew/Brewfile --forceExpected: File created with brew, cask, and tap entries.
- Step 3: Verify Brewfile contents
wc -l ~/.dotfiles/homebrew/Brewfile
grep -c '^brew' ~/.dotfiles/homebrew/Brewfile
grep -c '^cask' ~/.dotfiles/homebrew/BrewfileExpected: ~250+ lines, ~176 brew entries, ~74 cask entries.
- Step 4: Verify vfox is included
grep 'vfox' ~/.dotfiles/homebrew/BrewfileExpected: A line with brew "vfox" or similar. If missing, add it manually:
echo 'brew "vfox"' >> ~/.dotfiles/homebrew/Brewfile- Step 5: Review and trim Brewfile (optional)
Open in editor and remove any packages you no longer use:
cursor ~/.dotfiles/homebrew/BrewfileTask 2: Split Secrets from .zshrc
Machine: Old MacBook
Files:
-
Create:
~/.zsh_secrets -
Modify:
~/.zshrc -
Step 1: Identify all secret exports in .zshrc
grep -n 'export.*\(API_KEY\|TOKEN\|SECRET\|REDIS_URL\|DD_APP\)' ~/.zshrcExpected: ~12 lines with API keys, tokens, and secrets.
- Step 2: Create ~/.zsh_secrets with the secret exports
Extract all secret lines from .zshrc into ~/.zsh_secrets. The file should look like:
# API Keys and Secrets - DO NOT COMMIT TO GIT
export RECALL_API_KEY="..."
export RECALL_REDIS_URL="..."
export ANTHROPIC_API_KEY="..."
export OPENAI_API_KEY="..."
export XAI_API_KEY="..."
export TELEGRAM_BOT_TOKEN="..."
export TELEGRAM_CHAT_ID="..."
export SUPERMEMORY_CC_API_KEY="..."
export SUPERMEMORY_OPENCLAW_API_KEY="..."
export GITHUB_PERSONAL_ACCESS_TOKEN="..."
export DD_API_KEY="..."
export DD_APP_KEY="..."- Step 3: Replace secret lines in .zshrc with source command
Remove the individual export lines from .zshrc and add this in their place:
# Secrets (not version-controlled)
[[ -f ~/.zsh_secrets ]] && source ~/.zsh_secrets- Step 4: Verify shell still works
source ~/.zshrc
echo $ANTHROPIC_API_KEY # should print the key valueExpected: Key prints correctly, no errors on source.
Task 3: Fix Known .zshrc Issues
Machine: Old MacBook
Files:
-
Modify:
~/.zshrc -
Step 1: Fix duplicate LDFLAGS/CPPFLAGS
Find the two conflicting sets (postgresql@16 and llvm) and combine them into one:
export LDFLAGS="-L/opt/homebrew/opt/postgresql@16/lib -L/opt/homebrew/opt/llvm/lib"
export CPPFLAGS="-I/opt/homebrew/opt/postgresql@16/include -I/opt/homebrew/opt/llvm/include"- Step 2: Remove duplicate Windsurf PATH entry
Find and remove one of the two identical lines adding ~/.codeium/windsurf/bin to PATH.
- Step 3: Verify shell still loads cleanly
source ~/.zshrcExpected: No errors.
Task 4: Create Dotfiles Repo with Stow
Machine: Old MacBook
Files:
-
Create:
~/.dotfiles/(entire stow structure) -
Step 1: Initialize git repo
cd ~/.dotfiles
git init- Step 2: Create .gitignore
cat > ~/.dotfiles/.gitignore << 'EOF'
.zsh_secrets
*.pem
id_*
google_compute_engine
google_compute_engine.pub
.DS_Store
EOF- Step 3: Create stow package directories
mkdir -p ~/.dotfiles/zsh
mkdir -p ~/.dotfiles/git
mkdir -p ~/.dotfiles/wezterm
mkdir -p ~/.dotfiles/ssh/.ssh
mkdir -p ~/.dotfiles/karabiner/.config/karabiner
mkdir -p ~/.dotfiles/claude/.claude
mkdir -p ~/.dotfiles/bin/bin
mkdir -p ~/.dotfiles/gh/.config/gh- Step 4: Copy zsh files into stow package
cp ~/.zshrc ~/.dotfiles/zsh/
cp ~/.zpreztorc ~/.dotfiles/zsh/
cp ~/.zprofile ~/.dotfiles/zsh/
cp ~/.zshenv ~/.dotfiles/zsh/
cp ~/.zlogin ~/.dotfiles/zsh/
# Copy .zfunc if it exists
[ -d ~/.zfunc ] && cp -r ~/.zfunc ~/.dotfiles/zsh/- Step 5: Copy git config
cp ~/.gitconfig ~/.dotfiles/git/- Step 6: Copy WezTerm config
cp ~/.wezterm.lua ~/.dotfiles/wezterm/- Step 7: Copy SSH config (not private keys)
cp ~/.ssh/config ~/.dotfiles/ssh/.ssh/
cp ~/.ssh/azure_known_hosts ~/.dotfiles/ssh/.ssh/
cp ~/.ssh/google_compute_known_hosts ~/.dotfiles/ssh/.ssh/- Step 8: Copy Karabiner config
cp ~/.config/karabiner/karabiner.json ~/.dotfiles/karabiner/.config/karabiner/- Step 9: Copy Claude Code config (excluding ephemeral files)
# Core config files
cp ~/.claude/CLAUDE.md ~/.dotfiles/claude/.claude/
cp ~/.claude/settings.json ~/.dotfiles/claude/.claude/
[ -f ~/.claude/settings.local.json ] && cp ~/.claude/settings.local.json ~/.dotfiles/claude/.claude/
cp ~/.claude/recall-mcp-setup.md ~/.dotfiles/claude/.claude/
cp ~/.claude/recall-proxy.mjs ~/.dotfiles/claude/.claude/
# Directories (excluding cache and ephemeral)
cp -r ~/.claude/projects/ ~/.dotfiles/claude/.claude/projects/
cp -r ~/.claude/agents/ ~/.dotfiles/claude/.claude/agents/
cp -r ~/.claude/commands/ ~/.dotfiles/claude/.claude/commands/
cp -r ~/.claude/skills/ ~/.dotfiles/claude/.claude/skills/
cp -r ~/.claude/hud/ ~/.dotfiles/claude/.claude/hud/
# Plugins (manifests only, not cache)
mkdir -p ~/.dotfiles/claude/.claude/plugins
# Copy plugin list/config but not the cache directory
rsync -a --exclude='cache/' ~/.claude/plugins/ ~/.dotfiles/claude/.claude/plugins/- Step 10: Copy bin scripts
cp ~/bin/sync-claude.sh ~/.dotfiles/bin/bin/
cp ~/bin/pull-claude.sh ~/.dotfiles/bin/bin/
cp ~/bin/smart-sync-claude.sh ~/.dotfiles/bin/bin/
cp ~/bin/vim ~/.dotfiles/bin/bin/- Step 11: Copy gh config
cp ~/.config/gh/config.yml ~/.dotfiles/gh/.config/gh/
cp ~/.config/gh/hosts.yml ~/.dotfiles/gh/.config/gh/- Step 12: Verify stow structure
find ~/.dotfiles -type f | head -40Expected: Files organized under package directories matching home directory structure.
Task 5: Export Language Runtime State
Machine: Old MacBook
Files:
-
Create:
~/.dotfiles/setup/(version snapshots) -
Step 1: Export Node.js state
fnm list > ~/.dotfiles/setup/node-versions.txt
fnm default >> ~/.dotfiles/setup/node-versions.txt
npm list -g --depth=0 > ~/.dotfiles/setup/node-globals.txt- Step 2: Export Python state
pyenv versions > ~/.dotfiles/setup/python-versions.txt
pipx list --short > ~/.dotfiles/setup/pipx-packages.txt- Step 3: Export Ruby state
rbenv versions > ~/.dotfiles/setup/ruby-versions.txt- Step 4: Export Rust state
rustup toolchain list > ~/.dotfiles/setup/rust-toolchains.txt
cargo install --list > ~/.dotfiles/setup/cargo-packages.txt- Step 5: Export Go state
go version > ~/.dotfiles/setup/go-version.txt- Step 6: Verify exports
ls -la ~/.dotfiles/setup/
cat ~/.dotfiles/setup/node-versions.txtExpected: 7+ files in setup directory, Node versions listed.
Task 6: Commit and Push Dotfiles
Machine: Old MacBook
- Step 1: Add remote and push
The repo denniswon/mbp-migrate already exists (private).
cd ~/.dotfiles
git add -A
git commit -m "Initial dotfiles snapshot for MacBook migration"
git remote add origin git@github.com:denniswon/mbp-migrate.git
git push -u origin main- Step 2: Verify push succeeded
git log --oneline -1
git remote -vExpected: Commit hash shown, remote points to GitHub.
Phase 2: Migration Assistant
Task 7: Run Migration Assistant
Machine: New MacBook (first boot)
- Step 1: Unbox and power on new MacBook
During initial macOS setup, select "Transfer Information to This Mac" when prompted.
- Step 2: Choose transfer method
Options (in order of speed):
- Thunderbolt cable (fastest — use a USB-C cable between both machines)
- Wi-Fi Direct (slower, no cable needed)
- Step 3: Select what to transfer
Transfer everything — Migration Assistant handles: apps, system preferences, documents, photos, keychain, 1Password, Raycast, Karabiner, fonts, user account.
- Step 4: Wait for transfer to complete
Expected: 1-3 hours depending on data size and connection method.
- Step 5: Verify macOS layer
- 1Password: opens and unlocks ✓
- Raycast: launches with extensions ✓
- Karabiner: app present (config applied later via stow) ✓
- Cursor: launches ✓
- Docker Desktop: launches ✓
- System preferences: keyboard, trackpad, display settings correct ✓
- Step 6: Back up and remove Homebrew remnants
ls /opt/homebrew/ # check what Migration Assistant copied
sudo mv /opt/homebrew /opt/homebrew.bakExpected: Old Homebrew directory moved to backup. Will delete after Phase 3 succeeds.
Phase 3: Dev Environment Setup
All tasks in Phase 3 run on the new MacBook.
Task 8: Install Foundation (Xcode + Homebrew)
Machine: New MacBook
- Step 1: Install Xcode Command Line Tools
xcode-select --installExpected: Dialog appears, click Install. Wait for completion (~5 min).
- Step 2: Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"- Step 3: Add Homebrew to PATH for current session
eval "$(/opt/homebrew/bin/brew shellenv)"- Step 4: Verify Homebrew
brew --version
which brewExpected: Homebrew version printed, path is /opt/homebrew/bin/brew.
Task 9: Transfer SSH Keys and Secrets
Machine: New MacBook (receiving from old MacBook)
SSH keys must be transferred before cloning the dotfiles repo (which requires SSH auth).
- Step 1: AirDrop SSH private keys from old MacBook
From old MacBook, AirDrop these files:
-
~/.ssh/id_ed25519 -
~/.ssh/id_ed25519.pub -
~/.ssh/google_compute_engine -
~/.ssh/google_compute_engine.pub -
~/.ssh/newton.pem -
~/.ssh/tdx-prover-temp.pem -
Step 2: AirDrop secrets file
From old MacBook, AirDrop:
~/.zsh_secrets(rename tozsh_secretsbefore sending — macOS Finder hides dot-prefixed files)
Note: If dot-files don't appear in Finder, use terminal: ls -la ~/Downloads/ or check Finder > Go > AirDrop.
- Step 3: Move files to correct locations
mkdir -p ~/.ssh
# Move SSH keys from Downloads (where AirDrop puts them)
mv ~/Downloads/id_ed25519 ~/.ssh/
mv ~/Downloads/id_ed25519.pub ~/.ssh/
mv ~/Downloads/google_compute_engine ~/.ssh/
mv ~/Downloads/google_compute_engine.pub ~/.ssh/
mv ~/Downloads/newton.pem ~/.ssh/
mv ~/Downloads/tdx-prover-temp.pem ~/.ssh/
# Move secrets (rename back if sent without dot prefix)
mv ~/Downloads/zsh_secrets ~/.zsh_secrets 2>/dev/null || mv ~/Downloads/.zsh_secrets ~/.zsh_secrets- Step 4: Fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 600 ~/.ssh/google_compute_engine
chmod 600 ~/.ssh/newton.pem
chmod 600 ~/.ssh/tdx-prover-temp.pem
chmod 644 ~/.ssh/*.pub- Step 5: Verify SSH works
ssh -T git@github.comExpected: Hi dennis-won! You've successfully authenticated...
Task 10: Clone Dotfiles and Install Homebrew Packages
Machine: New MacBook
- Step 1: Clone dotfiles repo (SSH keys are now in place)
git clone git@github.com:denniswon/mbp-migrate.git ~/.dotfiles- Step 2: Install all packages from Brewfile
brew bundle install --file=~/.dotfiles/homebrew/BrewfileExpected: All 176 formulae + 74 casks install. Some casks may prompt for password. This step takes 15-30 minutes.
- Step 3: Verify key packages installed
brew list | grep -E 'fnm|pyenv|rbenv|stow|direnv|git-delta|fzf|vfox|gh'Expected: All listed packages appear.
Task 11: Stow Dotfiles
Machine: New MacBook
- Step 1: Remove config files Migration Assistant may have copied
Stow will refuse to create symlinks if real files already exist. Clean them up first:
rm -f ~/.zshrc ~/.zpreztorc ~/.zprofile ~/.zshenv ~/.zlogin ~/.gitconfig ~/.wezterm.lua
# Check if ~/.claude/ exists as a real directory (not from stow)
ls -la ~/.claude/ 2>/dev/null && echo "WARNING: ~/.claude/ exists — back up if needed, then: rm -rf ~/.claude/"- Step 2: Run stow for all packages
cd ~/.dotfiles
stow zsh git wezterm ssh karabiner claude bin ghExpected: No errors. Symlinks created in home directory.
- Step 3: Verify symlinks created
ls -la ~/.zshrc # should point to .dotfiles/zsh/.zshrc
ls -la ~/.gitconfig # should point to .dotfiles/git/.gitconfig
ls -la ~/.wezterm.lua # should point to .dotfiles/wezterm/.wezterm.lua
ls -la ~/.ssh/config # should point to .dotfiles/ssh/.ssh/config
ls -la ~/.claude/CLAUDE.md # should point to .dotfiles/claude/.claude/CLAUDE.mdExpected: All files are symlinks to ~/.dotfiles/....
- Step 4: Verify SSH config paths
grep '/Users/' ~/.ssh/configExpected: All paths reference /Users/dennis.won/. If the username is different on the new machine, update the paths.
- Step 5: Ensure bin scripts are executable
chmod +x ~/bin/*Task 12: Install Zprezto
Machine: New MacBook
- Step 1: Clone Zprezto
git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"- Step 2: Restart shell
Close and reopen terminal (or run exec zsh).
- Step 3: Verify prompt
Expected: Zprezto wikimatze theme renders with git info, colored prompt.
- Step 4: Verify aliases work
type cpush
type ezcExpected: Alias definitions printed.
Task 13: Install Language Runtimes
Machine: New MacBook
- Step 1: Install Node.js versions via fnm
eval "$(fnm env)"
fnm install 22.22.0
fnm default 22.22.0
fnm install 20.10.0
fnm install 24.11.1- Step 2: Verify Node
node -vExpected: v22.22.0
- Step 3: Install Python via pyenv
eval "$(pyenv init -)"
pyenv install 3.13.11
pyenv global 3.13.11- Step 4: Verify Python
python --versionExpected: Python 3.13.11
- Step 5: Install Ruby via rbenv
eval "$(rbenv init -)"
rbenv install 3.3.5
rbenv global 3.3.5- Step 6: Verify Ruby
ruby -vExpected: ruby 3.3.5
- Step 7: Install Rust via rustup
rustup-init -y
source "$HOME/.cargo/env"
rustup toolchain install stable
rustup toolchain install nightlyReview ~/.dotfiles/setup/rust-toolchains.txt for specialized toolchains (risc0, succinct) and install as needed.
- Step 8: Verify Rust
rustc --version
cargo --versionExpected: Stable toolchain version printed.
- Step 9: Verify Go (installed via Homebrew in Task 9)
go versionExpected: go1.23.x darwin/arm64 or newer.
Task 14: Install Global Packages
Machine: New MacBook
- Step 1: Install Node globals
npm install -g openclaw corepack- Step 2: Enable pnpm via corepack
corepack enable- Step 3: Verify pnpm
pnpm --versionExpected: Version string.
- Step 4: Generate OpenClaw completions
mkdir -p ~/.openclaw/completions
openclaw completions zsh > ~/.openclaw/completions/openclaw.zsh- Step 5: Install Python tools via pipx
pipx install poetry
pipx install jupyter-lab
pipx install towncrier- Step 6: Install Cargo tools from exported list
# Use the exported list for accuracy
cat ~/.dotfiles/setup/cargo-packages.txt | grep -E '^\w' | awk '{print $1}' | tr -d ':' | xargs cargo installOr install manually if the parsing is tricky:
cargo install cargo-edit cargo-pgrx cargo-shear circom cocogitto cross just svm-rs sqlx-cliExpected: Each tool compiles and installs. This step takes 10-20 minutes.
Task 15: Install Blockchain Toolchains
Machine: New MacBook
- Step 1: Install Foundry
curl -L https://foundry.paradigm.xyz | bash
source ~/.zshrc # load foundryup into PATH
foundryup- Step 2: Verify Foundry
forge --version
cast --version
anvil --versionExpected: Version strings for all three tools.
- Step 3: Install SP1
curl -L https://sp1.succinct.xyz | bash
source ~/.zshrc
sp1up- Step 4: Install RISC0
curl -L https://risczero.com/install | bash
source ~/.zshrc
rzup install- Step 5: Install Wasmer
curl https://get.wasmer.io -sSfL | shNote: Any Wasmer packages from the old machine need to be reinstalled separately.
- Step 6: Check if installers modified .zshrc
Foundry, SP1, and RISC0 installers may append lines to .zshrc. Since .zshrc is a symlink to the dotfiles repo, these changes modify the stowed file directly. Check and commit:
cd ~/.dotfiles
git diff
# If changes look correct:
git add -A && git commit -m "Add blockchain toolchain PATH entries from installers"Task 16: Install Claude Code
Machine: New MacBook
- Step 1: Install Claude Code CLI
curl -fsSL https://claude.ai/install.sh | sh- Step 2: Verify stow placed configs
ls -la ~/.claude/CLAUDE.md
ls -la ~/.claude/settings.jsonExpected: Both are symlinks to ~/.dotfiles/claude/.claude/....
- Step 3: Install plugins
claude plugins install oh-my-claudecode
claude plugins install superpowers
claude plugins install claude-supermemory
claude plugins install claude-md-management
claude plugins install claude-code-setup
claude plugins install plugin-dev
claude plugins install skill-creator
claude plugins install learning-output-style
claude plugins install rust-analyzer-lsp- Step 4: Verify MCP servers
claude mcp listExpected: 6 servers listed (context7, exa, github, slack, cloudflare, recall).
- Step 5: Verify Claude Code launches
claude --versionExpected: Version 2.x.
Task 17: Install Google Cloud SDK
Machine: New MacBook
- Step 1: Install SDK
curl https://sdk.cloud.google.com | bashFollow prompts. Install to ~/google-cloud-sdk/ (default).
- Step 2: Restart shell
exec zsh- Step 3: Initialize and authenticate
gcloud init
gcloud auth login
gcloud auth application-default loginTask 18: Re-Authenticate Services
Machine: New MacBook
- Step 1: GitHub CLI
gh auth loginSelect: GitHub.com → SSH → existing key.
- Step 2: Azure CLI
az login- Step 3: Launch Docker Desktop
Open Docker Desktop from Applications. Wait for it to fully start (whale icon in menu bar stops animating). This regenerates ~/.docker/completions/ which was lost when Homebrew was wiped.
- Step 4: Docker Hub
docker login- Step 5: Verify Docker completions
ls ~/.docker/completions/Expected: Completion files present (created by Docker Desktop on launch).
- Step 6: Slack MCP (if needed)
Re-authenticate via Claude Code — the OAuth token doesn't transfer.
Phase 4: rsync Projects
Task 19: Transfer Project Repos
Machine: Both (old provides, new receives)
- Step 1: Enable Remote Login on old MacBook
On old MacBook: System Settings → General → Sharing → Remote Login → ON
- Step 2: Find old MacBook's IP
On old MacBook:
ifconfig | grep "inet " | grep -v 127.0.0.1Note the IP address (e.g., 192.168.1.xxx).
- Step 3: rsync projects (from new MacBook)
rsync -aH --progress dennis.won@<OLD_IP>:~/projects/ ~/projects/Expected: All repos transfer with git state intact. Time depends on total size.
- Step 4: rsync magic directory
rsync -aH --progress dennis.won@<OLD_IP>:~/magic/ ~/magic/- Step 5: rsync Go workspace
rsync -aH --progress dennis.won@<OLD_IP>:~/go/ ~/go/- Step 6: Verify a project's git state
cd ~/projects
ls
cd <any-project>
git status
git log --oneline -3
git stash listExpected: Working tree, history, and stashes all intact.
Phase 5: Verification
Task 20: Full Verification Checklist
Machine: New MacBook
- Step 1: Shell and tools
| Check | Command | Expected |
|---|---|---|
| Shell prompt | Open new terminal | Zprezto wikimatze theme renders |
| Zsh aliases | type cpush |
Shows alias definition |
| Secrets loaded | echo $ANTHROPIC_API_KEY |
Key value prints |
| direnv | cd into project with .envrc |
Loads environment |
| vfox | vfox --version |
Version string |
- Step 2: Language runtimes
| Check | Command | Expected |
|---|---|---|
| Node.js | node -v |
v22.22.0 |
| pnpm | pnpm --version |
Version string |
| Python | python --version |
3.13.11 |
| Ruby | ruby -v |
3.3.5 |
| Rust | rustc --version |
stable |
| Go | go version |
1.23.x+ |
- Step 3: Dev tools
| Check | Command | Expected |
|---|---|---|
| Git identity | git config user.email |
jhwon0820@gmail.com |
| Git delta | git log --oneline -5 (in any repo) |
Colored delta output |
| SSH auth | ssh -T git@github.com |
"Hi dennis-won!" |
| Foundry | forge --version |
Version string |
| Docker | docker --version |
29.x |
- Step 4: Claude Code
| Check | Command | Expected |
|---|---|---|
| CLI | claude --version |
2.x |
| MCP servers | claude mcp list |
6 servers listed |
| Plugins | claude plugins list |
9 plugins |
- Step 5: Apps and GUI
| Check | Action | Expected |
|---|---|---|
| WezTerm | Open WezTerm | Custom config loads |
| Windsurf | windsurf --version |
Version string |
| Karabiner | Check remappings | Active |
| GitHub CLI | gh auth status |
Authenticated |
| OpenClaw completions | ls ~/.openclaw/completions/ |
openclaw.zsh exists |
| Docker completions | ls ~/.docker/completions/ |
Files present |
- Step 6: Clean up Homebrew backup
Once everything is verified working:
sudo rm -rf /opt/homebrew.bakSummary
| Phase | Tasks | Estimated Time |
|---|---|---|
| Phase 1: Prepare old machine | Tasks 1-6 | 30-60 min |
| Phase 2: Migration Assistant | Task 7 | 1-3 hours |
| Phase 3: Dev environment setup | Tasks 8-18 | 1-2 hours |
| Phase 4: rsync projects | Task 19 | 30-60 min |
| Phase 5: Verification | Task 20 | 20-30 min |
| Total | 20 tasks | 3-7 hours |
Rollback: Old machine remains untouched. If anything fails, the old MacBook is still fully functional and you can re-run any phase independently.
Here's the condensed step-by-step for migration day:
Phase 2: Migration Assistant
- Unbox, power on, select "Transfer from another Mac" during setup
- Connect via Thunderbolt cable (fastest) or Wi-Fi
- Transfer everything — wait 1-3 hours
- Verify: 1Password, Raycast, Karabiner, Cursor, Docker Desktop all launch
- Back up and remove old Homebrew: sudo mv /opt/homebrew /opt/homebrew.bak
Phase 3: Dev Environment (run in Terminal)
Foundation:
6. xcode-select --install
7. /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
8. eval "$(/opt/homebrew/bin/brew shellenv)"
SSH + Secrets (before cloning repo):
9. Download .ssh/ and .zsh_secrets from Google Drive
10. Place them: mkdir -p ~/.ssh && cp -r ~/Downloads/.ssh/* ~/.ssh/ && mv ~/Downloads/.zsh_secrets ~/
11. Fix permissions: chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519 ~/.ssh/google_compute_engine ~/.ssh/.pem && chmod 644
~/.ssh/.pub
12. Test: ssh -T git@github.com
Dotfiles + Packages:
13. git clone git@github.com:denniswon/mbp-migrate.git /.dotfiles/.dotfiles/homebrew/Brewfile (15-30 min)
14. brew bundle install --file=
15. Remove conflicting files: rm -f ~/.zshrc ~/.zpreztorc ~/.zprofile ~/.zshenv ~/.zlogin ~/.gitconfig ~/.wezterm.lua
16. cd ~/.dotfiles && stow zsh git wezterm ssh karabiner claude bin gh
17. Verify SSH paths: grep '/Users/' ~/.ssh/config (update if username differs)
Zprezto:
18. git clone --recursive https://github.com/sorin-ionescu/prezto.git ~/.zprezto
19. exec zsh — verify prompt renders
Languages:
20. fnm install 22.22.0 && fnm default 22.22.0 && fnm install 20.10.0 && fnm install 24.11.1
21. pyenv install 3.13.11 && pyenv global 3.13.11
22. rbenv install 3.3.5 && rbenv global 3.3.5
23. rustup-init -y && source ~/.cargo/env && rustup toolchain install stable nightly
Global packages:
24. npm install -g openclaw corepack && corepack enable
25. mkdir -p ~/.openclaw/completions && openclaw completions zsh > ~/.openclaw/completions/openclaw.zsh
26. pipx install poetry && pipx install jupyter-lab && pipx install towncrier
27. cat ~/.dotfiles/setup/cargo-packages.txt | grep -E '^\w' | awk '{print $1}' | tr -d ':' | xargs cargo install
Blockchain:
28. curl -L https://foundry.paradigm.xyz | bash && source ~/.zshrc && foundryup
29. curl -L https://sp1.succinct.xyz | bash && source ~/.zshrc && sp1up
30. curl -L https://risczero.com/install | bash && source ~/.zshrc && rzup install
31. curl https://get.wasmer.io -sSfL | sh
32. Check if installers modified .zshrc: cd ~/.dotfiles && git diff — commit if so
Claude Code:
33. curl -fsSL https://claude.ai/install.sh | sh
34. Install plugins (9 commands — see plan file)
35. claude mcp list — verify 6 servers
Google Cloud + Auth:
36. curl https://sdk.cloud.google.com | bash && exec zsh && gcloud init && gcloud auth login
37. gh auth login
38. az login
39. Launch Docker Desktop, then docker login
Phase 4: rsync Projects
- Enable Remote Login on old MacBook (System Settings → General → Sharing)
- From new MacBook:
rsync -aH --progress dennis.won@<OLD_IP>:~/projects//projects//magic/
rsync -aH --progress dennis.won@<OLD_IP>:/magic//go/ ~/go/
rsync -aH --progress dennis.won@<OLD_IP>:
Phase 5: Verify
- Run through the verification checklist in the plan file
- Clean up: sudo rm -rf /opt/homebrew.bak
⏺ ★ Insight ─────────────────────────────────────
The bootstrapping problem: Claude Code needs Homebrew, Node.js, and shell config to run — but those are what you're trying to install.
You need to do a minimal manual bootstrap first, then let Claude Code handle the rest.
─────────────────────────────────────────────────
Here's the minimum you need to do manually before Claude Code can take over:
Manual Bootstrap (10-15 min)
1. Migration Assistant (already done at this point)
2. Back up old Homebrew
sudo mv /opt/homebrew /opt/homebrew.bak
3. Xcode CLI tools
xcode-select --install
4. Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv)"
5. SSH keys + secrets from Google Drive
Download from: https://drive.google.com/drive/u/0/folders/1yZ4vZSQ7IH6zVTjtLyvMMYikKaPQm1Iq
mkdir -p ~/.ssh
cp -r ~/Downloads/.ssh/* ~/.ssh/
mv ~/Downloads/.zsh_secrets ~/
chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519 ~/.ssh/google_compute_engine ~/.ssh/.pem && chmod 644 ~/.ssh/.pub
6. Clone dotfiles (needs SSH key in place)
git clone git@github.com:denniswon/mbp-migrate.git ~/.dotfiles
7. Install Claude Code
curl -fsSL https://claude.ai/install.sh | sh
Then Hand It Off to Claude Code
claude
Once inside Claude, say:
▎ Follow the migration plan at ~/.dotfiles/../docs/superpowers/plans/2026-03-18-macbook-migration.md — start from Task 10 Step 2 (brew
bundle install). I've already done Tasks 7-10 Step 1 manually. Execute the remaining tasks through Phase 5.
Claude Code will then handle: Brewfile install, stow, Zprezto, all language runtimes, global packages, blockchain toolchains, plugin
installs, MCP server verification, Google Cloud SDK, re-authentication prompts, and the full verification checklist.
Note: A few steps will still need your manual input:
- gh auth login, az login, gcloud auth login — browser-based OAuth flows
- Docker Desktop — needs to be launched from Applications
- rsync from old machine — needs the old MacBook's IP
But Claude Code can orchestrate everything else and prompt you when it hits those steps.
On old MacBook: System Settings → General → Sharing → Remote Login → ON
On old machine:
ifconfig | grep "inet " | grep -v 127.0.0.1
Now let me start the brainstorming process. First question:
Have you already received the new MacBook, or are you planning ahead? This matters because:
Which scenario are you in?
✻ Cooked for 2m 50s
❯ I just purchased, but did not open the box
⏺ ★ Insight ─────────────────────────────────────
This is the ideal timing — before opening the box, you can prepare everything on the old machine so the new one gets a clean,
reproducible setup rather than a messy binary clone. Migration Assistant copies everything (including cruft), while a script-based
approach gives you a fresh start with only what you actually use.
─────────────────────────────────────────────────
Perfect timing — you can prepare everything before you even power it on. Next question:
How do you want to approach the migration strategy?
dotfile sync, language installer scripts). Fresh machine, no cruft carried over. Takes more upfront prep but gives you a pristine
environment.
work. Fastest path but carries over any accumulated junk and may have permission/path issues with Homebrew on the new machine.
but manually set up the entire dev environment fresh (Homebrew, languages, shell, Claude Code). Best of both worlds but most complex.
My recommendation is C (Hybrid) — because:
still better rebuilt
Which approach appeals to you?
❯ Hybrid sounds good
⏺ Good choice. Next question:
What's your new MacBook's chip? This affects whether compiled binaries (Rust toolchains, Go, LLVM) can be copied or must be rebuilt.
Also: is it the same macOS version (Sequoia) or newer?
❯ M1 Max RAM: 64GB, Storage: 1TB, Screen Size: 16"
⏺ Great — M1 Max is the same ARM architecture as your M1 Pro, so compiled binaries are fully compatible. That actually simplifies
things.
Next question:
For your secrets management — you currently have ~12 API keys hardcoded in .zshrc. Would you like to:
via op read commands. More secure, and syncs across machines automatically going forward.
.zshrc. Simple middle ground.
My recommendation is B since you already have 1Password and its CLI — it's the most secure and means you never have to manually sync
secrets between machines again.
Which do you prefer?
❯ A
⏺ Got it — keep secrets in .zshrc as-is. Moving on:
For your dotfiles — you have stow installed but not configured, and no dotfile repo exists. Do you want to:
new machine you just clone + stow. Also makes future machine setups trivial.
My recommendation is A (stow + git repo) — you already have stow installed, the setup is minimal, and it gives you a single git clone
&& stow */ command on the new machine. It also means any future dotfile changes are version-controlled.
Which approach?
❯ A
⏺ Good. Last question before I propose the full approach:
For your project repos (~/projects/, ~/magic/) — how do you want to handle those?
branches not pushed.
everything.
And a related question: do you have any uncommitted work or unpushed local branches you care about across those repos?
❯ B
⏺ ★ Insight ─────────────────────────────────────
rsync over local network is the safest for preserving git state — stashes, local branches, worktrees, and uncommitted changes all
survive intact. The key is using rsync -aHAX to preserve symlinks, permissions, and extended attributes that macOS uses.
─────────────────────────────────────────────────
Great — I have everything I need. Let me propose the full migration design.
Migration Design: Hybrid Approach
Phase 1: Prepare Old Machine (Before Opening New Box)
1a. Generate Brewfile
1b. Create Dotfiles Repo with Stow
1c. Export tool-specific state
1d. Snapshot Claude Code
Phase 2: Migration Assistant (macOS Layer)
Let Apple handle:
Do NOT rely on Migration Assistant for:
Phase 3: Dev Environment Setup (New Machine)
Run in this order (dependencies matter):
┌──────┬───────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────┐
│ Step │ What │ Why This Order │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 1 │ Install Xcode CLI tools │ Everything needs this │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 2 │ Install Homebrew │ Package manager for everything else │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 3 │ brew bundle install from Brewfile │ Installs formulae + casks (including fnm, pyenv, rbenv, stow, direnv, │
│ │ │ etc.) │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 4 │ Clone dotfiles repo, stow */ │ Shell configs, git config, WezTerm, scripts all land in place │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 5 │ Install Zprezto │ Clone + link (stow handles the rc files) │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 6 │ Install language runtimes via version │ fnm install, pyenv install, rbenv install, rustup toolchains │
│ │ managers │ │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 7 │ Install global packages │ npm globals, pipx tools, cargo tools │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 8 │ Install blockchain toolchains │ Foundry, SP1, RISC0, Wasmer (curl-based installers) │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 9 │ Re-authenticate services │ gcloud auth, gh auth, Azure CLI, Docker login │
├──────┼───────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 10 │ Verify Claude Code │ Plugins, MCP servers, HUD, memory all intact │
└──────┴───────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────┘
Phase 4: rsync Projects
Phase 5: Verify
What Won't Transfer Automatically (Need Re-Auth)
┌────────────┬───────────────────────────────────────────────────────────┐
│ Service │ Action Needed │
├────────────┼───────────────────────────────────────────────────────────┤
│ gcloud │ gcloud auth login + gcloud auth application-default login │
├────────────┼───────────────────────────────────────────────────────────┤
│ GitHub CLI │ gh auth login │
├────────────┼───────────────────────────────────────────────────────────┤
│ Azure CLI │ az login │
├────────────┼───────────────────────────────────────────────────────────┤
│ Docker Hub │ docker login │
├────────────┼───────────────────────────────────────────────────────────┤
│ Slack MCP │ Re-authenticate OAuth │
├────────────┼───────────────────────────────────────────────────────────┤
│ Raycast │ Should sync via Migration Assistant, verify │
└────────────┴───────────────────────────────────────────────────────────┘
Does this design look right? Anything you'd add, remove, or change before I write it up as a spec?