iTerm2 + Claude Code

Stop Your AI From Grading
Its Own Code

Run 4 Claude Code sessions in one iTerm2 window. Opus reviews. Sonnet builds. Each pane has a locked role, model, and permission set — the reviewer is physically incapable of writing files.

macOS only · iTerm2 · Claude Code CLI · ~15 min setup · zero dependencies
In this guide
01

Prerequisites

Three tools to install before anything else. All three are Homebrew packages — if you already have them, each check-then-install is a single command.

1.1 Homebrew
Terminal
# Check then install (skip if already present):
command -v brew >/dev/null && echo "already installed — skip" || \
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Apple Silicon only — add to PATH if not already in ~/.zshrc:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc && source ~/.zshrc
1.2 Node.js (required for Claude Code)
brew install node
1.3 iTerm2
brew install --cask iterm2

Open iTerm2 once to complete initial setup, then continue in it for the rest of this guide.

02

Install Claude Code

Claude Code is Anthropic’s official CLI. Install it globally via npm, then authenticate. Browser OAuth is the recommended path — no API key required.

2.1 Install and authenticate
npm install -g @anthropic-ai/claude-code
claude login # opens a browser window — sign in with your Anthropic account

Pro or Max subscription required for browser OAuth. No API key needed with this method.

🔑
API key alternative If you don’t have a subscription, add export ANTHROPIC_API_KEY="sk-ant-..." to your ~/.zshrc. Get a key at console.anthropic.com → API Keys.
2.2 Verify
claude --version
03

Local AI Models (Ollama)

Run AI models privately on your Mac — no API calls, no data leaving your machine. Install Ollama, pull the models for your RAM tier, then add the shell aliases.

🧪
RAM tiers — pick the block that matches your machine: 🌺 16 GB+ (base), 🔵 32 GB+ (mid), 🔴 64 GB+ (full). Higher tiers are additive.
3.1 Install Ollama and start the server
brew install ollama
ollama serve &
💡
Make it persistentollama serve & only runs until you close the terminal. For Ollama to stay running across reboots (so cc and llm-* aliases work without manual server starts), run this once now:
brew services start ollama
3.2 Pull models — choose your tier
TierModels to pullDisk / Time
🌺 16 GB+qwen3:8b   qwen3-coder:7b   nomic-embed-text~10 GB / 15 min
🔵 32 GB+qwen3:14b   qwen3-coder:14b   nomic-embed-text   deepseek-r1:8b~23 GB / 40 min
🔴 64 GB+qwen3:14b   qwen3-coder:32b   nomic-embed-text   deepseek-r1:8b   gemma3:27b~55 GB / 90 min

Example (16 GB tier):

ollama pull qwen3:8b
ollama pull qwen3-coder:7b
ollama pull nomic-embed-text
3.3 Shell aliases

The Ollama block in zshrc-snippet.sh adds these aliases. Append the relevant tier block to your ~/.zshrc (see Step 6 for full snippet instructions).

AliasModelUse for
llm-fastqwen3:8b / :14bGeneral queries, summaries
llm-codeqwen3-coder:7b / :14b / :32bCode generation & review
llm-reasondeepseek-r1:8b🔵 Structured reasoning (32 GB+)
llm-embednomic-embed-textEmbeddings / RAG
llm-smartrouterAuto-picks by task type
💡
Why iTerm2 over macOS Terminal?

This workflow relies on features the default Terminal doesn't have:

