Claude Code iOS Safety Guide

Run Claude Code autonomously for fast iOS development — without risking file destruction or project corruption. Step-by-step setup with every terminal command spelled out.

🚨 About --dangerously-skip-permissions: This flag disables ALL built-in permission prompts, including settings.json allow/deny rules. When active, Claude can execute any command without asking. This guide provides external guardrails (git checkpoints, hooks, CLAUDE.md) that work regardless of this flag.
⏱️ ~45 minutes total setup
🎯 7 layers of protection
💾 Persistent — set up once
📋

Prerequisites

You need Claude Code installed and working before starting this guide.

Install Claude Code
npm install -g @anthropic-ai/claude-code
Verify installation
claude --version
💡 Also need: Xcode installed and opened at least once (to accept the license), Git configured, and a macOS machine. Node.js is required for XcodeBuildMCP in Step 4.
🗺️

Safety Overview

The guide uses a layered defense approach. Steps are ranked by impact — do the top ones first and you're already 90% protected. Everything is persistent — you set it up once.

LayerWhat It DoesProtects Against
Step 1 — Git checkpointAuto-commit before every sessionEverything (nuclear rollback)
Step 2 — Permission whitelistBlocks rm, sudo, rmdirFile deletion, privilege escalation
Step 3 — CLAUDE.mdForbids .pbxproj edits, sets rulesProject corruption, scope creep
Step 4 — XcodeBuildMCPStructured build/test/run toolsMalformed xcodebuild commands
Step 5 — Slash commandsQuick access to safe workflowsHuman error, repetitive typing
Step 6 — Simulator skillStructured simulator interactionRaw simctl mistakes
Step 7 — Daily workflowRepeatable safe processForgetting to checkpoint
🚨 Critical limitation: As of February 2026, deny rules in settings.json are not reliably enforced. Commands like find . -exec rm {} \; or bash -c "rm -rf ..." bypass Bash(rm:*) deny patterns. Additionally, --dangerously-skip-permissions bypasses the entire permission system. This is why the git checkpoint (Step 1) and hooks (Step 2b) are your real safety nets — not the permission config alone.
🧭

Choose Your Path

Two approaches to running Claude Code safely for iOS development. Pick one based on your needs.

Step 1 · 5 minutes
🔒

Git Checkpoint Alias

This is your single most important safety layer. If Claude deletes files, corrupts your .pbxproj, or makes bad changes — one command rolls everything back. You're adding a shortcut command (called an "alias") to your shell configuration file.

1a — Open your shell config file

Open ~/.zshrc in TextEdit
open ~/.zshrc

If you get an error saying the file doesn't exist, create it first:

Create the file if missing
touch ~/.zshrc
open ~/.zshrc

1b — Paste the alias at the bottom of the file

Scroll to the very bottom and paste this line:

Safe Claude Code launcher alias
# Safe Claude Code launcher — auto-commits before every session
alias clauded='git add -A && git commit -m "pre-claude checkpoint $(date +%H:%M)" --allow-empty && claude --dangerously-skip-permissions'

1c — Save and reload

Save the file (Cmd + S), close TextEdit, then reload:

Reload shell config
source ~/.zshrc

1d — Verify it worked

Check the alias exists
which clauded

You should see output like clauded: aliased to git add -A && .... If you see "not found", repeat steps 1a–1c.

How to use it

From now on, start every Claude session with clauded instead of claude:

Start a safe session
cd ~/path/to/your/ios-project
clauded

If anything goes wrong mid-session, undo everything Claude did:

Nuclear rollback
# Undo everything
git reset --hard HEAD

# Or review changes first
git diff HEAD
Step 2 · 10 minutes
🛡️

Permission Whitelist

This explicitly allows only the commands Claude needs and blocks destructive ones like rm (delete).

2a — Create the settings directory

Check if it exists, create if not
# Check if directory exists
ls ~/.claude/

