Last updated: 2026-01-19
Get an M1 Mac ready for daily work with Claude Code, Codex CLI, ZSH + dotfiles, Postgres 17, Redis, and the Diversio monolith. Every step is copy/paste friendly with a clear "why" and a quick success check.
[0 Access] → [1 Claude Code] → [2 Git + Homebrew + SSH] → [3 Dotfiles + Ghostty] → [4 Node + Codex] → [5 Python + UV] → [6 Services] → [7 Monolith]
- 0 Access
- 1 Claude Code
- 2 Git + Homebrew + SSH
- 3 Dotfiles + Ghostty
- 4 Node + Codex
- 5 Python + UV
- 6 Services
- 7 Monolith
- Final verification
You type → Shell (zsh) → Tools (git, node, python) → Project (monolith)
- Open your terminal app (see below)
- Copy/paste commands one line at a time
- After each step, run the Check command
- If it fails, jump to "If stuck" at the end of that step
- If something looks scary, do not guess—ask or paste the output into Claude Code or Codex
We use Ghostty as our terminal app. It's fast, modern, and designed for developers.
First time? Start with macOS Terminal (already on your Mac) for Steps 1-2, then install and switch to Ghostty in Step 3.
Why Ghostty over macOS Terminal?
| Feature | Ghostty | macOS Terminal |
|---|---|---|
| Speed | GPU-accelerated, instant | Slower rendering |
| Font rendering | Crisp, modern | Basic |
| Quick terminal | Cmd+Shift+1 from anywhere | Not supported |
| Team setup | Pre-configured in dotfiles | Needs manual config |
Ghostty is installed automatically in Step 3 via brew bundle. After Step 3, you'll switch to Ghostty for all remaining work.
You are building layers. If a layer is missing, everything above it breaks. Do not skip ahead.
| Why | |
|---|---|
| Paste tokens or secrets into Claude Code/Codex | Security risk |
Run rm -rf unless a teammate tells you exactly what to delete |
Data loss |
Force overwrite files with >| unless you are sure |
Accidental overwrites |
Note: If a command asks for a password, it's your Mac login password (not a website password).
+--------------------------------------+
| Command = verb + options + args |
| Example: ls -la ~/Documents |
+--------------------------------------+
| Syntax | Purpose | Example |
|---|---|---|
cmd1 | cmd2 |
Pipe (connect commands) | ps aux | rg python |
> |
Redirect output (blocked by NO_CLOBBER) | echo "hi" > file.txt |
>| |
Force overwrite | echo "hi" >| file.txt |
>> |
Append | echo "hi" >> file.txt |
Your shell config:
- Exits early for non-interactive shells (scripts stay fast)
- Keeps huge shared history across tabs with de-dupe
- Safer defaults:
pipefail(pipes fail if any step fails),NO_CLOBBER(blocks accidental overwrites) - Fast tab completions with menus and colors
- Python via UV: helpers like
pynew,pyrun,activate - Node via lazy-loaded NVM (ignore if using Volta)
- Speed aliases:
gs=git status,ni=npm install - Modern tools:
ls→eza,cd→z(zoxide),grep→rg(ripgrep) - Auto-activates Python envs when
pyproject.tomlis found - FZF helpers for fuzzy find
- Starship prompt + syntax highlighting + autosuggestions
Want personal tweaks? Use
~/.zshrc.workfor overrides. Leave.zshrcalone.
~/.zshenv → ~/.zshrc → ~/.zshrc.work
(team defaults) (personal overrides)
+------------------------------------------+
| VAR = a setting tools can read |
| |
| export FOO=bar # for this terminal |
| FOO=bar command # for one command |
| echo $FOO # read it |
| env # list all |
+------------------------------------------+
The source command loads a file into the current shell:
source ~/.zshrc # or just: reload| Command | Purpose |
|---|---|
pwd |
Where am I? |
ls |
List files (pretty via eza) |
cd <folder> |
Move to folder |
cd .. |
Up one level |
cd - |
Jump back to previous folder |
open . |
Open current folder in Finder |
zed . |
Open current folder in Zed editor |
git status |
See uncommitted changes |
git pull |
Download latest code |
git checkout <branch> |
Switch branch |
NO_CLOBBERmeans>won't overwrite files—use>\|only when you mean itcdis zoxide, so it learns your folders (cd projectmight jump to your most-used path)- Lazy-loaded tools might say "command not found" until you open a new terminal tab
- Dangerous commands (
rm -rf,kill -9,findreplace): only use when someone tells you exactly what to do
These shortcuts will save you hours. Practice them until they become muscle memory.
This is your most powerful shortcut. Press Ctrl+R and start typing any part of a previous command.
+---------------------------------------------------------+
| Ctrl+R -> type "migrate" -> finds your last migrate |
| command instantly |
+---------------------------------------------------------+
- Press
Ctrl+R, then type a few letters (e.g.,migfor migrate,yarnfor yarn commands) - Use arrow keys to scroll through matches
- Press
Enterto run, orEscto cancel - Works with partial matches anywhere in the command
Example: You ran uv run python manage.py migrate --configuration=DevApp yesterday. Press Ctrl+R, type migrate, and it appears instantly.
As you type, you'll see gray "ghost" text suggesting a command from your history.
+---------------------------------------------------------+
| You type: git pu |
| You see: git push origin HEAD <- gray suggestion |
| |
| Press Shift+Tab to accept the whole suggestion |
| Or keep typing to ignore it |
+---------------------------------------------------------+
| Action | What happens |
|---|---|
| Shift+Tab | Accept the entire suggestion |
| Right arrow | Accept one character at a time |
| Keep typing | Ignore suggestion, it updates as you type |
Press Tab to autocomplete file names, folder names, and commands.
+---------------------------------------------------------+
| cd ~/wo[Tab] -> cd ~/work/ |
| cd ~/work/di[Tab] -> cd ~/work/diversio/ |
| |
| If multiple matches: press Tab twice to see options |
+---------------------------------------------------------+
The cd command learns your frequently-used folders.
# Instead of typing the full path:
cd ~/work/diversio/monolith/backend
# After visiting once, just type:
cd backend
# or even:
cd backIt remembers where you go most often and jumps there.
Type fcd to interactively search and jump to any folder:
fcd
# A searchable list appears - type to filter, Enter to jumpForgot a shortcut? Type show_aliases to see all available shortcuts organized by category.
| Shortcut | What it does |
|---|---|
Ctrl+R |
Search command history (fuzzy) |
Shift+Tab |
Accept autosuggestion |
Tab |
Autocomplete file/folder names |
Ctrl+A |
Jump to start of line |
Ctrl+E |
Jump to end of line |
Ctrl+W |
Delete word before cursor |
Ctrl+U |
Delete entire line |
Ctrl+L |
Clear screen |
cd - |
Go back to previous directory |
!! |
Repeat last command |
Try this sequence to build muscle memory:
- Run:
echo "Hello from terminal" - Press
Ctrl+R, typeecho, pressEnter(runs it again) - Type
cd ~/then pressTabtwice (see folder options) - Type
cd Docand pressTabto complete (becomescd Documents/) - Type
cd -to go back to where you were
Paste this into Claude Code or Codex:
I am stuck on step: <step name>
Command I ran:
<command>
Output:
<paste full terminal output here>
What I expected:
<expected result>
Time: 10-20 min
Why: You cannot clone private repos or use AI tools without accounts.
- Install 1Password (company password manager)
- Sign in and confirm you can see shared vaults
- Verify your GitHub account is added to the DiversioTeam org
- Confirm AI accounts are active:
- Claude Code requires Pro/Max
- Codex CLI requires ChatGPT Pro or supported business plan
- Can open 1Password and see shared vaults
- GitHub org membership confirmed (check with Engineering if unsure)
Ask Engineering to confirm your GitHub org access and AI tool seats.
Time: 5-10 min
Why: This becomes your helper for the rest of the setup.
curl -fsSL https://claude.ai/install.sh | bash
claude --version
claude doctorThen run claude and follow the login prompts (use your Pro/Max account).
claude --versionprints a versionclaude doctorshows all green checks
Re-open Terminal and run claude doctor again. If install fails, re-run the install command. If it still fails, ask a teammate for help or continue to Step 2—you can install Claude Code later.
Time: 15-25 min
Why: Homebrew installs most of our tools and services.
# Trigger Xcode Command Line Tools install (includes git)
git --versionIf macOS prompts you, accept and wait. Then install Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Important (Apple Silicon only): After Homebrew installs, add it to your PATH:
echo >> ~/.zprofile
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"SSH lets you securely connect to GitHub without entering your password every time.
+-----------------------------------------------------------------------+
| How SSH works (simple version): |
| |
| Your Mac GitHub |
| +-----------+ +-----------+ |
| | Private | ---proves you---> | Public | |
| | Key | | Key | |
| | (secret) | | (shared) | |
| +-----------+ +-----------+ |
| |
| You keep the private key. GitHub gets the public key. |
+-----------------------------------------------------------------------+
Step 1: Generate your SSH key
# Create a new SSH key (replace with YOUR email)
ssh-keygen -t ed25519 -C "your.email@diversio.com"When prompted:
- File location: Press
Enterto accept the default (~/.ssh/id_ed25519) - Passphrase: Press
Entertwice for no passphrase (simpler for beginners)
+-----------------------------------------------------------------------+
| You'll see something like: |
| |
| Generating public/private ed25519 key pair. |
| Enter file in which to save the key (/Users/you/.ssh/id_ed25519): |
| [Press Enter] |
| Enter passphrase (empty for no passphrase): [Press Enter] |
| Enter same passphrase again: [Press Enter] |
| Your identification has been saved in /Users/you/.ssh/id_ed25519 |
| Your public key has been saved in /Users/you/.ssh/id_ed25519.pub |
+-----------------------------------------------------------------------+
Step 2: Start the SSH agent
eval "$(ssh-agent -s)"You should see: Agent pid 12345 (number will vary)
Step 3: Add your key to the agent
ssh-add ~/.ssh/id_ed25519You should see: Identity added: /Users/you/.ssh/id_ed25519
Step 4: Copy your public key
pbcopy < ~/.ssh/id_ed25519.pubThis copies your public key to the clipboard. You won't see any output—that's normal!
Step 5: Add the key to GitHub
+-----------------------------------------------------------------------+
| 1. Open: https://github.com/settings/keys |
| |
| 2. Click the green "New SSH key" button |
| |
| 3. Fill in: |
| - Title: "Work MacBook" (or any name you'll remember) |
| - Key type: "Authentication Key" (default) |
| - Key: Press Cmd+V to paste your key |
| |
| 4. Click "Add SSH key" |
| |
| 5. GitHub may ask for your password - enter it |
+-----------------------------------------------------------------------+
Step 6: Test the connection
ssh -T git@github.comFirst time only: Type yes when asked about fingerprint.
+-----------------------------------------------------------------------+
| Success looks like: |
| |
| Hi yourname! You've successfully authenticated, but GitHub does |
| not provide shell access. |
| |
| (This message is GOOD! It means SSH is working.) |
+-----------------------------------------------------------------------+
git --versionprints a versionbrew --versionprints a versionssh -T git@github.comsays "Hi yourname! You've successfully authenticated"
- If
gitis missing, re-rungit --versionto trigger the install prompt - If
brewis not found, re-run the Homebrew install command, then run the three PATH commands again - If SSH test fails, make sure you copied the
.pubfile (public key) and added it to GitHub
Time: 10-20 min
Why: Gives you the same shell and terminal workflow as the team.
# Clone dotfiles (path must be ~/dotfiles for setup.sh)
git clone git@github.com:ashwch/dotfiles.git ~/dotfiles
# Install tools + symlinks
cd ~/dotfiles
./setup.sh
# Install Ghostty, Zed, and other tools
brew bundle --file ~/dotfiles/BrewfileIf
git clonefails with "permission denied": Go back to Step 2 and make sure SSH is set up correctly. Runssh -T git@github.comto test.
The default setup uses tmux (an advanced tool). Run these commands to simplify Ghostty for basic use:
# Remove the symlinks (they point to the shared dotfiles)
rm -f ~/.config/ghostty/config
rm -f ~/Library/Application\ Support/com.mitchellh.ghostty/config
# Create a simple Ghostty config
cat > ~/.config/ghostty/config << 'EOF'
# Ghostty config (simplified for PM setup)
# Documentation: https://ghostty.org/docs/config
# Quick terminal (Cmd+Shift+1 from anywhere)
keybind = global:super+shift+1=toggle_quick_terminal
quick-terminal-position = top
quick-terminal-animation-duration = 0.15
EOF
# Copy to macOS config location
cp ~/.config/ghostty/config ~/Library/Application\ Support/com.mitchellh.ghostty/config
# Remove tmux and its config (not needed for this setup)
rm -f ~/.tmux.conf
rm -rf ~/.tmux
brew uninstall --ignore-dependencies tmux 2>/dev/null || trueGhostty window/tab → zsh shell → your commands
- Open Ghostty from Applications (or Spotlight: Cmd+Space, type "Ghostty")
- Drag Ghostty to your Dock for quick access
- Close macOS Terminal—use Ghostty for all remaining steps
Ghostty is now configured for simple, direct shell access.
zsh --versionprints a version- Ghostty is open and working
- If
./setup.shstops after Xcode tools install, re-run it - If Ghostty won't open, continue with macOS Terminal for now and ask a teammate
Time: 10-15 min
Why: Codex CLI is installed with npm, so we need Node first.
curl https://get.volta.sh | bashOpen a new Ghostty tab (Cmd+T), then:
volta install node@20.11.0
node -v
# Install Yarn (used by frontend)
npm install -g yarn
yarn --versionInstall Codex CLI:
npm i -g @openai/codex
codex --versionRun once to log in:
codexnode -vprintsv20.11.0yarn --versionprints a versioncodex --versionprints a version
- If
voltanot found, open a new Ghostty tab (Cmd+T) - If
codexfails to log in, verify your ChatGPT Pro access
Time: 2-5 min
Why: Backend uses UV for Python and dependencies. (UV was already installed by setup.sh in Step 3.)
Verify UV is working:
uv --versionuv --versionprints a version (e.g.,uv 0.5.x)
If uv is not found, close and re-open Ghostty, then try again. If still missing:
curl -LsSf https://astral.sh/uv/install.sh | shTime: 15-25 min
Why: Backend uses Postgres and Redis locally.
brew install postgresql@17Add to PATH (use .zshrc.work so dotfiles stay safe):
cat <<'SH' >> ~/.zshrc.work
export PATH="/opt/homebrew/opt/postgresql@17/bin:$PATH"
SH
source ~/.zshrc.workStart and configure:
brew services start postgresql@17
psql --version
# Create local database user and db (matches backend sample .env)
createuser -s postgres
psql -d postgres -c "ALTER USER postgres WITH PASSWORD 'password';"
createdb diversio_db"role already exists" is OK.
brew install redis
brew services start redis
redis-cli pingpsql --versionprints17.xredis-cli pingprintsPONG
- If
psqlnot found, open a new Ghostty tab (Cmd+T) - If Redis fails, run
brew services listand paste output into Claude Code
Time: 20-40 min
Why: The unified repo containing all core projects.
mkdir -p ~/work/diversio
cd ~/work/diversio
git clone --recursive git@github.com:DiversioTeam/monolith.git
cd monolithIf clone fails with "permission denied": Go back to Step 2 and verify SSH is working (
ssh -T git@github.com).
cd ~/work/diversio/monolith
git submodule update --init --recursiveRequires
.envfrom teammate
cd ~/work/diversio/monolith/backend
uv sync
uv run python manage.py migrate --configuration=DevApp
uv run python manage.py runserver --configuration=DevAppRequires
NPM_TOKENfor design system (get this from 1Password or ask a coworker)
cd ~/work/diversio/monolith/frontend
# Replace YOUR_TOKEN_HERE with the actual token from 1Password
export NPM_TOKEN=YOUR_TOKEN_HERE
yarn install
yarn start
⚠️ Do not commit NPM_TOKEN. The token is secret—never paste it into AI tools or commit it to git.
cd ~/work/diversio/monolith/optimo-frontend
yarn install
yarn dev- Backend opens at http://localhost:8000/admin
- Frontend opens at http://localhost:3000
- Ask a teammate for the backend
.envfile - If
yarnmissing:npm install -g yarn
Why: Some workflows require a Linux or Windows VM.
- Ask Engineering which VM tool is approved
- If UTM: download from https://mac.getutm.app
- If other (Parallels, VMware): follow official installer
- Can open VM app and create a new VM
Ask Engineering which VM image you should use.
Run these and confirm no errors:
claude --version
codex --version
brew --version
zsh --version
uv --version
node -v
psql --version
redis-cli ping| Command | Expected |
|---|---|
claude --version |
Version number |
codex --version |
Version number |
brew --version |
Version number |
zsh --version |
Version number |
uv --version |
Version number |
node -v |
v20.11.0 |
psql --version |
17.x |
redis-cli ping |
PONG |
If any command fails, paste the output into Claude Code or Codex CLI.
| Problem | Solution |
|---|---|
| "command not found" | Close Ghostty, open new window, retry |
| "permission denied" while cloning | Go back to Step 2 and verify SSH setup (run ssh -T git@github.com to test) |
| Postgres not running | brew services list → check postgresql@17 status |
| Redis not running | brew services list → check redis status |
| AI tools fail login | Confirm Claude Pro/Max and ChatGPT Pro access |