FeaturemacOS TerminaliTerm2
Split panesTabs/windows only — no side-by-side splitsUnlimited independent panes in a single tab
Named profilesBasic profiles, no $ITERM_PROFILE env varAuto-sets $ITERM_PROFILE per pane — the key to role detection
Visual identityBasic themes and transparencyPer-profile backgrounds, tab colours, badges, and 24-bit colour
Window arrangementsNo saved layoutsSave & auto-restore multi-pane layouts on launch
ProductivityStandard find and copyPaste history, Instant Replay, triggers, shell integration
Split panes
Terminal Tabs/windows only
iTerm2 Unlimited independent panes in one tab
Named profiles
Terminal No $ITERM_PROFILE env var
iTerm2 Auto-sets $ITERM_PROFILE per pane
Visual identity
Terminal Basic themes only
iTerm2 Per-profile backgrounds, tab colours, badges
Saved layouts
Terminal Not supported
iTerm2 Save & auto-restore on launch
Productivity
Terminal Standard find and copy
iTerm2 Paste history, Instant Replay, triggers

The $ITERM_PROFILE environment variable is especially critical — it's what lets the cc alias automatically launch the right model and permissions per pane, and it survives window arrangement restores.

04

Create 4 iTerm2 Profiles

Create 4 named profiles, each with a distinct background tint, tab colour, and badge so you can instantly tell which pane you're in.

Each pane runs a separate Claude Code session with a dedicated role. The AUDIT pane uses Opus for deep review. Everything else uses Sonnet to keep costs down. A cc alias launches the right configuration automatically.

AUDIT Opus
Modelopus
Efforthigh
Permissionplan (read-only)
Review completed work. Never generates code. Enforced read-only via --permission-mode plan. Scope reviews with: "Focus ONLY on src/auth.py. Do not read other files."
IMPL Sonnet
Modelsonnet
Efforthigh
PermissionacceptEdits
Write and edit code. Auto-accepts file edits. Run tests after every change.
PROMPT Sonnet
Modelsonnet
Effortmedium
Permissiondefault
Refine prompts, templates, and content. Separate from code changes.
PLAN Sonnet
Modelsonnet
Effortlow
Permissiondefault
Discuss architecture, plan features, review docs. No file writes.
⚠️
Cost awareness Opus is ~15x more expensive than Sonnet per token. Only use the AUDIT pane for reviewing completed, tested work — never for code generation.
📝
What this is NOT This is not an agent orchestrator. There are no background processes, no task queues, no dashboards. You run four focused sessions, you drive each one, you decide when work moves between panes. If you want 50 agents running unattended, other tools exist for that. This setup is for developers who want control, not automation.
💾
Hardware note: This 4-pane setup runs comfortably on 16GB+ machines. On systems with less than 16GB RAM, consider running 2–3 panes instead of all four, or closing inactive panes between tasks. Monitor with top -l 1 | grep PhysMem if you notice slowdowns.
⚠️
macOS + iTerm2 required This guide requires macOS with iTerm2 3.3+. The $ITERM_PROFILE environment variable that drives role detection is iTerm2-specific. A WSL2 + Windows Terminal equivalent ($WT_PROFILE_ID as the role signal) is possible but not documented here.
2.1 Create and name 4 profiles

Open iTerm2 → Settings → Profiles (⌘,). Click the + button four times. Double-click each "New Profile" name to rename it:

Profile NameBackgroundTab ColourRole
CC-AUDIT#0d0b18#a855f7Code review
CC-IMPL#080f0b#22c55eImplementation
CC-PROMPT#080e10#06b6d4Prompt engineering
CC-PLAN#0d0b00#f59e0bArchitecture & planning
iTerm2 Settings showing 4 named profiles in the sidebar
All 4 profiles created and named in the sidebar
2.2 Set background & tab colour

For each profile, click the Colors sub-tab:

  • Click the Background swatch in the "Defaults" row. In the macOS colour picker, switch to Hex mode (sliders icon → dropdown at bottom) and enter the hex value from the table above.
  • Scroll down to "Tab:", tick "Use custom tab color", and set the accent colour.
iTerm2 Colors tab showing tab color checkbox and badge color
Scrolled down in Colors tab — Tab colour and Badge colour visible at the bottom
2.3 Set title, badge, and font