# If "No such file or directory", create it:
mkdir -p ~/.claude

2b — Check for existing settings

View current settings (if any)
cat ~/.claude/settings.json

If you see existing content, you'll merge carefully. If "No such file or directory", proceed to create it.

2c — Open the settings file

Create and open settings.json
touch ~/.claude/settings.json
open ~/.claude/settings.json

2d — Paste the permission config

~/.claude/settings.json
{
  "permissions": {
    "allow": [
      // File tools
      "Read(*)", "Write(*)", "Edit(*)",
      // Shell basics
      "Bash(ls:*)", "Bash(mkdir:*)", "Bash(mv:*)",
      "Bash(cp:*)", "Bash(cat:*)", "Bash(head:*)",
      "Bash(tail:*)", "Bash(grep:*)", "Bash(rg:*)",
      "Bash(find:*)", "Bash(touch:*)", "Bash(echo:*)",
      "Bash(which:*)", "Bash(open:*)",
      "Bash(wc:*)", "Bash(sort:*)", "Bash(uniq:*)",
      "Bash(diff:*)", "Bash(tr:*)", "Bash(cut:*)",
      "Bash(tee:*)", "Bash(env:*)",
      "Bash(basename:*)", "Bash(dirname:*)",
      // Text processing
      "Bash(sed:*)", "Bash(awk:*)",
      // Git
      "Bash(git:*)",
      // Swift / Xcode toolchain
      "Bash(swift:*)", "Bash(swiftc:*)",
      "Bash(xcodebuild:*)", "Bash(xcrun:*)",
      "Bash(xcode-select:*)", "Bash(plutil:*)",
      "Bash(swiftlint:*)", "Bash(swiftformat:*)",
      // Package managers
      "Bash(pod:*)", "Bash(mint:*)",
      "Bash(brew install:*)", "Bash(brew info:*)",
      "Bash(npm:*)", "Bash(npx:*)",
      // System
      "Bash(chmod:*)", "Bash(make:*)",
      "Bash(python3:*)", "Bash(curl:*)",
      "Bash(pkill:*)"
    ],
    "deny": [
      "Bash(rm:*)",
      "Bash(rmdir:*)",
      "Bash(sudo:*)",
      "Bash(bash -c:*)",
      "Bash(sh -c:*)",
      "Bash(chmod 777:*)",
      "Edit(**/*.pbxproj)"
    ]
  }
}

2e — Save and validate

Save the file (Cmd + S), close TextEdit, then validate the JSON:

Validate JSON syntax
python3 -c "import json; json.load(open('$HOME/.claude/settings.json')); print('Valid JSON')"

If you see "Valid JSON", you're good. If you see an error, open the file and check for missing commas or brackets.

💡 What this does: rm, rmdir, sudo, bash -c, and .pbxproj edits are blocked. Dev tools (git, swift, xcodebuild, xcrun, swiftlint, swiftformat) are pre-approved. Note: brew is limited to brew install and brew info only — not brew uninstall or brew cleanup.
Step 2b · 10 minutes
🪝

Safety Hooks

Hooks are shell commands that fire automatically before or after Claude uses a tool. Unlike deny rules, hooks execute deterministically and cannot be bypassed — even with --dangerously-skip-permissions. This is your most reliable enforcement layer.

💡 Why hooks over deny rules? A PreToolUse hook intercepts the actual tool invocation and can inspect the full command. Deny rules only match the first token of a Bash command, so find . -exec rm {} \; bypasses Bash(rm:*). Hooks catch everything.

2b.1 — Add hooks to your settings

Open ~/.claude/settings.json and add a hooks key alongside the existing permissions key:

~/.claude/settings.json — add hooks
{
  "permissions": { ... },
  "hooks": {
    "PreToolUse": [
      {
        // Block destructive commands (rm, rmdir, etc.)
        "matcher": "Bash",
        "hooks": [{
          "type": "command",
          "command": "echo \"$CLAUDE_TOOL_INPUT\" | grep -qiE '\\brm\\b|\\brmdir\\b|> /dev/null' && echo 'BLOCKED: destructive command detected' >&2 && exit 2 || exit 0"
        }]
      },
      {
        // Block .pbxproj modifications
        "matcher": "Edit",
        "hooks": [{
          "type": "command",
          "command": "echo \"$CLAUDE_TOOL_INPUT\" | grep -q '.pbxproj' && echo 'BLOCKED: .pbxproj edit' >&2 && exit 2 || exit 0"
        }]
      }
    ],
    "PostToolUse": [
      {
        // Auto-format Swift files after edits
        "matcher": "Write|Edit",
        "hooks": [{
          "type": "command",
          "command": "echo \"$CLAUDE_TOOL_INPUT\" | grep -q '.swift' && which swiftformat > /dev/null && swiftformat \"$(echo $CLAUDE_TOOL_INPUT | grep -oE '/[^ ]*\\.swift')\" --quiet || exit 0"
        }]
      }
    ]
  }
}

2b.2 — How hooks work

Hook EventWhen It FiresUse For
PreToolUseBefore a tool executesBlock destructive commands, prevent file edits
PostToolUseAfter a tool completesAuto-format code, log changes, run linters
StopWhen Claude finishes respondingAuto-commit changes, send notifications
SessionStartWhen a session beginsValidate environment, check prerequisites

2b.3 — Exit codes

The hook's exit code controls behavior:

Exit CodeEffect
0Allow — tool proceeds normally
2Block — tool execution is prevented, stderr shown to Claude
OtherError — hook failure is reported but tool may still proceed
ℹ️ The matcher field matches tool names: "Bash", "Edit", "Write", "Read". Use | for multiple: "Write|Edit". The environment variable $CLAUDE_TOOL_INPUT contains the JSON input to the tool.
Step 3 · 5 minutes
📄

CLAUDE.md Guardrails

Claude reads a file called CLAUDE.md automatically at the start of every session and treats the contents as binding instructions. You'll create one in your iOS project.

3a — Navigate to your project

Go to your iOS project
# Replace with your actual project path
cd ~/Developer/MyApp

3b — Create and open CLAUDE.md

Create the file
touch CLAUDE.md
open CLAUDE.md

3c — Paste the guardrails

Paste this into the file and customize the bottom section:

CLAUDE.md
# Project Rules for Claude Code

## Critical — Never Do These
- NEVER modify any .pbxproj file directly. Create new files
  and tell me to add them in Xcode manually.
- NEVER modify .xcscheme or build configuration files.
- NEVER use rm, rm -rf, rmdir, or any file deletion command.
- NEVER create files outside the project directory.
- NEVER modify .gitignore without asking first.
- NEVER touch Podfile.lock, Package.resolved, or any lockfiles.
- NEVER modify Info.plist signing or provisioning settings.
- NEVER add third-party dependencies without asking first.
- NEVER run `pod install` or `swift package resolve` without asking.
- NEVER use `open -a` to launch applications.

## Required Practices
- Commit checkpoints after completing a feature or significant change.
- Place new Swift files in the correct group folder.
- Use SwiftUI for new views unless told otherwise.
- Prefer @Observable over ObservableObject for iOS 17+ targets.
- Use structured concurrency (async/await) over completion handlers.
- Use #Preview macro syntax for iOS 17+ projects.
- Add MARK: comments to organize code sections.
- Follow existing code patterns and naming conventions.
- Add Logger/os_log statements for complex async flows.
- Write XCTest unit tests for new business logic.
- When fixing a build error, fix only that error — do not refactor
  surrounding code.
- Maximum file length: 300 lines. Suggest splitting if exceeded.

## Build Instructions
- Always use XcodeBuildMCP tools instead of raw xcodebuild.
- Build: simulator/build
- Test:  simulator/test
- Run:   simulator/build-and-run