Click the General sub-tab for each profile:

  • Title: Click the dropdown. Under "Foreground Job", uncheck "Job Name" (leave only "Session Name" checked under "Name"). This prevents the tab title from showing -zsh or (claude) after the role name.
  • Badge: Type the role name (AUDIT, IMPL, PROMPT, or PLAN). This overlays a faint watermark on the pane background.

Then click the Text sub-tab and set font to JetBrains Mono 13pt (or Menlo 13pt).

iTerm2 General tab showing title, badge, and command settings
General tab — badge set to "AUDIT", command and initial directory configured
05

Profile Startup Commands & Initial Directory

Each profile needs a startup command (to cd into the project directory and open an interactive shell) and an initial directory setting (as a fallback for window arrangement restores).

3.1 Set the startup command

In each profile → General sub-tab → change the Command dropdown from "Login Shell" to "Custom Shell" and paste the corresponding command:

# CC-AUDIT
/bin/zsh -c 'cd ~/Desktop/your-project; exec zsh'
# Same command for all 4 profiles — only the directory changes per project.
# Role detection uses $ITERM_PROFILE (set automatically by iTerm2),
# so the startup command doesn't need to set PANE_ROLE.

Replace your-project with your actual project directory name.

💡
Why exec zsh at the end? It replaces the subshell with an interactive zsh session. Without it, the pane would close the moment you exit Claude Code or any other command.
3.2 Set the initial directory

Still in the General sub-tab, find Initial directory below the Command field. Change from "Home directory" to "Directory:" and enter the full path:

/Users/yourname/Desktop/your-project
⚠️
Why set both Command and Initial Directory? iTerm2 window arrangement restore doesn't always re-run the startup command, but it always respects the Initial Directory. Setting both ensures you always land in the right folder regardless of how the pane was opened.
06

Shell Snippet

Add a block to your ~/.zshrc that auto-detects which profile you're in and configures coloured prompts, locked tab titles, and a cc alias to launch Claude Code with the right flags.

4.1 Append to ~/.zshrc

Open your shell config file and paste this block at the very bottom:

~/.zshrc — append at bottom
# ── Multi-pane Claude Code workflow ──
# Uses $ITERM_PROFILE (auto-set by iTerm2 on every
# session, including arrangement restores).
case "$ITERM_PROFILE" in
CC-AUDIT)
PANE_ROLE="AUDIT"
PROMPT="%F{magenta}[AUDIT]%f %~ %# " ;;
CC-IMPL)
PANE_ROLE="IMPL"
PROMPT="%F{green}[IMPL]%f %~ %# " ;;
CC-PROMPT)
PANE_ROLE="PROMPT"
PROMPT="%F{cyan}[PROMPT]%f %~ %# " ;;
CC-PLAN)
PANE_ROLE="PLAN"
PROMPT="%F{yellow}[PLAN]%f %~ %# " ;;
esac
if [[ -n "$PANE_ROLE" ]]; then
echo -ne "\033]0;${PANE_ROLE}\007"
_pane_title_precmd() {
echo -ne "\033]0;${PANE_ROLE}\007"
}
precmd_functions+=(_pane_title_precmd)
fi
# ── Claude Code launch alias (role-aware) ──
# Type "cc" to launch with the right flags.
case "$ITERM_PROFILE" in
CC-AUDIT) alias cc='claude --model opus --effort high --permission-mode plan' ;;
CC-IMPL) alias cc='claude --model sonnet --effort high --permission-mode acceptEdits' ;;
CC-PROMPT) alias cc='claude --model sonnet --effort medium' ;;
CC-PLAN) alias cc='claude --model sonnet --effort low' ;;
esac

Then run source ~/.zshrc in each pane to apply.

Why this works reliably
  • $ITERM_PROFILE is set automatically by iTerm2 on every session — including arrangement restores. No dependency on startup commands.
  • precmd_functions+=() adds to the hook array rather than overwriting it, so existing hooks from pyenv, fnm, conda, etc. are preserved.
  • Normal terminals (Default profile) are completely unaffected.
07

Window Layout & Arrangement