## Project Architecture
- Architecture: [MVVM / MVC / TCA — replace with yours]
- Min target:   iOS [17 / 18 — replace with yours]
- Packages:     [SPM / CocoaPods — replace with yours]
- Main scheme:  [YourAppScheme — replace with yours]

## Key Directories
- Sources/Features/ — feature modules
- Sources/Services/ — networking, persistence
- Tests/ — unit and UI tests
ℹ️ How to find your project details: Architecture — if you have ViewModel files, it's likely MVVM. Deployment target — Xcode → project → General → Minimum Deployments. Package manager — if you have a Podfile it's CocoaPods, if Package.swift it's SPM. Main scheme — the scheme selector next to the play button in Xcode.

3d — Commit to your project

Save guardrails to git
git add CLAUDE.md
git commit -m "add Claude Code project guardrails"
Step 4 · 10 minutes
🔧

XcodeBuildMCP v2

XcodeBuildMCP (now maintained by Sentry) gives Claude 59 structured tools for building, testing, debugging, and interacting with your iOS app — instead of running raw shell commands. It supports Xcode projects, workspaces, and Swift packages.

4a — Check Node.js

Verify Node.js is installed
node --version

If you see a version number (e.g. v20.11.0), skip to 4b. If "command not found":

Install Node.js via Homebrew
# Install Homebrew first if you don't have it:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Then install Node:
brew install node

4b — Install XcodeBuildMCP

Add the MCP server
claude mcp add --transport stdio XcodeBuildMCP -- npx -y xcodebuildmcp@latest

4c — (Optional) Enable fast rebuilds

Incremental builds + dynamic tools
claude mcp add --transport stdio XcodeBuildMCP \
  --env INCREMENTAL_BUILDS_ENABLED=true \
  --env XCODEBUILDMCP_DYNAMIC_TOOLS=true \
  -- npx -y xcodebuildmcp@latest

4d — Verify it works

Test inside a Claude session
# Start a Claude session in your project
cd ~/path/to/your/ios-project
claude

# Inside the session, type:
mcp__xcodebuildmcp__list_simulators

# You should see iPhone 15, iPhone 16, etc.
# Type /exit to leave

If you get an error, verify Xcode command line tools are installed:

Check Xcode CLI tools
xcode-select -p          # Should print a path
xcode-select --install   # Install if missing

4e — (Optional) Load only specific workflows

XcodeBuildMCP v2 has 59 tools. To save context window space, load only what you need:

Load specific workflow groups
claude mcp add --transport stdio XcodeBuildMCP \
  --env XCODEBUILDMCP_ENABLED_WORKFLOWS=simulator,debugging \
  -- npx -y xcodebuildmcp@latest

Available Tool Categories (v2)

CategoryKey ToolsWhat They Do
Simulatorsimulator/build, simulator/build-and-run, simulator/testBuild, run, and test on iOS Simulator
Screenshotssimulator/screenshotCapture simulator screen for visual verification
UI Automationui-automation/tap, ui-automation/swipe, ui-automation/type, ui-automation/long-pressInteract with running app UI elements
UI Inspectiondescribe_uiGet full view hierarchy with frame coordinates
Debuggingdebugging/attach, debugging/breakpointLLDB integration for runtime debugging
DeviceDeploy/test toolsPhysical device deployment over USB/Wi-Fi
SPMswift_package_build, swift_package_testSwift Package Manager operations
Projectclean, list_simulators, boot_simulatorProject management and simulator control
ℹ️ Sentry acquisition: XcodeBuildMCP was acquired by Sentry in February 2026. The npm package (xcodebuildmcp) remains the same. The GitHub repo moved to getsentry/XcodeBuildMCP. It integrates natively with Xcode 26.3's agentic coding features.
Step 5 · 5 minutes

Skills & Commands

Shortcuts you can type inside a Claude Code session. Instead of a long instruction, type /build or /test.

ℹ️ Skills vs. slash commands: As of Claude Code v2.1.3, slash commands have been merged into the skills system. The .claude/commands/ approach still works (backward-compatible), but the recommended path is .claude/skills/ with user-invocable: true. Both approaches are shown below.

5a — Create the commands directory

Create .claude/commands/
cd ~/path/to/your/ios-project
mkdir -p .claude/commands

5b — Create the build command

.claude/commands/build.md
cat > .claude/commands/build.md << 'EOF'
---
description: Build the iOS project on simulator
allowed-tools: mcp__xcodebuildmcp__*
---
Build the project using `mcp__xcodebuildmcp__build_sim_name_proj`.
Report any build errors clearly with file, line number, and suggested fix.
EOF

5c — Create the test command

.claude/commands/test.md
cat > .claude/commands/test.md << 'EOF'
---
description: Run all unit tests
allowed-tools: mcp__xcodebuildmcp__*
---
Run all tests using `mcp__xcodebuildmcp__test_sim_name_proj`.
Summarize results: total, passed, failed.
For failures show test name, expected vs actual, and a fix.
EOF

5d — Create the checkpoint command

.claude/commands/checkpoint.md
cat > .claude/commands/checkpoint.md << 'EOF'
---
description: Save current progress with a git commit
---
Run: git add -A && git commit -m "checkpoint: [brief description]"
Summarize what was committed.
EOF

5e — Verify and commit

Check files and commit
ls -la .claude/commands/
# Should show: build.md  test.md  checkpoint.md

git add .claude/
git commit -m "add Claude Code slash commands"
Step 6 — Optional · 10 minutes
📱

iOS Simulator Skill

Adds deeper simulator interaction — tapping UI elements, accessibility audits, visual testing. Skip this if you only need Claude for code generation and builds.

Install the skill
# Create skills directory
mkdir -p ~/.claude/skills

# Clone the skill
git clone https://github.com/conorluddy/ios-simulator-skill.git \
  ~/.claude/skills/ios-simulator-skill

# Verify
ls ~/.claude/skills/ios-simulator-skill/SKILL.md

Restart Claude Code. The skill loads automatically. Test it by asking:

Test in a Claude session
Run a health check on my iOS simulator setup
Step 7 · Daily use
🔄

Daily Workflow

Here's how to use everything together, every day.

7a — Start on a dedicated branch

Starting a session
# 1. Navigate to your project
cd ~/path/to/your/ios-project

# 2. Create a feature branch (isolate Claude's work)
git checkout -b claude/profile-view

# 3. Start a safe Claude session
clauded
💡 Why branch isolation? Working on a dedicated branch means Claude's changes never touch your main branch directly. Review the diff, squash-merge if good, delete the branch if bad. Much safer than working on main.

7b — Give a well-scoped task

Example prompt
Add a ProfileView with name, email, and avatar using SwiftUI.
Follow the existing MVVM pattern in the project.
Create a ProfileViewModel with @Published properties.
Write unit tests for the ViewModel.
ℹ️ Use plan mode for complex tasks: Press Shift+Tab twice to enter plan mode. Claude will explore your codebase and propose an implementation plan before writing any code. Approve or refine the plan first, then let it execute.

7c — Review Claude's changes

Review and decide
# See what files changed
git status

# See actual changes line by line
git diff HEAD

# If everything looks good — commit and merge
git add -A && git commit -m "feat: add ProfileView"
git checkout main && git merge claude/profile-view

# If something went wrong — undo EVERYTHING
git checkout main && git branch -D claude/profile-view

7d — iOS code review checklist

When reviewing Claude's Swift code, watch for these common issues:

7e — Managing context in long sessions

Large iOS projects can fill Claude's context window quickly. Tips to manage this:

TechniqueHow
Compact contextType /compact to summarize and free up context mid-session
Scope to modulesAsk Claude to focus on one module/feature at a time, not the whole project
Multi-session workflowBreak large features into multiple sessions — each starts fresh with full context
Use subagentsClaude automatically spawns Explore subagents to search without filling your main context
💡 Things you still do in Xcode manually: Add new files to the project (drag into navigator), run on physical devices, review UI visually, manage signing/provisioning, submit to App Store Connect.
Alternative Approach
🐳

VSCode DevContainer

If you want full container-level isolation — where Claude literally cannot touch your host system — use this Docker-based approach with VS Code. This is the safest option but comes with a trade-off: you lose native Xcode/Simulator integration inside the container.

⚠️ Trade-off: iOS simulators require macOS and can't run inside a Docker container. With this approach, Claude writes code inside the container, and you build/run natively in Xcode on your Mac. You work in two windows.

Anthropic's Official DevContainer

1. Install prerequisites
# Install Docker Desktop from docker.com
npm install -g @devcontainers/cli
# In VS Code: Cmd+Shift+X → "Dev Containers" → Install
2. Create .devcontainer in your project
cd ~/path/to/your/ios-project
mkdir -p .devcontainer

cat > .devcontainer/devcontainer.json << 'DEVEOF'
{
  "name": "Claude Code iOS Sandbox",
  "image": "mcr.microsoft.com/devcontainers/javascript-node:20",
  "features": {
    "ghcr.io/devcontainers/features/git:1": {}
  },
  "postCreateCommand": "npm install -g @anthropic-ai/claude-code",
  "mounts": [
    "source=${localEnv:HOME}/.claude,target=/home/node/.claude,type=bind",
    "source=${localEnv:HOME}/.claude.json,target=/home/node/.claude.json,type=bind"
  ],
  "forwardPorts": [],
  "customizations": {
    "vscode": { "extensions": ["anthropic.claude-code"] }
  }
}
DEVEOF
3. Launch
# VS Code: Cmd+Shift+P → "Reopen in Container"
# Or via CLI:
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . claude --dangerously-skip-permissions

Trail of Bits DevContainer (Maximum Security)

Purpose-built for running Claude Code in bypass mode safely.

Install and run
# Install the devc tool
npm install -g @devcontainers/cli
git clone https://github.com/trailofbits/claude-code-devcontainer ~/.claude-devcontainer
~/.claude-devcontainer/install.sh self-install

# Set up, start, and run
cd ~/path/to/your/ios-project
devc .
devc up
devc shell
claude --dangerously-skip-permissions

Quick Docker One-Liner

Minimal config. Filesystem sandboxed to mounted workspace.

Docker one-liner
docker run -it --rm \
  -v $(pwd):/workspace \
  -v ~/.claude:/root/.claude \
  -v ~/.claude.json:/root/.claude.json \
  node:20 \
  bash -c "npm i -g @anthropic-ai/claude-code && cd /workspace && claude --dangerously-skip-permissions"
🚨 Do NOT use --network none: Claude Code requires network access to the Anthropic API. The container already provides filesystem isolation.
💡 The hybrid workflow: Terminal 1 (container) — Claude writes and refactors code. Terminal 2 (your Mac) — you build and run in Xcode. Claude makes changes in the mounted workspace, and you build natively.

DevContainer Comparison

ApproachSetup TimeSecurityXcode Integration
Native + guardrails (Steps 1–7)45 minGoodFull
Option A — VS Code DevContainer15 minStrongSplit workflow
Option B — Trail of Bits20 minMaximumSplit workflow
Option C — Docker one-liner2 minStrongSplit workflow
🛠

Config Builders

Generate customized configuration files for your iOS project.

CLAUDE.md Builder

Fill in your project details and get a ready-to-use CLAUDE.md file.

Protect .pbxproj
Block Deletion
@Observable
Async/Await
Unit Tests
SwiftData
TCA Rules
📖

Quick Reference