Create a 2×2 pane layout, save it, and configure iTerm2 to restore it automatically on launch.

Target layout
AUDIT
adversarial review
opus · high · plan
PROMPT
prompt engineering
sonnet · medium
IMPL
code writing
sonnet · high · acceptEdits
PLAN
architecture & docs
sonnet · low
5.1 Create the 2×2 split
  1. Open a new window with the CC-AUDIT profile.
  2. ⌘D — split right. Right-click the new pane → Edit Session → change profile to CC-PROMPT.
  3. Click back on the left pane (AUDIT). ⌘⇧D — split down. Change the new pane to CC-IMPL.
  4. Click on the top-right pane (PROMPT). ⌘⇧D — split down. Change the new pane to CC-PLAN.
4-pane iTerm2 layout with coloured prompts and badges
Final result — 4 panes with coloured prompts, badges, and distinct background tints
5.2 Save as default arrangement
  1. Window → Arrangements → Save Window Arrangement — give it a name (e.g. your project name).
  2. Go to iTerm2 → Settings → General → Startup and set "Window restoration policy" to "Open Default Window Arrangement".
  3. Back in the menu: Window → Arrangements → Save Window Arrangement once more — this saves it as the default arrangement that the startup policy will use.
Window menu showing Save Window Arrangement option
Window → Arrangements → Save Window Arrangement
iTerm2 General Startup settings showing Open Default Window Arrangement
Settings → General → Startup → "Open Default Window Arrangement"
Result: Every time you open iTerm2, your 4-pane layout restores automatically with the correct profiles, directories, coloured prompts, and badges. No manual setup needed.
08

Launch Claude Code

Type cc in any pane. The alias you set up in Step 4 launches Claude Code with the correct model, effort level, and permissions for that pane.

Panecc expands toWhat you see
AUDIT claude --model opus --effort high --permission-mode plan Opus · plan mode on
IMPL claude --model sonnet --effort high --permission-mode acceptEdits Sonnet · accept edits on
PROMPT claude --model sonnet --effort medium Sonnet · medium effort
PLAN claude --model sonnet --effort low Sonnet · low effort
All 4 panes with Claude Code running showing different models and effort levels
All 4 panes with Claude Code running — Opus in AUDIT (plan mode), Sonnet in the rest
💡
Override anytime: The cc alias is a convenience, not a lock-in. You can always type the full command with different flags when you need to (e.g. claude --model opus --effort max).

Note: On some systems, cc is aliased to the C compiler. If you work with C/C++, rename the alias to cl or claude-go in your ~/.zshrc.
Ref CLI flags reference
FlagPurpose
--model opus|sonnet|haikuModel selection (or full IDs like claude-opus-4-6)
--effort low|medium|high|maxThinking budget: low = fast, minimal reasoning; medium = balanced; high = extended reasoning chains, more tokens; max = maximum depth (slowest, most expensive). PLAN uses low — architectural discussion doesn't need deep reasoning chains.
--permission-mode planRead-only — Claude cannot write files
--permission-mode acceptEditsAuto-accept file edits without prompting
--append-system-prompt "..."Add custom instructions on top of defaults
--continueResume most recent conversation in this directory
--resumeResume a specific session by ID
⚠️
Version note: Flags verified against Claude Code v2.1.81 (March 2026). CLI tools update frequently — run claude --help if a flag isn't recognised.
09

Keyboard Shortcuts

iTerm2 navigation

←/→
Switch panes (left/right)
↑/↓
Switch panes (up/down)
D
Split right
D
Split down
Zoom current pane (toggle)
M
Set mark (bookmark position)
Jump to previous mark
K
Clear terminal buffer

Claude Code (inside a session)

Esc
Interrupt generation
CtrlC
Cancel, return to prompt
/clear
Reset conversation context
/compact
Compress context (keeps summary)
/model
Switch model mid-session
/effort
Switch effort mid-session
10

iTerm2 Triggers (Optional)

Auto-highlight keywords in terminal output.

Set up in Profile → Advanced → Triggers → +

RegexActionColour
\b(CRITICAL|ERROR|FAIL(ED)?)\bHighlight TextRed background
\b(PASS(ED)?|SUCCESS)\bHighlight TextGreen background
\b(WARNING|WARN|TODO)\bHighlight TextYellow background
11

Cross-Pane Workflow

The change cycle

Every code change follows this pattern across panes:

PLAN → Discuss approach. No file writes. Get design sign-off.
IMPL → Implement. Run tests (must pass before proceeding).
AUDIT → Review changed files (read-only). Feed findings to IMPL.
PROMPT → Prompt/content changes (always separate from code).
Cross-pane handoff

When AUDIT finds an issue, copy its output and paste into IMPL:

"The AUDIT pane identified: [paste findings].
Fix this while preserving existing patterns.
Do not touch unrelated files."
💡 Keep context clean
  • Re-anchor on long sessions: "Re-read CLAUDE.md and confirm the project rules. Then..."
  • Scope AUDIT reviews: "Focus ONLY on src/auth.py. Do not read any other files."
  • Clear stale context: /clear resets the conversation entirely.
  • Compress instead: /compact summarises and frees context without losing history.
  • State sync before review: Run /clear in the AUDIT pane before starting a review pass on code that IMPL just wrote. This ensures AUDIT reads current file contents, not stale versions cached in its context.
🎯
The golden rule: When a conversation goes stale — Claude starts repeating itself or loses track of files — type /clear and start fresh with a tightly-scoped prompt. Short, focused sessions always beat long sprawling ones.
12

Daily Playbook

AM Start of session
# 1. Open iTerm2 (arrangement auto-restores)
# 2. Type "cc" in each pane
# 2.5 AUDIT — /clear (fresh context for first review)
/clear
# 3. PLAN — review where you left off
git log --oneline -10
# 4. IMPL — quick smoke test
pytest tests/ -x --tb=short
PM End of session
# 1. IMPL — run full test suite
pytest tests/ -v --tb=short
# 2. IMPL — stage and commit
git add -p
git commit -m "feat: ..."
# 3. Compress long contexts instead of clearing
# Type /compact inside Claude Code
# 4. Save arrangement if layout changed
# Window → Arrangements → Save Window Arrangement
13

Adapt for Other Projects

This setup is project-agnostic. To use it with a different codebase:

1 Create new profiles (or duplicate existing ones)

Use a project-specific prefix: MYPROJECT-AUDIT, MYPROJECT-IMPL, etc. Or keep DEV-* and just change the directory.

2 Update Initial Directory in each profile

Point to the new project path in each profile's General tab.

3 Add case entries to ~/.zshrc (if using new profile names)

Add matching entries in both case blocks for the new names:

# Example with a project-specific prefix
MYPROJECT-AUDIT)
PANE_ROLE="AUDIT"
PROMPT="%F{magenta}[AUDIT]%f %~ %# " ;;
# ... same pattern for MYPROJECT-IMPL, MYPROJECT-PROMPT, MYPROJECT-PLAN
4 Save a new window arrangement per project

Name it after the project (Window → Arrangements → Save Window Arrangement). To switch between projects later, use Window → Arrangements → [arrangement name] — iTerm2 opens the saved 4-pane layout for that project in a new window.

14

Two-Tier Hook Architecture

Hook scripts enforce safety invariants that prompt instructions alone cannot guarantee — blocking dangerous tool calls before they execute and tripping a circuit-breaker on repeated failures.

1 Copy hook scripts to ~/.claude/hooks/
mkdir -p ~/.claude/hooks
cp hooks/protect-env.py ~/.claude/hooks/
cp hooks/protect-git-push.py ~/.claude/hooks/
cp hooks/circuit-breaker.py ~/.claude/hooks/
cp hooks/session-start-reset.py ~/.claude/hooks/
cp hooks/version-check.py ~/.claude/hooks/
2 Merge hooks/settings.json.example into ~/.claude/settings.json