CommandWhat It Does
claudedStart a safe Claude session (auto-checkpoints first)
git reset --hard HEADUndo everything Claude did since checkpoint
git diff HEADReview what Claude changed
git checkout -b claude/featureCreate isolated branch for Claude's work
/buildBuild the project (inside session)
/testRun all tests (inside session)
/checkpointSave progress as git commit (inside session)
/compactSummarize context to free up space (inside session)
Shift+Tab (x2)Enter plan mode for complex tasks (inside session)
/exitLeave a Claude Code session
source ~/.zshrcReload shell config after editing
open ~/.claude/settings.jsonEdit permissions and hooks
open CLAUDE.mdEdit project guardrails
🩺

Troubleshooting

"clauded: command not found"

Your shell didn't load the alias. Run:

Fix
source ~/.zshrc

# Still not found? Check the alias is in the file:
grep "clauded" ~/.zshrc

# If nothing prints, the alias wasn't saved. Repeat Step 1.
"Invalid JSON" when validating settings.json

Open the file and check for common mistakes:

Fix
open ~/.claude/settings.json

Common issues: missing comma after a line, extra comma after the last item in a list, mismatched brackets or quotes.

XcodeBuildMCP tools not found in a session

Make sure you installed it with claude mcp add (Step 4b), not just npm. Close your Claude session and open a new one — the MCP server loads on session start.

Claude still asks for permission on allowed commands

Some commands may not match the whitelist patterns exactly. Add them:

Fix
open ~/.claude/settings.json

# Add the command to the "allow" array, e.g.:
# "Bash(swiftlint:*)"
# Save and restart Claude Code.
Claude modified my .pbxproj despite CLAUDE.md

Rare but possible. This is exactly why Step 1 exists:

Fix
git reset --hard HEAD

Then add a stronger instruction to your CLAUDE.md. You can also add a deny rule: "Edit(**/*.pbxproj)"

Docker container can't access Claude credentials

Make sure the mount paths are correct. The ~/.claude directory and ~/.claude.json file must exist on your host before mounting:

Fix
ls ~/.claude.json   # Should exist
ls ~/.claude/       # Should exist

# If missing, log in to Claude first outside the container:
claude
Hooks not firing / not blocking commands

Check that your hooks are in the correct location and have the right structure:

Fix
# Validate your settings.json
python3 -c "import json; json.load(open('$HOME/.claude/settings.json')); print('Valid JSON')"

# Make sure hooks key is at the top level, alongside permissions
# NOT nested inside permissions

Also verify the hook command works standalone: copy the "command" value and run it directly in terminal with a test input.

Context window full — Claude losing track of earlier work

Large iOS projects fill context quickly. Solutions:

Fix
# Inside a Claude session:
/compact    # Summarize and free context

# Or start a fresh session for the next subtask
# Claude reads CLAUDE.md at session start, so context resets cleanly

Tip: scope tasks to one module at a time. "Add login to the Auth module" is better than "refactor the whole app."

🔮

Xcode 26.3 Agentic Coding

Xcode 26.3 (February 2026) introduced agentic coding — a major leap beyond autocomplete and chat. Agents can explore your project, build, run tests, fix errors, and capture Xcode Previews for visual verification.

What's new in Xcode 26.3

FeatureDetails
Claude Agent SDKNative integration — the same engine powering Claude Code, now built into Xcode
OpenAI CodexAlso supported alongside Claude
Agent Activity paneTransparent log of every file accessed, command run, and decision made
MCP supportXcode exposes capabilities via MCP — XcodeBuildMCP auto-detects scheme and simulator
One-click setupXcode Settings → Intelligence → add your API key and select a model
💡 This guide still applies: Even with Xcode 26.3's native integration, the guardrails in this guide (git checkpoints, CLAUDE.md rules, hooks) add an extra safety layer. The two approaches complement each other — use Xcode's built-in agent for IDE-integrated work and Claude Code CLI for terminal-based automation.