Open (or create) ~/.claude/settings.json. Copy the "hooks" block from hooks/settings.json.example into the top level of the JSON object. All "command" values use $HOME — Claude Code does not expand ~.

💡
Why $HOME instead of ~? Claude Code does not expand ~ in hook command strings. Use $HOME which the shell expands at execution time, or replace with your full absolute path.

The example also includes "env": {"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "50"}. This tells Claude Code to auto-compact the conversation context when it reaches 50% of the context window. Without this, Claude waits until near the limit before compacting, which can cause abrupt context loss mid-session. Set to "0" to disable, or remove the "env" block entirely to use the default threshold.

3 What each hook does
HookTierBlocks when
protect-env.pyPreToolUseEdit/Write/MultiEdit targets any .env file
protect-git-push.pyPreToolUseBash command matches git … push
circuit-breaker.pyPostToolUse3 consecutive tool failures
session-start-reset.pySessionStart(resets counter — never blocks)
version-check.pySessionStart(never blocks — prints update checklist when Claude Code version changes)
⚠️
macOS and Linux only The hook scripts use fcntl for file locking, which is not available on Windows. This matches the iTerm2 requirement (macOS only).
15

gate Workflow

Two aliases in the IMPL pane create a hard gate between implementation and review.

1 The aliases (defined in zshrc-snippet.sh)
# gate: run full test suite; exit code 5 = no tests collected → helpful hint
alias gate='python3 -m pytest tests/ -x --tb=short && echo "✅ GATE PASSED" || { _rc=$?; [ $_rc -eq 5 ] && echo "No tests found — add tests/test_placeholder.py to get started" || false; }'
# ship: gate + interactive stage + commit
alias ship='gate && git add -p && git commit'

Both aliases are only defined when $ITERM_PROFILE == CC-IMPL. They are no-ops in other panes.

2 The handoff rule
IMPL → implement → gate (must pass) → AUDIT → findings → IMPL → fix → gate → AUDIT

Never send work to AUDIT until gate passes.

Why this matters Sending failing code to AUDIT wastes Opus tokens on defects the test suite already catches. The gate alias makes this impossible to forget.
16

SESSION_LOG Pattern

Without a session log, each IMPL session starts cold — Claude asks for a project overview instead of resuming from where work stopped.

1 Keep SESSION_LOG.md in the project root

Append a new entry at the end of every session. Never overwrite old entries. Minimum viable format:

### YYYY-MM-DD — one-line task summary
- **Done**: what was completed this session
- **Decisions**: any architectural choices made
- **Next**: open items for the next session

Real example:

### 2026-03-22 — Add rate-limit retry to API client
- **Done**: Implemented exponential backoff in api_client.py. All 24 tests pass.
- **Decisions**: Max 3 retries, 2s base delay. Errors logged with context, not raised.
- **Next**: AUDIT review of api_client.py. Then wire retry into pipeline scheduler.
2 Instruct Claude to read it on session start

In your ~/.claude/CLAUDE.md (see Step 14), add a Session Continuity instruction: "At the start of every session, read the last 60 lines of SESSION_LOG.md and surface the most recent 'Next:' items before doing anything else."

17

CLAUDE.md Split Pattern

Separating global rules from project-specific rules reduces noise and prevents cross-project contamination in every Claude session.

1 Two files, two scopes
FileLocationCommitted?Contains
CLAUDE.md~/.claude/No — personalCoding conventions, error-handling policy, tool preferences
CLAUDE.md.claude/ (repo)YesProject architecture, active constraints, session continuity

Claude Code merges both automatically — global first, project-specific second.

💡
Keep global rules lean Your ~/.claude/CLAUDE.md is loaded into every session across every project. Aim for under 80 lines — move project-specific detail into the repo's .claude/CLAUDE.md.
2 Use the included templates
# Global rules — do NOT commit
cp CLAUDE.md.template ~/.claude/CLAUDE.md
# Project reference — commit this
cp REFERENCE.md.template .claude/REFERENCE.md
18

MCP Server, Slash Commands & Skills

Phase 6 additions — GitHub MCP integration, the /reflect command, and contextual skills.

1 GitHub MCP Server

Claude Code registers MCP servers via claude mcp add, not by reading a config file from disk. The included .mcp.json.example is reference JSON if you need claude mcp add-json instead.

  1. Install the binary:
    brew install github-mcp-server
    Or see github.com/github/github-mcp-server for other install methods.
  2. Register with Claude Code (user-scope — available in every project):
    claude mcp add github -s user \
    -e GITHUB_PERSONAL_ACCESS_TOKEN=ghp_your_readonly_token \
    -- $(which github-mcp-server) stdio
    Generate a read-only PAT at github.com/settings/tokens with scope public_repo (or repo for private-repo access). Recommended expiry: 90 days.
  3. Verify: claude mcp list | grep github
💡
Scope: -s user registers the server globally (all projects). Omit -s user to restrict to the current project.
2 /reflect slash command

Run /reflect at the end of any IMPL or AUDIT session. Claude reads the recent git log and diff, then outputs a formatted table of suggested CLAUDE.md additions — ready to copy and paste.

# Install once:
mkdir -p ~/.claude/commands
cp commands/reflect.md ~/.claude/commands/reflect.md
⚠️
/reflect never edits CLAUDE.md directly. It outputs suggestions — you decide what to incorporate.
3 Contextual skills

Three skills that load relevant instructions automatically when Claude is doing review or test work:

SkillPaneAdds
code-reviewAUDITProject-specific review conventions
security-auditAUDITSecurity checklist and vulnerability patterns
testingIMPLpytest conventions matching the project
# Install once:
cp -r skills/ ~/.claude/skills/

Skills activate automatically — no manual invocation needed.

19

Draw Things (Optional — Creative AI)

Free local image generation on macOS. Runs entirely on-device via Core ML — no API calls, no sign-up. Completely independent from Claude Code and Ollama.

💡
Truly optional — this section has no bearing on any other step. Skip if you’re not interested in image generation.
Install and set up
  1. Download from the Mac App Store: search “Draw Things AI Image Generator”.
  2. Open the app and let it download a base model (~2–4 GB).
  3. Prompt directly in the app’s text field. Drag and drop an image as reference.

Recommended starting model: SDXL Turbo (fast) or Flux Schnell (higher quality). Models are downloaded in-app — no terminal commands needed.

20

Troubleshooting

Common failure modes and how to fix them.

T1 $ITERM_PROFILE is empty — cc launches the wrong model

Symptom: echo $ITERM_PROFILE returns nothing. The cc alias falls through with no model flags.

Cause: Old iTerm2 version (< 3.3) or the pane was opened before the profile was applied.

Fix:

  • Update iTerm2 to 3.3 or later (Help → Check For Updates).
  • Close and reopen the pane by selecting the profile explicitly: Profiles → [your profile name] → Open in current tab.
  • Confirm with: echo $ITERM_PROFILE — should print CC-AUDIT, etc.
T2 cc launches the C compiler instead of Claude

Symptom: which cc shows /usr/bin/cc. Typing cc outputs compiler error messages.

Fix: Rename the alias in ~/.zshrc. Replace all 4 alias cc= occurrences with alias cl= (or any name you prefer), then reload:

# In ~/.zshrc — change all 4 occurrences:
CC-AUDIT) alias cl='claude --model opus --effort high --permission-mode plan' ;;
CC-IMPL) alias cl='claude --model sonnet --effort high --permission-mode acceptEdits' ;;
# ... then:
source ~/.zshrc
T3 Hooks not firing — .env edits or git push not blocked

Check 1 — Hook files exist:

ls ~/.claude/hooks/
# Expected: protect-env.py protect-git-push.py circuit-breaker.py session-start-reset.py version-check.py

Check 2 — Python 3 is available:

which python3
# Must return a path. If missing: brew install python3

Check 3 — settings.json is valid JSON:

python3 -m json.tool ~/.claude/settings.json
# Prints formatted JSON on success. Any error = invalid JSON in the file.
T4 Circuit-breaker stuck — session halted after tool failures

Symptom: Claude is blocked and won't proceed. The circuit-breaker tripped after 3 consecutive tool failures.

Fix A — Start a new session: Press Ctrl+C, then type cc. The session-start-reset.py hook fires automatically on session start and resets the counter.

Fix B — Reset the state file directly:

# Run from your project root (where Claude Code was launched from)
rm -f ./circuit-breaker-state.json
# Then /clear inside Claude Code to reset conversation context.
T5 gate fails with "pytest not found" or collects 0 tests

Symptom: gate exits non-zero immediately or pytest reports collected 0 items.

  • Venv not active: Run source venv/bin/activate (or source .venv/bin/activate) before running gate.
  • pytest not installed: which pytest should point inside your venv. If not: pip install pytest.
  • No test files yet: Add a placeholder so the intent is explicit: touch tests/test_placeholder.py with a single passing test.
T6 Need to push to git — hook is blocking it

The protect-git-push.py hook blocks Claude from running git push autonomously. You can always push directly from a regular terminal prompt — hooks only intercept tool calls inside a Claude Code session.

# Open a new iTerm2 tab (not inside a Claude session) and run:
git push
⚠️
This is by design. Review the diff yourself before pushing — that's the point of the hook.
T7 Claude CLI update broke the cc alias

Symptom: After npm update -g @anthropic-ai/claude-code, typing cc errors with an unknown flag message.

  1. Run claude --help to see current supported flags.
  2. Update the alias block in ~/.zshrc to match, then source ~/.zshrc.
  3. Most stable flags: --model and --effort have been stable across versions. --permission-mode values are also stable. Check the Claude Code release notes for breaking changes.

Run claude --version to check your installed version. This guide was verified against v2.1.81 (March 2026).

💡
Tip: The version-check.py hook (Step 11) detects version changes automatically and prints this checklist at session start.
21

Quick Reference — read as needed

Everything on one screen — copy, paste, go.

1 Pane roles
PaneModelEffortPermissionPurpose
AUDITOpushighplanCode review (read-only)
IMPLSonnethighacceptEditsWrite code + run tests
PROMPTSonnetmediumdefaultPrompt engineering
PLANSonnetlowdefaultArchitecture + planning
2 Shell aliases
AliasPaneWhat it does
ccAllLaunch Claude Code with role-correct flags
gateIMPLRun full test suite — must pass before AUDIT handoff
shipIMPLgate + git add -p + git commit
3 Keyboard shortcuts
ShortcutAction
⌘⌥ ←/→/↑/↓Switch panes
⌘⇧↵Zoom/unzoom pane
⌘DSplit right
⌘⇧DSplit down
EscStop Claude generation
/clearReset conversation context
/compactCompress context (keep history)
4 Daily workflow
# Morning
1. Open iTerm2 (arrangement auto-restores)
2. Type cc in each pane
 
# Working
3. PLAN → discuss approach (no writes)
4. IMPL → implement → gate (must pass)
5. AUDIT → review changed files → findings back to IMPL
   /clear AUDIT before reviewing (state sync)
 
# End of day
6. IMPL → ship (gate + stage + commit)
7. Update SESSION_LOG.md
8. /compact in long sessions
5 Safety hooks
HookEventBlocks
protect-env.pyPreToolUseAny edit to .env files
protect-git-push.pyPreToolUsegit push commands
circuit-breaker.pyPostToolUse3 consecutive tool failures
session-start-reset.pySessionStart(resets counter)
version-check.pySessionStart(never blocks — prints update checklist on version change)