blake@xcode:~/Projects$ cat ios-agent-development.md

AIエージェントでiOSアプリを構築する:実践者向けガイド

# AIエージェントでiOSアプリ開発を高速化します。Claude Code、Codex CLI、Xcode 26.3ネイティブ、MCP、CLAUDE.mdパターン、hooks、8つのアプリから得た教訓。

words: 4085 read_time: 57m updated: 2026-06-08 21:24
$ less ios-agent-development.md

TL;DR: iOS向けにコードを生成できる agent runtime は、今では3つあります。MCP付きの Claude Code CLI、MCP付きの Codex CLI、そして Xcode 26.3 のネイティブ Intelligence agents です。2つの MCP server(59個の tool を備えた XcodeBuildMCP と、20個の tool を備えた Apple の xcrun mcpbridge)により、agent は build、test、simulator、debugging へ構造化された形でアクセスできます。このガイドでは、実際の CLAUDE.md pattern、hook 設定、何が機能し何が壊れるのかの率直な評価を扱います。内容は、合計293個の Swift file からなる8本の production iOS app で得た経験に基づいています。23 Agent は SwiftUI view、SwiftData model、refactoring、build error の診断を得意とします。一方で、.pbxproj の変更、code signing、visual debugging は苦手です。「agent が Swift を書く」ことと「agent が iOS app を出荷する」ことの差は、prompting ではなく configuration によって埋まります。WWDC 2026(6月8日)時点で iOS 27 は beta であり、agent に関係する framework(Foundation Models の tool-calling control、App Intents の background execution、新しい Core AI と Evaluations framework)が追加されています。2026年6月以前に学習された model はこれらを知らないため、agent の context には明記しておく価値があります。

私は AI coding agent を使って8本の iOS app を作ってきました。prototype ではありません。App Store に公開され、HealthKit integration、Metal shader、SpriteKit physics、iCloud sync、Live Activities、Game Center leaderboard、iOS、watchOS、tvOS にまたがる multi-platform target を備えた app です。これらの app の Swift は、すべて agent が書いて私が review したもの、または私が書いて agent が refactor したものです。私の見積もりでは、行単位の著作の大半は agent が担いました。私は review、scope、人間の判断が必要な部分(visual polish、signing、performance tuning、App Store submission)を担当しました。

このガイドは、私が始めたときに欲しかった reference です。どの agent runtime を使うべきか、構造化された build access のために MCP server をどう設定するか、CLAUDE.md に何を書くべきか、agent が Xcode project を壊さないようにする hook、そして何より重要な、agent が失敗し自分でハンドルを握る必要がある場所まで、full stack を扱います。

重要ポイント

AI agent が初めての iOS developer 向け:

  • Claude Code CLI + XcodeBuildMCP から始めましょう。 もっとも成熟した runtime であり、MCP tool coverage も最も深いです。2つの command を install し、project に CLAUDE.md を追加すれば、error message を手で copy しなくても agent が build、test、debug できます。
  • agent に .pbxproj を変更させてはいけません。 これが最も重要な rule です。.pbxproj.xcodeproj/ への write を block する PreToolUse hook があれば、何時間もの復旧作業を避けられます。
  • CLAUDE.md は agent の onboarding document です。 ここに時間をかけるほど、その project に触れるすべての agent session で元が取れます。

既に agent を使っていて、workflow に iOS を追加する人向け:

  • MCP は iOS build loop を変えます。 MCP 以前の agent は Swift を書けても、compile できるかを verify できませんでした。XcodeBuildMCP があれば、agent は code を書き、build し、構造化された error を読み、修正し、test を実行できます。しかも自律的にです。
  • 3つの runtime は用途が異なります。 深い agentic session には Claude Code CLI、headless batch work には Codex CLI、IDE を離れずに素早く inline fix するには Xcode 26.3 native agents が向いています。
  • hook infrastructure はそのまま活かせます。 既存の PostToolUse formatter、PreToolUse blocker、test runner hook は、path を少し調整するだけで iOS project でも同じように機能します。

AI-assisted iOS development を評価している team lead 向け:

  • agent の有効性は project size ではなく project documentation に比例します。 詳細な CLAUDE.md がある63 file の app は、何もない14 file の app よりも良い agent output を生みます。
  • .pbxproj の境界は交渉不可です。 Agent は Xcode project file を安定して編集できません。workflow では、Xcode target への手動 file 追加を前提にする必要があります。
  • 率直な ROI: agent は、よく document 化された project では実装の大部分を担えます。これは、3時間の agent-assisted work で出荷した15 file の TV app からも見て取れます(case study は後述)。残る作業、つまり visual polish、signing、performance tuning、App Store submission には人間の判断が必要です。

目的別の読み方

必要なこと 読む場所
初めて MCP を設定する MCP Setup: The Complete Configuration — 両方の server を install し、verify し、agent を設定します
iOS project 用の CLAUDE.md を書く CLAUDE.md Patterns for iOS Projects — 8本の app から得た実例です
3つの agent runtime を比較する Three Agent Runtimes for iOS — Claude Code vs. Codex vs. Xcode native
agent ができること、できないことを理解する What Agents Do WellWhat Agents Do Poorly
iOS development 用の hook を設定する Hooks for iOS Development — format-on-save、.pbxproj protection、test runner
深い reference(この page) このまま読み進めてください。setup から advanced pattern まで扱います

このガイドの使い方

これは3,000行を超える reference です。経験値に合うところから始めてください。

経験 ここから始める 次に読む
iOS + agents が初めて PrerequisitesMCP SetupYour First Agent Session CLAUDE.md Patterns, What Works/Doesn’t
iOS developer だが agents は初めて Three RuntimesMCP SetupCLAUDE.md Hooks, Architecture Patterns
agent user だが iOS は初めて Architecture PatternsWhat Agents Do PoorlyCLAUDE.md Framework-Specific Context, Advanced Workflows
両方に慣れている Advanced WorkflowsHooksMulti-Platform Patterns Runtime Comparison, The Portfolio

目次

  1. The Portfolio: 8 Apps, 293 Files
  2. Prerequisites
  3. Three Agent Runtimes for iOS
  4. MCP Setup: The Complete Configuration
  5. CLAUDE.md Patterns for iOS Projects
  6. Your First Agent Session
  7. What Agents Do Well in iOS
  8. What Agents Do Poorly in iOS
  9. Hooks for iOS Development
  10. Architecture Patterns That Work with Agents
  11. Framework-Specific Context
  12. Multi-Platform Patterns
  13. Advanced Workflows
  14. Real-World Case Studies
  15. Project Lifecycle with Agents
  16. Configuring Agent Definitions
  17. Testing Patterns for Agent-Assisted iOS
  18. Context Window Management for iOS Projects
  19. Troubleshooting
  20. Common Agent Mistakes in iOS
  21. The Honest Assessment
  22. FAQ
  23. Quick Reference Card
  24. References

関連リソース

Topic Resource
Xcode 向け MCP setup(短めの blog post) Two MCP Servers Made Claude Code an iOS Build System
Claude Code CLI の完全 reference Claude Code CLI: The Complete Guide
Codex CLI reference Codex CLI: The Complete Guide
hook system の deep dive Anatomy of a Claw: 84 Hooks as an Orchestration Layer
agent architecture pattern Agent Architecture Guide
Mac desktop app + Remote Control Claude Code Mac Desktop + Remote Control: A CLI User’s Guide

Apple Ecosystem Series。 Apple Intelligence、MCP、Foundation Models、Vision、Core ML、iOS 26 framework stack と統合する SwiftUI app についての production post 21本です。Water、Get Bananas、Return、そして941 portfolio の他の app から得た内容です。

Series hub: Apple Ecosystem Series

Agentic Apple (E4):

Topic Resource
Apple Intelligence の intent surface App Intents Are Apple’s New API to Your App
iOS app と並走する MCP server Two Agent Ecosystems, One Shopping List
どちらをいつ使うか App Intents vs MCP Tools: The Routing Question
runtime feature と tooling としての on-device LLM Foundation Models + Agentic Workflow
Apple development 向け hooks Hooks for Apple Development
cross-process state Single Source of Truth: SwiftData + MCP + iCloud

Frameworks (E2/E3):

Topic Resource
Foundation Models on-device LLM Foundation Models On-Device LLM
Vision framework(CV primitives) Vision Framework: What’s Built In
Core ML inference pattern Core ML On-Device Inference
RealityKit の spatial mental model RealityKit and the Spatial Mental Model
SwiftUI internals What SwiftUI Is Made Of
Symbol Effects animation vocabulary Symbol Effects: SwiftUI’s Built-In Animation Vocabulary
iOS 26+ の Liquid Glass Liquid Glass in SwiftUI: Three Patterns

Shipped-code (E1):

Topic Resource
Live Activities state machine Live Activities State Machine
watchOS runtime contract watchOS Runtime Contract
SwiftData schema discipline SwiftData Schema Discipline
HealthKit + SwiftUI pattern HealthKit + SwiftUI on iOS 26
Multi-platform SwiftUI Five Apple Platforms, Three Shared Files
XcodeBuildMCP integration Two MCP Servers, One Xcode Project

Synthesis (E5):

Topic Resource
iOS app の3つの surface The Three Surfaces of an iOS App
platform target decisions The Apple Platform Matrix
私が書くことを拒むもの What I Refuse to Write About

iOS 27とWWDC 2026: Agentが新たに利用できるもの

WWDC 2026(2026年6月8日)で、iOS 27がbetaになりました。このガイドで扱うAgent開発ワークフローは変わりません。引き続きMCP経由でClaude Code、Codex、またはXcodeのIntelligence agentsを操作し、CLAUDE.mdを書き、破壊的な操作はhooksで制御します。変わるのは、Agentがコードを書く対象となる領域です。iOS 27にはAgentに関係する新しいframeworkがいくつか含まれています。実務上は、coding agentにそれらを明示的に指定するのが重要です。2026年6月より前に学習されたモデルは、それらの存在を知らないためです。iOS 26は引き続き出荷版です。以下の項目は、iOS 27 beta SDK向けにビルドする場合のターゲットとして扱ってください。

Agentに関係するiOS 27の領域と、それぞれの詳細参照は次のとおりです。

  • Foundation Modelsにtool-calling制御が追加されました。 GenerationOptions.ToolCallingModeにより、オンデバイスモデルがツールをどの程度積極的に呼び出すかをリクエスト単位で調整できます。また、このframeworkは初回呼び出し後にモードを切り替え、リクエスト内のツール利用を制限できます。Vision frameworkには、認識コードを書かずにLanguageModelSessionへ接続できる既製のOCRToolBarcodeReaderToolも含まれるようになりました。詳しくはFoundation Models in iOS 27: Tool-Calling Controlをご覧ください。12
  • App Intentsが30秒の壁を越えました。 LongRunningIntent(進捗報告が必要なperformBackgroundTask(options:operation:)経由)は、同期、ファイル処理、オンデバイス推論のためにintentのバックグラウンド実行時間を延長します。SyncableEntityAppEntityにデバイス間で共有できるidentityを与えます。IndexedEntityQueryでは、システムがqueryにSpotlight indexの修復を依頼できます。詳しくはApp Intents in iOS 27: Background, Sync, Spotlightをご覧ください。13
  • Core AIはApple Silicon上でモデルを実行するための新しいframeworkです。 Appleのsystem modelではなく独自モデルを使うケースでは、Foundation Modelsより下の層に位置します。詳しくはCore AI: Running Models on Apple Siliconをご覧ください。14
  • Evaluationsはモデル品質のためのXCTestです。 テストスイートの一部としてモデル出力品質を測定する新しいframework(macOS 27)です。Agentの支援で構築したAI機能を出荷するために欠けていた要素となります。詳しくはEvaluations: XCTest for Model Qualityをご覧ください。15
  • SwiftData、HealthKit、SwiftUIも進化しました。 SwiftDataにはiOS 27でobservationとhistoryが追加されます。HealthKitにはworkout zonesと新しいtypesが追加されます。SwiftUIのiOS 27追加分は、例年どおり幅広い領域に及びます。詳しくはSwiftData in iOS 27HealthKit in iOS 27What’s New in SwiftUI for iOS 27をご覧ください。16

運用上の教訓は、このガイド全体で述べていることと同じです。Agentがコードを書きますが、不足している知識を与えるのは人間です。iOS 27 betaでは、promptやCLAUDE.mdでこれらのframework名を明示し、AppleのdocumentationへAgentを誘導する必要があります。そうしないと、モデルは各APIについてiOS 26の形を前提にしてしまいます。このガイドのその他の内容(runtimes、MCP、hooks、failure modes)は、iOS 27向けの作業でも変わりません。


Portfolio: 8つのアプリ、293ファイル

設定に入る前に、このガイドの根拠となる内容を示します。これらはtoy projectではありません。5つのApple framework、3つのplatformにまたがり、14ファイルのworkout trackerから63ファイルのmulti-platform meditation timerまで、iOSの複雑さを幅広く含んでいます。

App Stack Files Complexity
Banana List SwiftUI + SwiftData + iCloud Drive sync + Claude Desktop向けMCP server 53 Full CRUD、iCloud sync、アプリのdataをClaude Desktopに公開するcustom MCP server
Ace Citizenship SwiftUI study app + FastAPI backend 26 Client-server、REST API integration、quiz engine
TappyColor SpriteKit color matching game 30 Game loop、physics、touch handling、particle effects
Return Zen meditation timer — iOS 26+、watchOS、tvOS 63 HealthKit、Live Activities、Watch extended runtime、TV focus navigation、iCloud session sync
amp97 Metal shaders + audio visualization 41 Custom Metal render pipeline、audio analysis、real-time GPU compute
Reps SwiftUI + SwiftData workout tracking 14 Minimal viable app、clean SwiftData patterns
Water SwiftUI + SwiftData + Metal + HealthKit hydration tracking 34 Metal fluid simulation、HealthKit water intake logging、widget
Starfield Destroyer SpriteKit + Metal space shooter 32 99 levels、8 ships、Game Center leaderboards、Metal post-processing

ファイル数が重要な理由: Agentの有効性は、project sizeではなくproject legibilityと相関します。Return(63 files)はamp97(41 files)よりも良いAgent出力を生みます。Returnにはfile annotations、architecture diagrams、explicit patternsを含む詳細なCLAUDE.mdがあるためです。amp97のMetal shadersは、documentation qualityに関係なく、Agentにとって本質的に推論が難しい領域です。


前提条件

iOS開発向けのAgent runtimeを設定する前に、次を確認してください。

App Store Connectの期限: 2026年4月28日以降、App Store Connectへのアプリuploadは、Xcode 26以降を使い、iOS 26、iPadOS 26、tvOS 26、visionOS 26、またはwatchOS 26向けのSDKsでビルドする必要があります。17(macOSの提出はこの要件の対象外です。)チームがまだXcode 16.xを使っている場合、このガイドのAgent-assisted toolchainは移行を促す強制力にもなります。いずれにしても、以下のMCP serversはXcode 26.3+なしでは動作しません。

必須: - macOS 15+(Sequoia)またはmacOS Tahoe - Xcode 26.3+がインストールされ、設定済みであること(xcrun mcpbridgeの下限)。Agent workflowの改善、つまりcoding assistantのmessage queuingとclarifying-question supportに加え、Swift Testing image attachments、recorded-issue severity、crashlogs付きUI-test crash warnings、String Catalog editor improvementsを利用するには、Xcode 26.5+を推奨します。これらは26.4で初めて追加されました。1819 Xcode 26.5(2026年5月11日、build 17F42)が最新のstableです。26.4.1(2026年4月16日、build 17E202)は、26.4系最後のbug-fix releaseでした。20 - 少なくとも1つのiOS Simulator runtimeがインストールされていること - Anthropic API account(Claude Code用)またはOpenAI account(Codex用)

推奨: - SwiftFormatがインストール済み(brew install swiftformat)— format-on-save hooksで使用します - SwiftLintがインストール済み(brew install swiftlint)— 任意ですがstyle enforcementに有用です - terminalに慣れていること — 3つのruntimeはいずれもcommand lineから操作するか、command lineと統合して動作します

Xcodeのインストールを確認します:

# Check Xcode version
xcodebuild -version
# Expected: Xcode 26.3 or later (26.5+ recommended)

# Check available simulators
xcrun simctl list devices available
# Expected: at least one iPhone simulator

# Verify xcrun mcpbridge is available
xcrun mcpbridge --help
# Expected: usage information (not "command not found")

xcrun mcpbridgeが「command not found」を返す場合は、Xcode 26.3以降が必要です。App Storeまたはdeveloper.apple.comからXcodeをインストールまたは更新してください。注意: xcode-select --installでインストールされるのはCommand Line Toolsのみで、mcpbridgeは含まれません。完全なXcode.appが必要です。


iOSのための3つのエージェントランタイム

iOSのコードを書き、ビルドし、テストできる3つの異なるランタイムがあります。これらは互換性のあるものではなく、それぞれ異なる強み、異なるMCP統合パターン、そして異なる理想的なユースケースを持っています。

1. Claude Code CLI

概要: Anthropicによるターミナルベースのエージェント型コーディングアシスタントです。コードベースを読み込み、コマンドを実行し、ファイルを変更し、MCPを介して外部ツールに接続します。

MCP統合: XcodeBuildMCPとAppleのXcode MCPの両方を完全にサポートしています。エージェントはMCPプロトコルを介してツールを検出し、構造化されたパラメータで呼び出します。両サーバーで59 + 20のツールを利用できます。

セットアップ:

# Install Claude Code (if not already installed)
claude --version  # verify installation

# Add XcodeBuildMCP (59 tools — builds, tests, simulators, debugging)
claude mcp add XcodeBuildMCP \
  -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

# Add Apple Xcode MCP (20 tools — file ops, diagnostics, Swift REPL, previews)
claude mcp add --transport stdio xcode \
  -s user -- xcrun mcpbridge

代替手段 — xcodebuildmcp init 自動インストーラー(v2.1.0+、2026-02-23):

手動でのMCP設定を省略したい場合、XcodeBuildMCP v2.1.0+にはinitサブコマンドが用意されており、Claude Code、Cursor、またはCodexを自動検出してエージェントスキルとMCP設定を1ステップでインストールできます。

xcodebuildmcp init
# Or without a global install:
npx -y xcodebuildmcp@latest init

フラグ:--print(非対応クライアント向けに設定をstdoutに書き出す)、--uninstall(削除)。どのMCPサーバーをどのスコープで接続するかを明示的に制御したい場合は、これをスキップしてください。上記の手動のclaude mcp addコマンドを使えば、その制御が可能です。21

最適な用途: 深い実装セッション — 新機能の構築、複数ファイルにまたがるリファクタリング、複雑な問題のデバッグ、ビルド・テスト・修正ループの自律的な実行。Claude Codeの100万トークンのコンテキストウィンドウ(Opus 4.6使用時)により、エージェントはほとんどの小〜中規模のiOSプロジェクトを作業メモリ上に保持できます。私の経験では、ファイルサイズにもよりますが、おおよそ50ファイル程度までです。

典型的なセッション:

You: Add a new SettingsView with toggles for notifications and haptic feedback.
     Use the existing Settings.swift pattern from TimerManager.
     Build for simulator after implementation and fix any errors.

Claude: [reads Settings.swift, TimerManager.swift, existing views]
        [creates SettingsView.swift]
        [calls build_sim via MCP]
        [reads structured error: missing import HealthKit]
        [fixes import]
        [calls build_sim again  success, 0 errors, 1 warning]
        [calls test_sim  all tests pass]

MCP導入前のワークフローとの決定的な違いは、エージェントが手動でビルドしたりエラー出力を貼り付けたりするようユーザーに求めない点です。ビルド・エラー・修正のループは自律的に進行します。

2. Codex CLI

概要: OpenAIによるターミナルベースのコーディングエージェントです。Claude Codeと概念的には似ていますが、OpenAIモデル(GPT-4o、o3)を使用し、異なるパーミッションモデルを採用しています。

MCP統合: Codexはcodex mcp addコマンドでMCPをサポートしています。AppleのXcode MCPは直接動作します。

# Add Apple Xcode MCP to Codex
codex mcp add xcode -- xcrun mcpbridge

XcodeBuildMCPも同じnpxコマンドでCodexと連携できます。

# Add XcodeBuildMCP to Codex
codex mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp

最適な用途: ヘッドレスなバッチ操作、CI/CD統合、そして異なるモデルファミリーからのセカンドオピニオンを得たいタスクです。Codexのサンドボックスモードはコードを隔離された環境で実行するため、状態を変更するテストスイートの実行のような破壊的操作に有用です。

Claude Codeとの主な違い: - ClaudeモデルではなくOpenAIモデルを使用 - コンテキストウィンドウサイズとトークン経済性が異なる - サンドボックス優先のパーミッションモデル(デフォルトでより制限的) - MCPエコシステムが小規模(テスト済みのコミュニティサーバーが少ない) - Hooksシステムが利用可能(v0.119.0+)だがClaude Codeほど成熟していない — イベントタイプが少なく、条件付きifフィールドがない

iOS開発でClaude CodeよりCodexを使う場面:

モデルの多様性が欲しいときにCodexを使います。一方のエージェントが書いたコードをもう一方のエージェントがレビューすることで、異なる種類のエラーを発見できます。collabワークフロー(Claudeがビルドし、Codexがレビュー)はiOS開発において効果的です。あるモデルファミリーでは正しく見えるSwiftUIのパターンに、別のモデルファミリーが微妙な問題を見つけ出すことがあるからです。Metalシェーダーや並行処理パターンは特にデュアルモデルレビューの恩恵を受けます。

3. Xcode 26.3ネイティブエージェント

概要: AppleはAIコーディングエージェントをXcodeのIntelligenceパネルに直接統合しました。Xcode 26.3以降、Xcode Settings > IntelligenceでClaude AgentとCodexをインテリジェンスプロバイダとして設定できます。

セットアップ:

  1. Xcode 26.3+を開く
  2. Settings > Intelligenceに移動
  3. 新しいプロバイダを追加:
  4. Claudeの場合:「Claude Agent」を選択し、AnthropicのAPIキーを入力
  5. Codexの場合:「Codex」を選択し、OpenAIのAPIキーを入力
  6. エージェントがIntelligenceサイドバーに表示され、インラインで呼び出せるようになります

最適な用途: 素早いインライン編集、エージェントレベルの推論を伴うコード補完、そしてXcodeから離れたくない開発者向けです。ネイティブ統合により、エージェントはXcodeのプロジェクトコンテキスト — 開いているファイル、ビルドターゲット、スキーム設定 — にMCPブリッジなしで直接アクセスできます。

CLIエージェントと比較した制約: - フックシステムなし — フォーマット・オン・セーブの強制や.pbxprojへの書き込みブロックができない - CLAUDE.mdの読み込みなし — エージェントはプロジェクトレベルの設定ファイルを読まない - 自律性の制限 — エージェントは現在のファイルや選択範囲に対して動作し、プロジェクト全体には及ばない - サブエージェントの委譲なし — 複雑なマルチステップタスクを並列化できない - MCPサーバー設定なし — エージェントはXcode組み込みツールのみを使用

Xcodeネイティブエージェントを使う場面:

ターミナルへ切り替えるのが面倒な、素早く範囲が限定された編集向けです。「このモデルに計算プロパティを追加して」「この関数のユニットテストを書いて」「このビューを@Observableを使うようにリファクタリングして」といった、1〜2ファイルに触れるだけでビルド・テストサイクルを必要としないタスクに適しています。

ビルド、テスト、複数ファイルのリファクタリング、自律的なエラー修正が必要な作業には、MCPを備えたCLIエージェントを使用してください。

ランタイム比較マトリクス

機能 Claude Code CLI Codex CLI Xcode 26.3ネイティブ
MCPサポート フル(79ツール) フル(79ツール) Xcode組み込みツールのみ
フックシステム あり(成熟) あり(基本、v0.119.0+) なし
CLAUDE.md / プロジェクト設定 あり codex.md相当あり なし
自律的なビルド・テスト・修正 あり(MCP経由) あり(MCP経由) 部分的(インラインのみ)
サブエージェントの委譲 あり(最大10並列) なし なし
コンテキストウィンドウ 100万トークン(Opus 4.6) モデルによる プロバイダによる
複数ファイル操作 コードベース全体にアクセス可能 コードベース全体にアクセス可能 現在のファイル / 選択範囲
.pbxproj保護 フック経由 手動 N/A(Xcodeをネイティブに使用)
フォーマット・オン・セーブ PostToolUseフック経由 外部ツール Xcode設定
オフライン対応 なし なし なし
課金モデル Anthropic API利用料 OpenAI API利用料 プロバイダAPI利用料

推奨: プライマリランタイムとしてClaude Code CLIを使用してください。素早いインライン編集にはXcode 26.3ネイティブエージェントを使い、レビューパスとバッチ操作にはCodex CLIを使います。この3つは競合するのではなく、互いを補完します。


MCP セットアップ: 完全な設定

MCP(Model Context Protocol)は、エージェントを「Swiftを書き、ビルドはユーザー任せ」から「Swiftを書き、ビルドし、構造化されたエラーを読み取り、修正する」存在へ変えるものです。このセクションでは、ブログ記事よりも踏み込んで、2つのサーバー、すべてのインストール方法、検証、そしてツールが実際に使われるようにするエージェント設定を扱います。

XcodeBuildMCP: ヘッドレス iOS 開発のための59個のツール

XcodeBuildMCP は、xcodebuildxcrun simctl、LLDBを59個の構造化された MCP ツールとしてラップします。Xcodeを起動していなくても動作し、ビルド、テスト、デバッグの一連のサイクルをAppleのコマンドラインツール経由で完全にヘッドレスに実行できます。

インストール方法:

# Option 1: Via npx (recommended — always uses latest version)
claude mcp add XcodeBuildMCP \
  -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

# Option 2: Via Homebrew (pinned version, manual updates)
brew install xcodebuildmcp
claude mcp add XcodeBuildMCP \
  -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- xcodebuildmcp mcp

# Option 3: Project-scoped (omit -s user)
claude mcp add XcodeBuildMCP \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

-s user フラグを付けると、すべてのプロジェクトでサーバーをグローバルに利用できます。プロジェクト単位でインストールしたい場合は省略します(Webプロジェクトではなく、iOSプロジェクトだけで MCP を使いたい場合に便利です)。

-e XCODEBUILDMCP_SENTRY_DISABLED=true 環境変数は、クラッシュレポートのテレメトリを無効にします。XcodeBuildMCP にはデフォルトでSentryが含まれており、ファイルパスを含むエラーデータが送信されます。プロジェクトへの診断情報提供を希望しない限り、オプトアウトしましょう。1

全ツール一覧(8カテゴリにわたる59個のツール):

カテゴリ ツール 役割
プロジェクト検出 discover_projs, list_schemes, list_targets .xcodeproj/.xcworkspace ファイルを見つけ、利用可能なスキームとターゲットを一覧表示します
ビルド build_sim, build_device, build_mac ファイルと行ごとに整理された、構造化 JSON のエラー/警告出力付きでビルドします
テスト test_sim, test_device メソッドごとの成功/失敗結果付きでテストを実行します
Simulator ライフサイクル list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults Simulatorを作成、起動、管理、設定します
デバイス管理 list_devices, install_device, launch_device 実機へのデプロイと管理を行います
デバッグ debug_attach_sim, debug_attach_device, debug_breakpoint, debug_stack, debug_variables, debug_eval, debug_continue, debug_step, debug_detach ブレークポイントと変数検査を含む完全なLLDB統合です
UI自動化 snapshot_ui, screenshot, tap, swipe, type_text 自動操作とビジュアルキャプチャを行います
プロジェクトのひな形作成 create_project, add_file, add_package プロジェクトを作成し、依存関係を追加します

日々の作業で特に重要なツール:

  1. build_sim — 何百回も呼び出すことになります。ファイル、行、重要度ごとに分類されたエラーを JSON で返します。エージェントはエラーを読み取り、ファイルへ移動し、ユーザーが何もしなくても修正します。

  2. test_sim — テストメソッドごとの結果を返します。単に「テストが失敗した」ではなく、どのテストがなぜ失敗したのかをエージェントが正確に把握できます。

  3. list_sims + boot_simxcrun simctl のフラグを覚えなくてもSimulatorを管理できます。エージェントが利用可能なランタイムを検出し、適切なデバイスを選びます。

  4. discover_projs + list_schemes — プロジェクトの内省です。エージェントがスキーム名やワークスペース構造を推測する必要がありません。

  5. debug_attach_sim + debug_stack + debug_variables — リモートLLDBデバッグです。デバッガを開かなくても、エージェントがブレークポイントを設定し、変数を検査し、コードをステップ実行できます。

Apple Xcode MCP: Xcodeへ橋渡しする20個のツール

Appleの MCP サーバーは、Xcode 26.3に xcrun mcpbridge として同梱されています。XPC(Appleのプロセス間通信フレームワーク)を通じて実行中のXcodeプロセスと通信し、どの CLI ツールからもアクセスできない内部状態を公開します。

インストール:

# Standard installation (global)
claude mcp add --transport stdio xcode \
  -s user -- xcrun mcpbridge

# For Codex CLI
codex mcp add xcode -- xcrun mcpbridge

Xcode 26.3以降と、実行中のXcodeプロセスが必要です。 Xcodeが開いていない場合、このサーバー経由の MCP 呼び出しはすべて失敗するか、ハングします。XcodeBuildMCP にはこの制限がありません。

ツール一覧(5カテゴリにわたる20個のツール):

カテゴリ ツール 役割
ファイル操作 XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep Xcodeプロジェクトコンテキスト内でファイルを読み書きします
ビルドとテスト BuildProject, GetBuildLog, RunAllTests, RunSomeTests Xcodeの内部ビルドシステムでビルドとテストを実行します
診断 XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile リアルタイムのコード診断です(ビルドエラーだけではありません)
コードとドキュメント ExecuteSnippet, DocumentationSearch Swift REPLの実行とAppleドキュメント検索です
プレビュー RenderPreview ヘッドレスのSwiftUIプレビュー描画です

Apple MCP 固有のツール(XcodeBuildMCP では利用不可):

  1. DocumentationSearch — WWDCセッションを含むAppleの開発者ドキュメントを検索します。Apple API に関する疑問では、Web検索より高速で信頼性があります。「HKQuantityType(.dietaryWater) は有効ですか?」と尋ねれば、一次情報から確定的な答えを得られます。

  2. ExecuteSnippet — プロジェクトのコンテキスト内でSwift REPLを実行します。アプリ全体をビルドしなくても、エージェントが API の挙動を確認し、型変換をテストし、式を検証できます。

  3. RenderPreview — SwiftUIプレビューをヘッドレスに描画します。ビューがエラーなく描画されるかは確認できますが、視覚的な正しさは評価できません(描画結果は視覚的に検査されるのではなく、データとして返されます)。

  4. XcodeListNavigatorIssues — ビルドエラーだけでなく、Xcodeのアナライザーからリアルタイム診断を返します。未使用変数、潜在的なretain cycle、ビルドシステムでは表面化しない非推奨警告などを検出できます。

両方のサーバーが必要な理由

ビルドとテストでは重なる部分がありますが、根本的に異なります。

┌─────────────────────────────────────────────────────────────────┐
                     MCP TOOL COVERAGE                           
├─────────────────────────────────────────────────────────────────┤
                                                                 
  XcodeBuildMCP (59 tools)        Apple Xcode MCP (20 tools)    
  ┌─────────────────────┐         ┌─────────────────────┐       
   Standalone                     Requires Xcode             
   (no Xcode process)            (XPC bridge)               
                                                            
    Simulators          BOTH     Documentation            
    Real devices       ┌─────┐   Swift REPL               
    LLDB debugging     Build   SwiftUI previews         
    UI automation      Test    Live diagnostics         
    Project scaffold   └─────┘   Analyzer issues          
    Screenshot                                             
  └─────────────────────┘         └─────────────────────┘       
                                                                 
└─────────────────────────────────────────────────────────────────┘

XcodeBuildMCP を使う場面: ビルド、テスト、デバッグのサイクルです。Xcodeを開かなくても動作し、システムメモリの消費が少なく、Simulatorとデバイス管理がより充実しています。主力のビルドツールになります。

Apple Xcode MCP を使う場面: ドキュメント検索、Swift REPL検証、SwiftUIプレビュー描画、リアルタイム診断です。これらの機能が必要なセッションでは、Xcodeを開いたままにしておきます。

実際の使い分け: MCP 呼び出しの約90%ではXcodeBuildMCP を使い、ドキュメントとREPL検証ではApple Xcode MCP を使います。ビルドとテストでは、エージェントはデフォルトでXcodeBuildMCP を使います。こちらのほうが高速(Xcodeプロセスのオーバーヘッドがない)で、より安定している(XPCへの依存がない)ためです。

検証

両方のサーバーをインストールしたら、接続されていることを確認します。

# List all configured MCP servers
claude mcp list

# Expected output includes:
# XcodeBuildMCP: npx -y xcodebuildmcp@latest mcp - Connected
# xcode: xcrun mcpbridge - Connected

サーバーが「Disconnected」と表示される、または表示されない場合:

  1. XcodeBuildMCP が接続されない: Node.jsがインストールされていることを確認します(node --version)。npx コマンドにはNode.js 18以降が必要です。
  2. Apple Xcode MCP が接続されない: Xcode 26.3以降がインストールされており、ターミナルで xcrun mcpbridge コマンドが動作することを確認します。ライセンス契約に同意するため、少なくとも一度はXcodeを開いてください。
  3. どちらも表示されない: Claude Code を再起動します(新しいターミナルで claude)。セッション途中で登録された MCP サーバーは、再起動するまで表示されない場合があります。

エージェントに MCP の使い方を教える

MCP サーバーのインストールは必要ですが、それだけでは十分ではありません。明示的な指示がないと、エージェントはBash経由で xcodebuild を実行したり(非構造化出力でコンテキストトークンを浪費します)、Appleドキュメントの確認にWeb検索を使ったりする可能性があります(遅く、信頼性も下がります)。

CLAUDE.mdまたはエージェント定義に以下を追加します。

## Build & Test — Always Use MCP

Prefer MCP tools over raw shell commands for ALL build operations:

- **Build**: `build_sim` / `build_device` (NOT `xcodebuild` via Bash)
- **Test**: `test_sim` / `test_device` (NOT `xcodebuild test` via Bash)
- **Simulators**: `list_sims`, `boot_sim`, `open_sim` (NOT `xcrun simctl` via Bash)
- **Debug**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Apple docs**: `DocumentationSearch` (NOT WebSearch for Apple APIs)
- **Swift verification**: `ExecuteSnippet` (NOT `swift` via Bash)
- **Previews**: `RenderPreview` for headless SwiftUI verification

MCP returns structured JSON. Bash returns unstructured text.
Structured data means fewer tokens consumed and better error diagnosis.

この指示により、エージェントはまず MCP ツールを使うようになります。これがないと、エージェントがBashで長い xcodebuild コマンドを組み立て、出力の解析に何千ものコンテキストトークンを消費し、ときには実際のエラーを取り違える様子を見ることになります。


iOSプロジェクトのCLAUDE.mdパターン

CLAUDE.mdは、エージェント支援型開発においてプロジェクト内で最も重要なファイルです。エージェントのオンボーディング文書であり、アーキテクチャドキュメントを読んだ新入社員と、推測で進める新入社員ほどの差があります。

私が保守しているすべてのiOSプロジェクトにはCLAUDE.mdがあります。8つのアプリで得た、有効だったパターンを紹介します。

必須セクション

すべてのiOS向けCLAUDE.mdには、次の6つのセクションが必要です。それ以外は任意です。

1. プロジェクトの基本情報

# Return - Zen Focus Timer

**Bundle ID:** `com.941apps.Return`
**Target:** iOS 26+ / macOS Tahoe / watchOS 26+ / tvOS 26+
**Architecture:** SwiftUI with @Observable pattern, companion Watch and TV apps
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0

これが重要な理由: エージェントはコードを書く前に、デプロイメントターゲットを知る必要があります。iOS 17を対象にするエージェントはNavigationView@ObservedObjectを使います。iOS 26を対象にするエージェントはNavigationStack@Observableを使います。Bundle IDはentitlementsやHealthKit設定に関係します。Swiftのバージョンは並行処理モデル(async/awaitかcompletion handlerか、strict concurrencyかlenientか)を決めます。

2. 目的注釈付きファイル構成

## File Structure

```
Return/
├── ReturnApp.swift              # App entry, dark mode enforcement
├── ContentView.swift            # Main timer view with theme backgrounds
├── TimerManager.swift           # Timer state, logic, and repeat handling
├── AudioManager.swift           # Sound playback with AVAudioPlayer
├── Settings.swift               # Centralized settings with validation
├── SettingsSheet.swift          # Settings UI
├── HealthKitManager.swift       # Mindful session logging + cross-device sync
├── LiveActivityManager.swift    # Lock Screen/Dynamic Island
├── Theme.swift                  # Theme definitions
├── ThemeManager.swift           # Theme state management
├── VideoBackgroundView.swift    # AVPlayer video backgrounds
├── GlassTextShape.swift         # Core Text glyph paths for glass effect
├── GlassTimerText.swift         # Timer text with glass material
└── Constants.swift              # App constants
```

各ファイル名の後ろにあるインラインコメントは飾りではありません。書けるドキュメントの中で、最も効果が高いものです。エージェントが新機能をどこに追加するか判断するとき、この注釈があれば、プロジェクト構成を理解するために全ファイルを読むのではなく、最初の試行で正しいファイルにたどり着けます。

アンチパターン: 注釈なしでファイルだけを列挙すること。TimerManager.swiftだけでは、状態を扱うのか、UIを扱うのか、その両方なのかがエージェントには分かりません。TimerManager.swift # Timer state, logic, and repeat handlingなら、そこに属するものと属さないものが明確になります。

3. ビルドとテストのコマンド

## Build & Test

Build for iOS simulator:
```bash
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
```

Run tests:
```bash
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```

Run tvOS tests:
```bash
xcodebuild -scheme ReturnTV -destination 'platform=tvOS Simulator,name=Apple TV' test
```

**Prefer MCP tools** (`build_sim`, `test_sim`) over these raw commands.
MCP returns structured JSON with categorized errors.

エージェントはMCPを優先すべきですが、生のコマンドも含めてください。生のコマンドはフォールバック用ドキュメントとして機能し、scheme名とdestinationを明示できます。

4. 主要パターンとルール

## Key Patterns

### Observable Architecture
- ALL view models use `@Observable` (NEVER `ObservableObject`)
- ALL navigation uses `NavigationStack` (NEVER `NavigationView`)
- State management via `@Observable` classes with `@MainActor` isolation

### Settings Pattern
- Centralized `Settings.shared` singleton
- All settings bounded to valid ranges with validation
- Sound names validated against whitelist
- Thread-safe access via @MainActor

### Audio System
- `AVAudioPlayer` with `.playback` category (plays in silent mode)
- Silent audio loop for background execution
- Bell playback with completion callbacks and token-based staleness

これらのパターンにより、エージェントが一貫性のない実装を持ち込むのを防げます。明示的なパターンドキュメントがないと、エージェントはあるファイルではObservableObjectを使い、別のファイルでは@Observableを使ったり、既存のSettings.shared singletonを使わず新しい設定機構を作ったりすることがあります。

5. エージェントが絶対にしてはいけないこと

## Rules

- **NEVER modify .pbxproj files** — create Swift files, then I will add them to Xcode manually
- **NEVER modify .xcodeproj/ contents directly**
- **NEVER add new package dependencies** without asking first
- **NEVER change the deployment target**
- **NEVER modify entitlements files** unless explicitly asked
- **NEVER use NavigationView** — always NavigationStack
- **NEVER use ObservableObject** — always @Observable
- **NEVER use @StateObject** — always @State with @Observable

明示的な禁止事項は、暗黙の期待よりも効果的です。エージェントは肯定的な提案よりも否定的な制約のほうが安定して守ります。禁止事項は二値的(やる / やらない)であり、ヒューリスティック(これを優先する / 場合によってはあれを使う)ではないためです。

6. フレームワーク固有のコンテキスト

このセクションはアプリによって変わります。分かりにくい設定があるフレームワークでは含めてください。

HealthKitアプリの場合:

## HealthKit Configuration

- Entitlement: `com.apple.developer.healthkit`
- Info.plist keys:
  - `NSHealthShareUsageDescription`: "Return reads your mindful minutes..."
  - `NSHealthUpdateUsageDescription`: "Return logs meditation sessions..."
- Category types: `HKCategoryType(.mindfulSession)`
- Authorization checked on every write (user can revoke at any time)
- HealthKit is unavailable on tvOS — guard with `#if canImport(HealthKit)`

SwiftDataアプリの場合:

## SwiftData Models

### Model Relationships
- `GroceryList` has many `GroceryItem` (cascade delete)
- `GroceryItem` belongs to one `GroceryList`
- `GroceryItem` has optional `Category`

### Model Container Setup
- Configured in App struct with `modelContainer(for:)`
- Schema versioning: currently V2
- Migration plan: `GroceryMigrationPlan` handles V1 → V2

### Queries
- `@Query(sort: \GroceryItem.name)` for sorted fetches
- `@Query(filter: #Predicate { !$0.isCompleted })` for active items
- Always use `@Query` in views, `modelContext.fetch()` in managers

SpriteKitアプリの場合:

## SpriteKit Scene Hierarchy

```
GameScene (SKScene)
├── backgroundLayer (SKNode, zPosition: -100)
│   └── StarfieldNode (custom, parallax scrolling)
├── gameLayer (SKNode, zPosition: 0)
│   ├── playerShip (PlayerNode, zPosition: 10)
│   ├── enemyContainer (SKNode, zPosition: 5)
│   └── bulletPool (SKNode, zPosition: 8)
├── effectsLayer (SKNode, zPosition: 50)
│   └── ParticleManager (manages explosion/trail emitters)
└── hudLayer (SKNode, zPosition: 100)
    ├── scoreLabel (SKLabelNode)
    └── healthBar (HealthBarNode)
```

- Physics categories defined in `PhysicsCategory.swift` as bitmasks
- Contact detection via `didBegin(_ contact:)` on GameScene
- Bullet pooling: pre-allocate 50, recycle via `removeFromParent()` + re-add

Metalアプリの場合:

## Metal Pipeline

- Render pipeline: `MetalView``Renderer``ShaderLibrary`
- Compute pipeline: `AudioAnalyzer` → compute shader → texture output
- Shared uniforms struct: `Uniforms` in `ShaderTypes.h` (bridged to Swift)
- Frame timing: `CADisplayLink` drives render loop
- Buffer triple-buffering: 3 in-flight frames with semaphore

### Shader Files
- `Shaders.metal` — Main render shaders (vertex + fragment)
- `Compute.metal` — Audio analysis compute kernel
- `PostProcess.metal` — Bloom and color grading

### DO NOT modify Metal shaders without testing on device.
Simulator Metal is not representative of device GPU behavior.

実際のCLAUDE.md: Banana List(SwiftUI + SwiftData + iCloud + MCP Server)

6つのセクションがどのように連携するかを示す、注釈付きの例です。これはBanana Listで使っているCLAUDE.mdパターンです。Banana Listは、iCloud syncと、アプリのデータをClaude Desktopへ公開するカスタムMCP serverを備えた、53ファイル構成の買い物リストアプリです。

# Banana List - Grocery List App

**Bundle ID:** `com.941apps.BananaList`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData + iCloud Drive sync
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0

## Core Features

- Grocery lists with items, categories, and quantities
- iCloud Drive sync via SwiftData CloudKit integration
- Custom MCP server exposing list data to Claude Desktop
- Liquid Glass design system
- Haptic feedback on interactions
- Share sheets for list sharing

## File Structure

```
BananaList/
├── BananaListApp.swift           # App entry, model container setup
├── Models/
│   ├── GroceryList.swift         # @Model: list with name, items, color
│   ├── GroceryItem.swift         # @Model: item with name, quantity, category, isCompleted
│   ├── Category.swift            # @Model: user-defined categories
│   └── SampleData.swift          # Preview and test data
├── Views/
│   ├── ListsView.swift           # Main list of grocery lists
│   ├── ListDetailView.swift      # Items within a list
│   ├── ItemRow.swift             # Single item row with swipe actions
│   ├── AddItemSheet.swift        # New item form
│   ├── CategoryPicker.swift      # Category selection with create-new
│   └── SettingsView.swift        # App settings
├── Managers/
│   ├── CloudSyncManager.swift    # iCloud Drive sync status and conflict resolution
│   └── HapticManager.swift       # UIImpactFeedbackGenerator wrapper
├── MCP/
│   ├── MCPServer.swift           # MCP server for Claude Desktop integration
│   ├── ListTools.swift           # MCP tools: list CRUD operations
│   └── ItemTools.swift           # MCP tools: item CRUD operations
└── Extensions/
    ├── Color+Extensions.swift    # Custom color definitions
    └── View+Extensions.swift     # Reusable view modifiers
```

## SwiftData Models

### Relationships
- `GroceryList` has many `GroceryItem` (cascade delete)
- `GroceryItem` belongs to one `GroceryList` (required)
- `GroceryItem` has optional `Category`
- `Category` has many `GroceryItem` (nullify on delete)

### Container Setup
```swift
@main
struct BananaListApp: App {
    var body: some Scene {
        WindowGroup {
            ListsView()
        }
        .modelContainer(for: [GroceryList.self, GroceryItem.self, Category.self])
    }
}
```

### Query Patterns
- Lists: `@Query(sort: \GroceryList.name) var lists: [GroceryList]`
- Active items: `@Query(filter: #Predicate { !$0.isCompleted })`
- By category: filter in-memory after fetch (SwiftData predicate limitations)

## Build & Test

```bash
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```

Prefer MCP tools (`build_sim`, `test_sim`) over raw commands.

## Key Patterns

### Observable + SwiftData
- SwiftData `@Model` classes are automatically Observable
- DO NOT add `@Observable` to `@Model` classes (redundant, causes warnings)
- Use `@Bindable` for two-way bindings to model properties in forms
- Use `@Query` in views, `modelContext.fetch()` in non-view code

### iCloud Sync
- Automatic via SwiftData CloudKit integration
- Conflict resolution: last-write-wins (CloudKit default)
- Sync status exposed via `CloudSyncManager.shared.syncState`
- Test sync by running on two simulators with same iCloud account

### MCP Server Architecture
- Runs as a local WebSocket server on port 8765
- Exposes 6 tools: listAll, getList, createList, addItem, completeItem, deleteItem
- Claude Desktop connects via MCP config in `~/.config/claude-desktop/config.json`

## Rules

- NEVER modify .pbxproj or .xcodeproj contents
- NEVER change the model schema without updating SampleData.swift
- NEVER use `ObservableObject` — SwiftData models are already Observable
- NEVER use `@StateObject` — use `@State` with `@Observable` classes
- NEVER use `NavigationView` — always `NavigationStack`
- NEVER add `@Observable` macro to `@Model` classes
- ALWAYS use `@Bindable` for form bindings to model properties
- ALWAYS test iCloud sync changes on two simulator instances

実際のCLAUDE.md: Reps(最小構成のSwiftDataアプリ — 14ファイル)

小規模プロジェクトでは、CLAUDE.mdは簡潔で構いません。ここでは、14ファイル構成のワークアウト記録アプリRepsのパターンを示します。短いCLAUDE.mdでも、6つの必須セクションをすべて押さえている点に注目してください。

# Reps - Workout Tracking

**Bundle ID:** `com.941apps.Reps`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData
**Swift version:** 6.2

## File Structure

```
Reps/
├── RepsApp.swift              # App entry, model container
├── Models/
│   ├── Workout.swift          # @Model: workout with exercises, date, duration
│   ├── Exercise.swift         # @Model: exercise with sets, reps, weight
│   └── ExerciseTemplate.swift # @Model: saved exercise definitions
├── Views/
│   ├── WorkoutListView.swift  # Main list of workouts
│   ├── WorkoutDetailView.swift # Exercises within a workout
│   ├── ExerciseRow.swift      # Single exercise with inline editing
│   ├── AddExerciseSheet.swift # Exercise selection from templates
│   ├── NewWorkoutView.swift   # Start new workout flow
│   └── StatsView.swift        # Progress charts and summaries
├── Managers/
│   └── WorkoutTimer.swift     # Active workout timer
└── Extensions/
    └── Date+Extensions.swift  # Formatting helpers
```

## Build & Test

```bash
xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```

## SwiftData Relationships

- `Workout` has many `Exercise` (cascade delete)
- `Exercise` has optional `ExerciseTemplate`
- `ExerciseTemplate` standalone (nullify on exercise delete)

## Rules

- NEVER modify .pbxproj
- NEVER use ObservableObject — use @Observable
- NEVER use NavigationView — use NavigationStack
- @Model classes are already Observable — do not add @Observable macro
- Use @Bindable for form bindings to model properties

14ファイルのプロジェクトに対して、CLAUDE.mdは40行です。書くのに10分しかかからず、エージェントの混乱を何時間分も減らせます。

実際のCLAUDE.md: Starfield Destroyer(SpriteKit + Metal — 32ファイル)

ゲームプロジェクトでは、より多くのフレームワーク固有コンテキストが必要です。エージェントはscene graph、physics category、ゲーム状態マシンを理解する必要があります。

# Starfield Destroyer - Space Shooter

**Bundle ID:** `com.941apps.StarfieldDestroyer`
**Target:** iOS 26+
**Architecture:** SpriteKit + Metal post-processing + Game Center
**Swift version:** 6.2

## Game Overview

99 levels across 3 galaxies. 8 unlockable ships with different stats.
Game Center leaderboards and achievements. Metal shader post-processing
for bloom and screen effects.

## File Structure

```
StarfieldDestroyer/
├── StarfieldDestroyerApp.swift    # App entry, Game Center auth
├── GameScene.swift                # Main game scene, update loop
├── MenuScene.swift                # Title screen, ship selection
├── Entities/
│   ├── PlayerShip.swift           # Player node with physics, weapons, shields
│   ├── EnemyShip.swift            # Enemy base class with AI behaviors
│   ├── Bullet.swift               # Bullet pool node
│   ├── PowerUp.swift              # Collectible power-ups
│   └── Boss.swift                 # Boss enemies (levels 33, 66, 99)
├── Systems/
│   ├── LevelManager.swift         # Level progression, wave spawning
│   ├── PhysicsCategory.swift      # UInt32 bitmask categories
│   ├── CollisionHandler.swift     # Contact delegate methods
│   ├── ScoreManager.swift         # Score tracking, multipliers
│   ├── ParticleManager.swift      # Explosion, trail, shield emitters
│   └── AudioManager.swift         # Sound effects, background music
├── UI/
│   ├── HUDNode.swift              # Score, health, level display
│   ├── ShipSelectView.swift       # SwiftUI ship selection (UIHostingController)
│   ├── GameOverView.swift         # Game over screen with score submission
│   └── PauseMenu.swift            # Pause overlay
├── Metal/
│   ├── MetalRenderer.swift        # Post-processing render pipeline
│   ├── BloomShader.metal          # Bloom post-process effect
│   └── ShaderTypes.h              # Shared uniforms (bridging header)
├── Data/
│   ├── ShipData.swift             # 8 ship definitions (speed, damage, shields)
│   ├── LevelData.swift            # 99 level configurations
│   └── AchievementData.swift      # Game Center achievement definitions
└── GameCenterManager.swift        # Leaderboard/achievement submission
```

## SpriteKit Scene Hierarchy

```
GameScene (SKScene)
├── backgroundLayer (zPosition: -100)
│   └── StarfieldNode (parallax scrolling, 3 layers)
├── gameLayer (zPosition: 0)
│   ├── playerShip (zPosition: 10)
│   ├── enemyContainer (zPosition: 5)
│   ├── bulletPool (zPosition: 8) — pre-allocated 50 bullets
│   └── powerUpContainer (zPosition: 3)
├── effectsLayer (zPosition: 50)
│   └── ParticleManager (explosion + trail emitters)
└── hudLayer (zPosition: 100)
    ├── scoreLabel (SKLabelNode)
    ├── healthBar (custom SKShapeNode)
    └── levelLabel (SKLabelNode)
```

## Physics Categories

```swift
struct PhysicsCategory {
    static let none:      UInt32 = 0
    static let player:    UInt32 = 0b1        // 1
    static let enemy:     UInt32 = 0b10       // 2
    static let bullet:    UInt32 = 0b100      // 4
    static let powerUp:   UInt32 = 0b1000     // 8
    static let shield:    UInt32 = 0b10000    // 16
    static let bossBullet:UInt32 = 0b100000   // 32
}

// Contact pairs:
// player + enemy → damage
// player + powerUp → collect
// bullet + enemy → destroy
// player + bossBullet → damage
```

## Game State Machine

```
.menu → .playing → .paused → .playing
                 → .gameOver → .menu
                 → .bossIntro → .playing
                 → .levelComplete → .playing (next level)
```

## Metal Post-Processing

- Bloom shader: `BloomShader.metal` — multi-pass Gaussian blur + additive blend
- Uniforms: `PostProcessUniforms { float intensity; float threshold; float2 resolution; }`
- Applied after SpriteKit renders each frame via `SKView.presentScene(:transition:)`
- DO NOT modify Metal shaders without testing on device

## Build & Test

```bash
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```

## Rules

- NEVER modify .pbxproj
- NEVER modify PhysicsCategory bitmasks (breaks all collision detection)
- NEVER change the scene hierarchy z-ordering without understanding render order
- NEVER modify ShaderTypes.h without updating both Swift and Metal references
- Add new enemies by subclassing EnemyShip, not by modifying it
- Bullet pooling: recycle via removeFromParent() + re-add, never allocate new
- Game Center: always check isAuthenticated before submitting scores

実際のCLAUDE.md: amp97(Metal + Audio Visualization — 41ファイル)

Metalプロジェクトでは、エージェントが視覚的な出力を検証できないため、最も多くのフレームワーク固有コンテキストが必要です。

# amp97 - Audio Visualizer

**Bundle ID:** `com.941apps.amp97`
**Target:** iOS 26+
**Architecture:** Metal render pipeline + AVAudioEngine analysis
**Swift version:** 6.2

## Architecture

```
Audio Input (microphone/file)
    → AVAudioEngine tap
    → FFT (vDSP)
    → Frequency/amplitude buffers
    → Metal compute shader (analysis)
    → Metal render pipeline (visualization)
    → CADisplayLink (60fps)
    → MTKView
```

## File Structure

```
amp97/
├── amp97App.swift               # App entry
├── Audio/
│   ├── AudioEngine.swift        # AVAudioEngine setup, tap installation
│   ├── FFTProcessor.swift       # vDSP FFT, frequency bin extraction
│   ├── AudioBuffer.swift        # Ring buffer for audio data
│   └── MicrophoneManager.swift  # Microphone permission, session config
├── Rendering/
│   ├── MetalView.swift          # MTKView wrapper for SwiftUI
│   ├── Renderer.swift           # Main render loop, pipeline state
│   ├── ShaderLibrary.swift      # Compiled shader management
│   ├── BufferManager.swift      # Triple-buffered uniform updates
│   └── TextureManager.swift     # Offscreen render targets
├── Shaders/
│   ├── Shaders.metal            # Vertex + fragment shaders
│   ├── AudioCompute.metal       # Audio analysis compute kernel
│   ├── PostProcess.metal        # Bloom, color grading
│   └── ShaderTypes.h            # Shared uniforms (bridging header)
├── Visualizations/
│   ├── WaveformViz.swift        # Oscilloscope-style waveform
│   ├── SpectrumViz.swift        # Frequency spectrum bars
│   ├── CircularViz.swift        # Radial visualization
│   └── VizSelector.swift        # Visualization switching
├── Views/
│   ├── MainView.swift           # Full-screen viz with overlays
│   ├── ControlsOverlay.swift    # Play/pause, viz selection, gain
│   └── SettingsView.swift       # Audio source, sensitivity
└── Extensions/
    ├── SIMD+Extensions.swift    # Vector math helpers
    └── Color+Metal.swift        # UIColor → float4 conversion
```

## Metal Pipeline

### Uniforms (ShaderTypes.h)
```c
typedef struct {
    float time;
    float2 resolution;
    float audioLevel;       // 0.0-1.0 RMS amplitude
    float frequencyBins[64]; // FFT output, normalized
    float4x4 transform;
} Uniforms;
```

### Render Pipeline
1. Compute pass: AudioCompute.metal processes FFT data → texture
2. Render pass: Shaders.metal reads texture + uniforms → visualization
3. Post-process pass: PostProcess.metal applies bloom → final output

### Buffer Management
- Triple buffering with DispatchSemaphore(value: 3)
- Uniforms updated per-frame on CPU, consumed by GPU 1-2 frames later
- Audio data ring buffer: 4096 samples, lock-free single producer/consumer

## Rules

- NEVER modify ShaderTypes.h without updating BOTH Swift and Metal sides
- NEVER exceed 64 frequency bins (fixed buffer size in shader)
- NEVER test Metal visual output in simulator — device only
- NEVER modify the audio engine tap format (48kHz, mono, float32)
- Triple buffer discipline: always signal semaphore in completion handler
- Audio session: .playAndRecord category with .defaultToSpeaker option

プロジェクト規模に応じたCLAUDE.mdの調整

適切な詳細度は、ファイル数とフレームワークの複雑さによって変わります。

プロジェクト規模 CLAUDE.mdの深さ
小規模(20ファイル未満) 基本情報 + ファイル一覧 + ルール Reps(14ファイル): 基本的なSwiftDataパターン、ビルドコマンド、禁止事項
中規模(20〜40ファイル) + フレームワークコンテキスト + 主要パターン TappyColor(30ファイル): SpriteKit scene hierarchy、physics category、game loop
大規模(40ファイル以上) + アーキテクチャ図 + 関係マップ + 複数ターゲット情報 Return(63ファイル): クロスプラットフォームアーキテクチャ、session sync図、プラットフォームごとの差分
特化型(Metal/GPU) + パイプライン図 + 共有型定義 + バッファレイアウト amp97(41ファイル): render pipeline stages、uniform struct、buffer management

ドキュメントを書きすぎるコストはほぼゼロです(エージェントは不要な部分を読み飛ばします)。一方、ドキュメント不足のコストは高くなります(エージェントがコードベースと衝突するパターンを作り出します)。

CLAUDE.mdチェックリスト

iOSプロジェクト向けCLAUDE.mdを作成または監査するときは、このチェックリストを使ってください。

  • [ ] Bundle IDとデプロイメントターゲットを明記している
  • [ ] Swiftバージョンとアーキテクチャパターンを明記している
  • [ ] ファイル構成にインラインの目的注釈がある
  • [ ] 正しいschemeとdestinationを使ったビルドコマンドがある
  • [ ] 正しいschemeとdestinationを使ったテストコマンドがある
  • [ ] MCPの優先方針を明記している(”prefer build_sim over xcodebuild”)
  • [ ] @Observableルールがある(ObservableObjectは使わない)
  • [ ] NavigationStackルールがある(NavigationViewは使わない)
  • [ ] .pbxprojの禁止事項がある
  • [ ] フレームワーク固有のコンテキストがある(HealthKit権限、SwiftData relationships、SpriteKit hierarchy、Metal pipeline)
  • [ ] プラットフォーム可用性ガードを記載している(#if canImport、#if os)
  • [ ] 主要なsingletonと共有パターンを記載している
  • [ ] 既知の制限や注意点を記載している

初めてのエージェントセッション

MCP を設定し、プロジェクトに CLAUDE.md を置いたら、効果的な初回セッションの流れは次のようになります。ここでは Claude Code CLI を使いますが、このワークフローはどのランタイムにも適用できます。

ステップ 1: エージェントがプロジェクトを認識できることを確認する

You: Summarize this project. What scheme should I build with?

Claude: [reads CLAUDE.md]
        [calls discover_projs via MCP]
        [calls list_schemes via MCP]

        This is Return, a zen meditation timer for iOS 26+, watchOS, and tvOS.
        Available schemes: Return, ReturnWatch, ReturnTV, ReturnTests.
        Primary scheme for iOS: Return.

エージェントが CLAUDE.md の内容に触れない場合は、ファイルがプロジェクトルート(.xcodeproj または Package.swift と同じディレクトリ)にあることを確認してください。

ステップ 2: ヘルスチェックビルドを実行する

You: Build the Return scheme for iOS simulator and report results.

Claude: [calls list_sims — finds iPhone 16 Pro on iOS 26.2]
        [calls boot_sim — boots the simulator]
        [calls build_sim — builds the project]

        Build succeeded. 63 source files compiled.
        2 warnings:
        - HomeView.swift:132 — UIScreen.main deprecated in iOS 26.0
        - LogWaterIntent.swift:61 — Result of try? is unused
        0 errors.

ステップ 3: テストを実行する

You: Run all tests and report pass/fail.

Claude: [calls test_sim]

        12 tests executed:
         TimerManagerTests (5/5 passed)
         SettingsTests (4/4 passed)
         ConstantsTests (3/3 passed)
        All tests passed.

ステップ 4: 機能を実装する

You: Add a new "Rain" theme to the theme system. Follow the existing
     pattern in Theme.swift and ThemeManager.swift. Include a rain
     ambient sound. Build and test after implementation.

Claude: [reads Theme.swift  understands Theme struct pattern]
        [reads ThemeManager.swift  understands theme registration]
        [reads existing theme definitions]
        [adds Rain theme to Theme.swift following existing pattern]
        [registers Rain theme in ThemeManager.swift]
        [calls build_sim  build succeeds]
        [calls test_sim  all tests pass]

        Added Rain theme:
        - Theme.swift: new `static let rain` with video, cover, ambient
        - ThemeManager.swift: added to `allThemes` array
        - Build: success (0 errors, 2 existing warnings)
        - Tests: 12/12 passed

        Note: You'll need to add rain_ambient.wav to the project
        and add the new Theme.swift changes to the Xcode target manually
        (I did not modify .pbxproj).

.pbxproj を変更しないというエージェントの注記は、CLAUDE.md のルールによるものです。このルールがなければ、エージェントはプロジェクトファイルを変更しようとして、高い確率で壊してしまいます。


iOS でエージェントが得意なこと

ここでは、エージェントが最小限の人間によるレビューで、一貫して正しく本番品質の出力を出せるタスクを紹介します。

SwiftUI ビューとモディファイア

エージェントは、SwiftUI の宣言的な構文パターンを深く認識できます。ビュー構成、モディファイアチェーン、状態バインディング、レイアウトは、エージェントの学習データと相性が良い領域です。SwiftUI の API サーフェスはドキュメントが充実しており、パターンの一貫性も高いためです。

エージェントが得意な領域: - 説明から新しいビューを作る(「X、Y、Z のトグルを持つ設定シートを作成して」) - モディファイアチェーンを適用する(.glassEffect().sensoryFeedback().navigationTitle()) - レイアウトパターンを変換する(VStack から LazyVGrid、List から ScrollView など) - SwiftData モデルへの @Bindable フォームバインディングを実装する - サンプルデータ付きのプレビュープロバイダーを作る

優れた結果を生むプロンプト例:

Create a SettingsView that matches the existing pattern in SettingsSheet.swift.
Include toggles for:
- Enable haptic feedback (Settings.shared.hapticsEnabled)
- Enable HealthKit logging (Settings.shared.healthKitEnabled)
- Show session history (navigation link to SessionHistoryView)

Use Liquid Glass styling with .glassEffect() on section backgrounds.
Follow the @Observable pattern, not ObservableObject.

具体性が重要です。「設定ビューを作成して」では汎用的な出力になります。「SettingsSheet.swift の既存パターンに合わせて SettingsView を作成して」と指定すると、コードベースと一貫した出力になります。

SwiftData モデルとクエリ

エージェントは、SwiftData の @Model マクロ、リレーション、@Query パターンを安定して扱えます。このフレームワークの宣言的な性質(Django ORM や SQLAlchemy に近いもの)は、多くのコードベースでエージェントが見てきたパターンとよく対応します。

エージェントが得意な領域: - リレーションを持つ @Model クラスを定義する - ソート記述子と述語を使って @Query を書く - modelContext 経由で CRUD 操作を実装する - スキーマバージョン間のマイグレーション計画を作る - プレビューデータとテストフィクスチャを作る

エージェントにガイダンスが必要な領域: - 複雑な #Predicate 式(SwiftData の述語 DSL には制限があり、エージェントが常に把握しているとは限りません。既知の制限は CLAUDE.md に記載してください) - CloudKit 同期設定(SwiftData 経由で自動化されますが、エージェントが手動同期を実装しようとする場合があります)

ユニットテスト

エージェントが書くユニットテストは、iOS プロジェクトで一貫して高品質です。エージェントは XCTest のパターン、async テストメソッド、setUp/tearDown のライフサイクルを理解しています。

Write unit tests for TimerManager covering:
1. Initial state is .stopped
2. start() transitions to .running
3. pause() transitions to .paused
4. reset() returns to .stopped with original duration
5. Timer counts down correctly (test with 3-second duration)

エージェントは、setUp()tearDown()、適切なアサーション、タイマーベースのテストに対する async 処理を備えた、よく構造化された XCTest ケースを生成します。

リファクタリングとパターン適用

エージェントは機械的なリファクタリングを得意としています。ビューをコンポーネントに抽出する、ObservableObject@Observable に変換する、NavigationView から NavigationStack に移行する、複数ファイルに一貫したパターンを適用する、といった作業です。

Refactor all views in the Views/ directory to use @Observable instead of
ObservableObject. Update @StateObject to @State, @ObservedObject to direct
property access, and @Published to plain properties.

エージェントは各ファイルを順に処理し、変換を正しく適用し、既存の機能を維持します。これはレバレッジの高い作業です。手作業なら 1 時間かかるリファクタリングが、ほぼ完璧な精度で数分で完了します。

MCP によるビルドエラー診断

構造化された MCP 出力があれば、エージェントはほとんどの開発者より速くビルドエラーを診断できます。エージェントはエラーの JSON を読み、正確なファイルと行を特定し、エラーメッセージを理解して修正します。多くの場合、1 ターンで完了します。

エージェントが自律的に修正できるエラー: - 不足している imports - 型の不一致 - プロトコル準拠の不足 - 非推奨の API 使用(置き換えを含む) - 必須イニシャライザーパラメータの不足 - アクセス制御違反

エージェントに支援が必要なエラー: - あいまいな型解決(複数のモジュールが同じ型を定義している場合) - 複雑なジェネリック制約の失敗 - マクロ展開エラー(エージェントは展開後のマクロ出力を確認できません)

シミュレーター管理

エージェントは MCP 経由でシミュレーターのライフサイクルをうまく扱えます。

Boot an iPhone 16 Pro simulator on iOS 26, install the app, and take a screenshot.

エージェントは list_sims を呼び出して利用可能なランタイムを探し、boot_sim でシミュレーターを起動し、build_sim でビルドとインストールを行い、screenshot でキャプチャします。すべて構造化された MCP 呼び出しを通じて実行します。


iOSでエージェントが苦手なこと

エージェントがどこで失敗するのかを正直に整理します。この境界を知っておくと、フラストレーションや無駄なトークン消費を防げます。

.pbxprojファイルの変更 — 絶対にしない

これはiOSエージェント開発で最も重要なルールです。.pbxprojファイルはXcodeのプロジェクト設定です。UUID参照、ビルドフェーズの一覧、ターゲットメンバーシップを含む構造化テキストファイルです。名目上は人間が読めますが、AIエージェントにとっては実質的に解析不能です。

エージェントが.pbxprojで失敗する理由: - ファイルは独自形式(JSONでもYAMLでもXMLでもありません)を使っており、位置に意味があります - すべてのエントリがUUIDで相互参照されています。ファイルを追加するには、3〜5個の異なるセクションを一貫して更新する必要があります - 1文字でも場所を誤ると、プロジェクトファイル全体が壊れます - Xcodeの.pbxprojマージコンフリクト解決はもともと脆弱です。エージェントによる編集はそれをさらに悪化させます

エージェントが.pbxprojを編集すると起きること: 1. 編集は成功したように見えます(エージェントは「file updated」と報告します) 2. Xcodeがプロジェクトを開けなくなります(「The project file is corrupted」) 3. git履歴から復旧するのに15〜60分かかります 4. PreToolUseフックを追加する必要性を学びます(フックを参照)

ワークフロー: エージェントがSwiftファイルを作成します。Xcodeプロジェクトへの追加は手動で行います(Xcodeへドラッグするか、File > Add Filesを使います)。1ファイルあたり5秒で済み、何時間もの復旧作業を防げます。

Swift Package Managerプロジェクトの場合: この制限はそれほど深刻ではありません。Package.swiftは標準的なSwiftファイルなので、エージェントでも安定して編集できます。プロジェクトがSPMのみを使用している場合(.xcodeprojなし)、エージェントがプロジェクト構造全体を管理できます。

複雑なInterface Builder / Storyboard編集

プロジェクトでInterface Builder(.xibファイル)やStoryboard(.storyboardファイル)を使っている場合、エージェントはそれらを意味のある形で編集できません。これらは自動生成UUID、制約参照、アウトレット接続を含むXMLファイルであり、テキスト編集ではなくビジュアル編集を前提に設計されています。

対策: 新しいビューにはSwiftUIだけを使います。プロジェクトにレガシーなInterface Builderファイルがある場合は触らず、新しいUIはSwiftUIで構築しましょう。

パフォーマンス最適化

エージェントは正しいコードを書けますが、必ずしも高性能なコードを書けるわけではありません。アプリをプロファイルしたり、ボトルネックを特定したり、フレームレートを測定したりすることはできません。パフォーマンス最適化には次が必要です。

  1. Instrumentsによるプロファイリング(視覚的なツールであり、エージェントからはアクセスできません)
  2. 特定デバイスのGPU/CPU特性の理解
  3. 測定に基づく反復的な変更

この問題が現れる場所: - Metalシェーダー最適化(エージェントは有効なMetalを書けますが、GPUフレーム時間は測定できません) - SwiftUIのview bodyの複雑さ(エージェントが深くネストしたビューを作成し、再描画オーバーヘッドを引き起こすことがあります) - Core Data / SwiftDataのフェッチ最適化(エージェントは正しいクエリを書けますが、大規模データセットでは遅い場合があります)

対策: 実装にはエージェントを使い、Instrumentsで手動プロファイリングします。そのうえで、特定した最適化をエージェントに適用させます。

コード署名とプロビジョニング

エージェントは、エラーメッセージを読む以上のコード署名問題のデバッグはできません。プロビジョニングプロファイル管理、証明書作成、エンタイトルメント設定、App Store提出は、Apple Developer portal、Keychain Access、Xcodeの署名UIを使う、人間が行うワークフローです。

エージェントに見えるもの: “Signing for ‘Return’ requires a development team.”

エージェントに見えないもの: 証明書が期限切れかどうか、プロビジョニングプロファイルにデバイスが含まれているか、bundle IDがApp IDと一致しているか、エンタイトルメントファイルが正しいかどうかです。

対策: 署名はすべてXcodeのSigning & Capabilitiesタブで処理します。署名失敗のデバッグをエージェントに依頼しないでください。

複雑なMetalシェーダーのデバッグ

エージェントは構文的に正しいMetal Shading Language(MSL)を書けますが、視覚出力の検証やGPU側の問題のデバッグはできません。MetalシェーダーはGPU上で実行されます。シェーダーが正しい視覚結果を生成しているかどうかについて、エージェントにはフィードバック手段がありません。

エージェントがMetalでできること: - 説明に基づいてvertexシェーダーとfragmentシェーダーを書く - SwiftでMetalレンダーパイプラインを設定する - データ並列処理用のcomputeシェーダーを作成する - .metalファイルのコンパイルエラーを修正する

エージェントがMetalでできないこと: - シェーダー出力の視覚的な正しさを検証する - GPUパフォーマンスをデバッグする(フレーム時間、occupancy、メモリ帯域幅) - 視覚的なアーティファクトを診断する(バンディング、精度の問題、誤った色空間) - 異なるGPUアーキテクチャでテストする(A-seriesとM-seriesの挙動差)

対策: Metalシェーダーは実機でテストします。SimulatorのMetal実装は、デバイスのGPU挙動を代表するものではありません。視覚デバッグにはXcodeのGPU Frame Captureを使います。

ビジュアルレイアウト検証

エージェントにはアプリのUIが見えません。SwiftUIレイアウトコードを書き、コンパイルできることは検証できますが、結果の画面が正しく見えるかどうかは判断できません。10ピクセル中心からずれているビュー、誤ったフォントウェイト、要素の重なりは、ビルドエラーを出さず、すべてのロジックテストにも合格します。

対策: UI変更は目視でレビューします。XcodeのSwiftUI Previews(またはヘッドレスレンダリング用のApple MCP経由のRenderPreview)を使ってレイアウトを検証します。自動のビジュアル回帰検出には、swift-snapshot-testingのようなライブラリを使ったスナップショットテストも検討してください。


iOS開発向けHooks

Hooksは、エージェントのワークフロー内の特定の時点で決定的に実行されるシェルコマンドです。強制の仕組みであり、「.pbxprojを編集しないでください」(エージェントが無視する可能性のある提案)と「.pbxprojは編集できません」(強制的なブロック)の違いを生みます。

hookシステムの背景については、Claude Code hooksガイドをご覧ください。このセクションでは、iOS固有のhookパターンを扱います。

PreToolUse: .pbxprojへの書き込みをブロックする

あらゆるiOSプロジェクトで最も重要なhookです。エージェントが.pbxprojファイル、.xcodeproj/ディレクトリ、その他のXcode管理ファイルへ書き込むのを防ぎます。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files. Create Swift files and add to Xcode manually.\" >&2; exit 2; fi'"
      }
    ]
  }
}

プロジェクトルートの.claude/settings.json、またはグローバルに保護する場合は~/.claude/settings.jsonに配置します。

仕組み: エージェントがパターンに一致するファイルに対してEditまたはWriteツールを使おうとすると、hookが実行されます。ファイルパスを検出し、stderrに警告を出力して、コード2で終了します(これによりツールの使用がブロックされます)。エージェントはエラーメッセージを受け取り、別の方法に調整します。

検出対象: - .pbxprojの直接編集 - .xcodeproj/または.xcworkspace/ディレクトリ内の任意のファイル - Interface Builderファイル(.xib.storyboard

PostToolUse: SwiftFormatによる保存時フォーマット

エージェントがSwiftファイルを書き込みまたは編集するたびに、自動でフォーマットします。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
      }
    ]
  }
}

要件: SwiftFormatがインストールされている必要があります(brew install swiftformat)。

重要な理由: エージェントは構文的に正しいSwiftを生成しますが、フォーマット規約に一貫して従うとは限りません。SwiftFormatはインデント、波括弧の配置、importの順序を正規化します。保存時フォーマットのhookにより、エージェントが触れたすべてのSwiftファイルは、目に入る前に自動でフォーマットされます。

任意: .swiftformat設定ファイルを追加する と、プロジェクトルートでフォーマット規則をカスタマイズできます。

# .swiftformat
--indent 4
--allman false
--stripunusedargs closure-only
--importgrouping testable-bottom
--header strip

PostToolUse: SwiftLintを自動実行する

SwiftLintを使っている場合は、Swiftファイルを編集するたびに実行します。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftlint lint --path \"$FP\" --quiet 2>/dev/null || true; fi'"
      }
    ]
  }
}

|| trueにより、lint警告でエージェントがブロックされないようにしています。lint違反でブロックしたい場合は、これを削除してください。

PostToolUse: 変更後に自動ビルドする

より積極的なフィードバックループを作るには、Swiftファイルの変更ごとにビルドをトリガーします。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then xcodebuild -scheme Return -destination \"platform=iOS Simulator,name=iPhone 16 Pro\" build 2>&1 | tail -5; fi'"
      }
    ]
  }
}

警告: これはコストが高いです。ファイル編集のたびにビルドが実行されます。慎重に使ってください。即座にビルドフィードバックが欲しいデバッグセッションで特に役立ちます。通常の開発では、準備ができたタイミングでエージェントにMCP経由で手動ビルドさせるのがよいでしょう。

PreToolUse: Entitlementsの変更をブロックする

entitlementsファイルを、エージェントによる意図しない変更から保護します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.entitlements$\"; then echo \"BLOCKED: Do not modify entitlements files without explicit permission.\" >&2; exit 2; fi'"
      }
    ]
  }
}

iOS Hook設定の統合例

以下は、私がすべてのiOSプロジェクトで使っている完全な.claude/settings.jsonです。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard|entitlements)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode-managed files. Create Swift files and add manually.\" >&2; exit 2; fi'"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
      }
    ]
  }
}

これにより、2つの保証が得られます。 1. エージェントはXcodeプロジェクトファイルを壊せません(PreToolUseブロック) 2. エージェントが触れたすべてのSwiftファイルは自動フォーマットされます(PostToolUseフォーマット)


エージェントと相性のよい Architecture Patterns

すべての Swift architecture がエージェントに同じくらい扱いやすいわけではありません。以下のパターンは、明示的で一貫しており、学習データでも十分に表現されているため、最もよい結果につながります。

@Observable(ObservableObjectは使わない)

iOS 26以降をターゲットにする場合は、@Observable だけを使うべきです。これはモダンなパターンであると同時に、エージェントにも扱いやすいパターンです。

// CORRECT — @Observable
@Observable
@MainActor
final class TimerManager {
    var timeRemaining: TimeInterval = 0
    var state: TimerState = .stopped

    func start() {
        state = .running
        // ...
    }
}

// In a view:
struct TimerView: View {
    @State private var timer = TimerManager()

    var body: some View {
        Text(timer.timeRemaining, format: .number)
    }
}
// WRONG — ObservableObject (deprecated pattern)
class TimerManager: ObservableObject {
    @Published var timeRemaining: TimeInterval = 0
    @Published var state: TimerState = .stopped
}

// WRONG — @StateObject (deprecated pattern)
struct TimerView: View {
    @StateObject private var timer = TimerManager()
}

@Observable がエージェントに扱いやすい理由: パターンがよりシンプルで(@Published アノテーションが不要)、所有モデルも明確です(@StateObject@ObservedObject の使い分けではなく @State)。動く部分が少ないため、エージェントが生み出すバグも減ります。

CLAUDE.md に明記してください: ターゲットが iOS 26 でも、エージェントは学習データにある ObservableObject パターンへ戻ってしまうことがあります。明示的に禁止しておくと、それを防げます。

// CORRECT
NavigationStack {
    List(items) { item in
        NavigationLink(value: item) {
            ItemRow(item: item)
        }
    }
    .navigationDestination(for: Item.self) { item in
        ItemDetailView(item: item)
    }
}

// WRONG
NavigationView {
    List(items) { item in
        NavigationLink(destination: ItemDetailView(item: item)) {
            ItemRow(item: item)
        }
    }
}

NavigationStack は iOS 16以降の機能であり、新しいコードで使うべき唯一のナビゲーションパターンです。型安全な navigationDestination(for:) パターンにより、エージェントが誤ったナビゲーションリンクを作成するのを防げます。

永続化には SwiftData を使う

SwiftData モデルは、エージェント支援開発において最もすっきりした永続化パターンです。

@Model
final class GroceryItem {
    var name: String
    var quantity: Int
    var isCompleted: Bool
    var category: Category?
    var list: GroceryList?

    init(name: String, quantity: Int = 1) {
        self.name = name
        self.quantity = quantity
        self.isCompleted = false
    }
}

SwiftData を扱うエージェント向けの重要なルール: 1. @Model クラスは自動的に Observable になります。@Observable は追加しません 2. フォームバインディングには @Bindable を使います: @Bindable var item: GroceryItem 3. リアクティブなデータには view 内で @Query を使います: @Query var items: [GroceryItem] 4. view 以外のコードでは modelContext.fetch() を使います 5. リレーションシップの削除には明示的なルールが必要です: .cascade, .nullify, .deny

Swift 6.2 Concurrency

新規プロジェクトでは Swift 6.2 の strict concurrency をターゲットにします。

// Actor isolation for shared mutable state
@MainActor
@Observable
final class DataManager {
    var items: [Item] = []

    func loadItems() async throws {
        let fetched = try await api.fetchItems()
        items = fetched  // Safe: @MainActor isolated
    }
}

// Sendable conformance for cross-actor transfers
struct Item: Sendable, Identifiable {
    let id: UUID
    let name: String
    let createdAt: Date
}

Concurrency に関するエージェント向けガイド: - すべての view model に @MainActor を付けます(データ競合の警告を防ぎます) - すべての非同期処理には async/await を使います(completion handler は使いません) - actor をまたいで渡す値型は Sendable にします - view での非同期初期化には Task { } を使います - nonisolated は、パフォーマンス上の必要性を測定できた場合にのみ使います

Liquid Glass デザインシステム(iOS 26以降)

iOS 26 では Liquid Glass デザインシステムが導入されました。明示的なガイドを与えれば、エージェントはこれをうまく扱えます。

// Glass effect on containers
VStack {
    // content
}
.glassEffect()

// Glass effect with tint
Button("Action") { }
    .glassEffect(.regular.tint(.blue))

// Glass effect on navigation bars (automatic in iOS 26)
NavigationStack {
    // content
}
// Navigation bar automatically uses glass material

// Custom glass shapes
RoundedRectangle(cornerRadius: 16)
    .fill(.ultraThinMaterial)
    .glassEffect()

CLAUDE.md に含めてください: 「セクション背景とカードコンテナには .glassEffect() を使います。iOS 26 ではナビゲーションバーが自動的に glass material を採用します。カスタム material で glass effect を手作業で再現しないでください。システム modifier を使います。」


Framework 別の Context

Apple の各 framework には、エージェント固有の注意点があります。このセクションでは、8つのアプリで使った framework を扱います。

HealthKit

使用しているアプリ: Return, Water

HealthKit では、権限処理とプラットフォームガードを慎重に扱う必要があります。

// Always check availability and authorization
import HealthKit

@MainActor
@Observable
final class HealthKitManager {
    private let store = HKHealthStore()
    var isAuthorized = false

    func requestAuthorization() async {
        guard HKHealthStore.isHealthDataAvailable() else { return }

        let types: Set<HKSampleType> = [
            HKQuantityType(.dietaryWater),
            HKCategoryType(.mindfulSession)
        ]

        do {
            try await store.requestAuthorization(toShare: types, read: types)
            isAuthorized = true
        } catch {
            // User denied — do not retry automatically
        }
    }
}

HealthKit に関するエージェント向けルール: - 必ず HKHealthStore.isHealthDataAvailable() でガードします - 承認済みだと決めつけず、書き込みのたびに確認します - マルチプラットフォームコードでは #if canImport(HealthKit) を使います(HealthKit は tvOS では利用できません) - HealthKit が提供する範囲を超えて、ヘルスデータをローカルに保存しません - Info.plist には NSHealthShareUsageDescriptionNSHealthUpdateUsageDescription の両方を含めます

SpriteKit

使用しているアプリ: TappyColor, Starfield Destroyer

SpriteKit のシーングラフモデルには、エージェントへの明示的なガイドが必要です。

## SpriteKit Rules

- Scene hierarchy is a tree of SKNodes with zPosition ordering
- Physics bodies use category bitmasks (UInt32) for collision detection
- Node pooling: pre-allocate reusable nodes (bullets, particles)
- Never add nodes directly to the scene — use layer nodes for organization
- Update loop: `update(_ currentTime:)` runs every frame — keep it fast
- Actions: use SKAction sequences for animations, not manual property updates
- Textures: use texture atlases for performance (.atlas directories)

SpriteKit におけるエージェントの得意分野: - SKAction のシーケンスとグループの作成 - physics body と接触検出の設定 - ゲームステートマシンの実装 - HUD オーバーレイの構築

SpriteKit におけるエージェントの苦手分野: - パフォーマンスが重要なゲームループ(エージェントはフレームごとに不要な処理を追加しがちです) - 複雑な physics シミュレーション(精度が必要な場合は、SKPhysicsBody よりカスタム physics が向いています) - particle effect の調整(視覚的な作業であり、反復が必要です)

Metal

使用しているアプリ: amp97, Water, Starfield Destroyer

Metal は、エージェントが最も苦戦する framework です。GPU のプログラミングモデルは CPU 側の Swift とは根本的に異なり、エージェントは視覚的な出力を検証できません。

## Metal Rules

- Shared types between Swift and Metal go in a bridging header (ShaderTypes.h)
- Triple buffer in-flight frames (semaphore with value 3)
- Test shaders on DEVICE, not simulator (Metal behavior differs)
- Compute shaders: threadgroup size must divide evenly into grid size
- Fragment shaders: output color must be in correct color space (sRGB or linear)
- DO NOT optimize shaders without Instruments GPU profiling data

Metal プロジェクトで CLAUDE.md に含めるべき内容: - Uniforms struct の定義(Swift と MSL で共有) - render pipeline state の設定パターン - buffer index とその用途 - 存在する shader と、それぞれの役割 - 既知の精度問題(half と float)

Live Activities

使用しているアプリ: Return

Live Activities には特定の設定が必要ですが、文書化しておけばエージェントはうまく扱えます。

## Live Activities

- ActivityAttributes defined in `TimerActivityAttributes.swift`
- ActivityKit framework: `import ActivityKit`
- Widget extension: `ReturnWidgets/ReturnLiveActivity.swift`
- Start: `Activity<TimerActivityAttributes>.request(attributes:content:)`
- Update: `activity.update(ActivityContent(state:staleDate:))`
- End: `activity.end(ActivityContent(state:staleDate:), dismissalPolicy:)`
- Push token: register for updates via `activity.pushTokenUpdates`

Game Center

使用しているアプリ: Starfield Destroyer

## Game Center

- Authentication: `GKLocalPlayer.local.authenticateHandler`
- Leaderboards: `GKLeaderboard.submitScore(_:context:player:leaderboardIDs:completionHandler:)`
- Achievements: `GKAchievement.report(_:withCompletionHandler:)` (takes `[GKAchievement]` array)
- Always check `GKLocalPlayer.local.isAuthenticated` before submitting
- Handle authentication failure gracefully (offline play must work)

マルチプラットフォームのパターン

ReturnはiOS、watchOS、tvOSにまたがります。エージェントによるマルチプラットフォーム開発では、プラットフォーム境界を明示的に文書化する必要があります。

共有コードの構成

Shared/
├── MeditationSession.swift    # Data model (all platforms)
├── SessionStore.swift         # iCloud sync (all platforms)
└── SessionHistoryView.swift   # UI (adapts per platform)

Return/                        # iOS-specific
ReturnWatch Watch App/         # watchOS-specific
ReturnTV/                      # tvOS-specific

エージェント向けルール: 「ファイルがShared/にある場合、変更はすべてのプラットフォームに影響します。ファイルがプラットフォームディレクトリにある場合、変更は分離されます。変更する前に、必ずそのファイルがどのディレクトリにあるか確認してください。」

プラットフォーム可用性ガード

// HealthKit: available on iOS and watchOS, not tvOS
#if canImport(HealthKit)
import HealthKit
// HealthKit code here
#endif

// ActivityKit: available on iOS only
#if canImport(ActivityKit)
import ActivityKit
// Live Activity code here
#endif

// WatchKit: available on watchOS only
#if os(watchOS)
import WatchKit
// Watch-specific code here
#endif

エージェント向けガイダンス: 「プラットフォーム固有のフレームワークを使う場合は、必ず#if canImport()または#if os()ガードを使用してください。フレームワークがすべてのターゲットで利用できると決めつけてはいけません。」

プラットフォーム別UI適応

struct SessionHistoryView: View {
    @Query var sessions: [MeditationSession]

    var body: some View {
        List(sessions) { session in
            SessionRow(session: session)
        }
        #if os(tvOS)
        .focusable()
        #endif
        #if os(iOS)
        .swipeActions {
            Button("Delete", role: .destructive) {
                // delete
            }
        }
        #endif
    }
}

高度なワークフロー

自律的なBuild-Test-Fixループ

最も強力なパターンは、エージェントに機能仕様を渡し、build-test-fixサイクルを自律的に反復させることです。

Implement a countdown timer that:
1. Starts from a user-selected duration (10, 20, or 30 minutes)
2. Shows remaining time with a circular progress indicator
3. Plays a bell sound on completion
4. Logs the session to HealthKit as mindful minutes

Build after each change. Fix all errors. Run tests when the build succeeds.
Continue until all tests pass and the build is clean.

エージェントはコードを書き、MCP経由でビルドし、構造化されたエラーを読み取り、修正して、これを繰り返します。人間なら5〜10回のbuild-error-fixサイクルが必要になる機能も、1回の自律ループで完了します。

うまく機能する場合: 受け入れ基準が明確な、よく定義された機能。

破綻しやすい場合: オープンエンドな機能(「見た目をいい感じにして」)、パフォーマンスに敏感なコード、または視覚的な検証が必要なもの。

iOS向けSubagent Delegation

Claude CodeのsubagentシステムはiOSプロジェクトでも機能します。

Use a subagent to research the best approach for implementing
iCloud key-value store sync for meditation sessions across iOS,
watchOS, and tvOS. Report back with the recommended pattern.

subagentは別のコンテキストウィンドウでドキュメントとコードパターンを調査し、要約を返します。その後、メインセッションが推奨内容を実装します。これにより、調査で主要なコンテキストを消費せずに済みます。

アプリ間でのパターン適用

一貫したパターンで複数のiOSアプリを保守している場合、エージェントはあるアプリのパターンを別のアプリに適用できます。

Look at how Settings.swift works in the Return project
(centralized singleton with validation). Apply the same pattern
to create a Settings.swift for the Water project.

エージェントは元のパターンを読み取り、構造を理解し、ターゲットプロジェクトに一貫した実装を作成します。

デュアルエージェントレビュー(Claude + Codex)

重要な変更では、異なるモデルファミリーの2つのエージェントを使います。

  1. Claude Codeが実装を書く
  2. Codex CLIが別パスでレビューする
# After Claude implements the feature:
codex "Review the changes in the last commit. Focus on Swift 6.2
      concurrency correctness, SwiftData relationship integrity,
      and potential retain cycles. Report issues only — no praise."

異なるモデルファミリーは、異なる種類のエラーを検出します。これは、微妙なバグが入り込みやすいMetalシェーダーや並行処理パターンで特に有効です。

単独レビューでは見落とし、デュアルレビューで検出できるもの:

問題の種類 Claudeの強み Codexの強み
SwiftData relationship cycles 中程度 強い(GPT-4o)
@MainActor isolation gaps 強い 中程度
Metal buffer alignment 中程度 中程度
Retain cycle detection 強い(Opus) 強い(o3)
API deprecation awareness 強い(新しいトレーニングデータ) 中程度
Concurrency race conditions 強い 強い(異なるパターンを検出)

デュアルレビューの目的は、より多くのバグを見つけることではありません。異なるバグを見つけることです。各モデルファミリーには、パターン認識において異なる失敗モードがあります。

複数アプリにまたがるバッチ操作

フレームワークやパターンの変更が複数のアプリに影響する場合:

# Update @Observable pattern across all projects
for project in BananaList Return Water Reps; do
  cd ~/Projects/$project
  claude -p "Audit all files for any remaining ObservableObject usage.
             Convert to @Observable following the pattern in CLAUDE.md.
             Build and test after changes." --dangerously-skip-permissions
done

注意して使用してください。 --dangerously-skip-permissionsフラグは非対話モードに必要ですが、すべての安全チェックを迂回します。.pbxprojファイルを保護するため、PreToolUse hooksが設定されていることを確認してください。

AppleのオンデバイスLLMを使用するアプリ

アプリがAppleのFoundation Modelsフレームワークを呼び出す場合(オフライン要約、分類、構造化出力の生成など)、エージェントはプロンプトの予算を把握している必要があります。iOS 26.4では、以前の4096トークンという推測を置き換える2つのAPIがSystemLanguageModelに追加されました。contextSize(モデルが1つの会話で受け入れる最大トークン数)と、tokenCount(for:)async throwsで、指定したプロンプトが実際に消費するトークン数を返します)です。22 どちらも@backDeployed(before: iOS 26.4)なので、#availableの分岐を組まなくても、FMをサポートするすべてのOSバージョンで利用できます。

エージェントがプロンプト構築コードを生成するときに従うべきパターンは次のとおりです。

import FoundationModels

func budgetFor(prompt: String, reservedReply: Int = 256) async throws -> Int {
    let model = SystemLanguageModel.default
    let promptCost = try await model.tokenCount(for: prompt)
    let budget = model.contextSize - promptCost - reservedReply
    guard budget > 0 else { throw ContextError.promptTooLong }
    return budget
}

アプリがSystemLanguageModelに触れる場合は、このパターンをCLAUDE.mdに追加してください。追加しないと、エージェントは古い4096のハードコードに戻り、より大きなコンテキストウィンドウを搭載したデバイスでプロンプトを静かに切り詰めてしまいます。tokenCount(for:)async throwsシグネチャは重要です。同期版を貼り付けたエージェントのコードはコンパイルに失敗します。


実世界のケーススタディ

抽象的なアドバイスを書くのは簡単です。ここでは、8つのアプリから、agent支援によるiOS開発が実際にどう機能するのかを示す具体的なシナリオを紹介します。失敗例も含めています。

ケーススタディ 1: ReturnへのTVアプリ追加(成功)

タスク: すでにiOS版とwatchOS版がある瞑想タイマーReturnに、tvOSターゲットを追加することでした。TVアプリには、Siri Remoteナビゲーション、大画面向けUI、iOSアプリとの設定同期が必要でした。

agentがうまくできたこと: - 既存のiOS TimerManagerを読み、tvOSでは利用できないLive ActivitiesとHealthKitを省いたTVTimerManagerを作成しました - Siri Remoteのフォーカスナビゲーション向けに、カスタムボタンスタイル(TVCapsuleButtonStyleTVCircleButtonStyle)を作成しました - Siri Remoteでは使いにくいホイールピッカーを、+/-ボタンに置き換えるTVStepperコンポーネントを構築しました - App Groups(group.com.941apps.Return)経由で設定同期を実装しました - 共有コード全体に#if os(tvOS)ガードを追加しました - MCPでplatform=tvOS Simulator,name=Apple TVを指定し、ビルドとテストを実行しました

手動で行う必要があったこと: - XcodeでtvOSターゲットを作成する(File > New > Target > tvOS App) - 新しいターゲットをXcodeプロジェクトに追加する(.pbxprojの変更) - TVターゲット向けにApp Groupsエンタイトルメントを設定する - 既存のスキームにTVターゲットを追加する、または新しいスキームを作成する - agentが作成したすべてのSwiftファイルを、TVターゲットに手動で追加する - Siri Remoteナビゲーションを手動でテストする(agentはフォーカス挙動を評価できません)

結果: 約3時間のagent支援作業で、15個の新しいSwiftファイルと、完全に動作するTVアプリができました。私の見積もりでは、実装作業のおよそ80%をagentが担当し、Xcode UI操作が必要な部分(エンタイトルメント、ターゲット設定、機能フラグ)と、実機のApple TVでのフォーカステストを私が担当しました。このコードベースで同等の作業を1人で行う場合、過去にagentなしで出荷した類似機能を基準にすると、数日かかる作業だったはずです。

ケーススタディ 2: amp97のMetalシェーダーデバッグ(一部失敗)

タスク: オシロスコープシェーダーに、エネルギーベースの強度システムを追加することでした。ビジュアライゼーションが音声エネルギーに合わせて脈動する必要がありました。

起きたこと: 1. agentは、uEnergy uniformとHDRトーンマッピングを追加する、有効なMetalシェーダー変更を書きました 2. コードはエラーなくコンパイルされました 3. 実機では、ビジュアライゼーションが完全に白く表示されました。強度係数が10倍高すぎたのです(0.30ではなく3.5) 4. agentには白い画面が見えないため、フィードバック信号がありませんでした 5. 私が視覚的に問題を特定し、係数を下げるようagentに依頼しました 6. agentは係数を下げましたが、全体のエネルギーステートマシンが複雑すぎて、別の形でビジュアライザーを壊しました 7. 完全にrevertしました。2つのコミット(67959edcda4830)を869d914でrevertしました

教訓: Metalシェーダーは、agent支援開発で最も難しい領域です。フィードバックループが切れているからです。agentは構文(コンパイルできること)と意味論(型が正しいこと)は検証できますが、出力(見た目が正しいこと)は検証できません。視覚的挙動を変えるシェーダー変更には、必ず実機での人間による検証が必要です。

この後CLAUDE.mdに追加したこと: 「極めて慎重な係数テストなしに、オシロスコープシェーダーのエネルギーステート変更を試みないこと。前回の試みでは係数が10倍高すぎて、ビジュアライザーが壊れた。」

ケーススタディ 3: Banana ListのSwiftDataマイグレーション(成功)

タスク: データモデルをV1からV2へマイグレーションし、GroceryItemquantityフィールドを追加し、リレーションを持つ新しいCategoryモデルを追加することでした。

agentが行ったこと: 1. 既存のV1モデル定義を読みました 2. 新しいフィールドとリレーションを含むV2モデル定義を作成しました 3. SchemaMigrationPlanプロトコルに準拠したGroceryMigrationPlanを書きました 4. V1toV2マイグレーションステージを実装しました。デフォルトのquantity: 1category: nilを追加しました 5. 新しいフィールドに対応するよう、すべてのビューを更新しました 6. プレビュー向けにSampleData.swiftを更新しました 7. MCP経由でビルドとテストを実行し、すべて合格しました 8. マイグレーション専用のユニットテストを作成しました

要点: SwiftDataマイグレーションは、Appleのドキュメントと学習データに十分含まれている、明確なプロトコルパターンに従うため、agentは成功しました。CLAUDE.mdにV1モデルが明示的に記録されていたため、agentは何からマイグレーションするのかを理解できました。

ケーススタディ 4: ReturnのiCloudセッション同期(複雑だが成功)

タスク: デバイス間の瞑想セッション記録を実装することでした。Apple TVやMacで完了したセッションを、HealthKit記録のためにiPhoneへ同期する必要がありました。

agentが生成したもの:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
    tvOS              Mac              Watch     
 TVTimerMgr        TimerMgr          WatchTimer  
└──────┬──────┘     └──────┬──────┘     └──────┬──────┘
                                             
       └───────────────────┼───────────────────┘
                           
                           
              ┌────────────────────────┐
                   SessionStore       
                (iCloud Key-Value)    
              └───────────┬────────────┘
                          
                          
              ┌────────────────────────┐
                iPhone (on foreground)
                 Write to HealthKit  
              └────────────────────────┘

agentは次を行いました。 1. UUID、日付、継続時間、ソースデバイス、HealthKit同期ステータスを持つMeditationSessionデータモデルを作成しました 2. iCloud同期向けにNSUbiquitousKeyValueStoreを管理するSessionStoreシングルトンを構築しました 3. マージ競合解決(UUIDベースの重複排除)を実装しました 4. プラットフォーム別の調整を含むSessionHistoryViewを追加しました(iOSではスワイプ削除、tvOSではフォーカスベース) 5. 他デバイスからのセッションに対して、iPhone側のHealthKit同期を接続しました

反復が必要だったこと: 初期実装では、iPhoneアプリがバックグラウンドで起動するケースを扱えていませんでした(同期のためのフォアグラウンド通知がありません)。agentには具体的な指示が必要でした。「バックグラウンドのKV変更で同期をトリガーするために、NSUbiquitousKeyValueStore.didChangeExternallyNotificationを使う」。このヒントの後、実装は正しくなりました。

教訓: アーキテクチャが明確に説明されていれば、agentはマルチプラットフォームのアーキテクチャパターンをうまく扱えます。iCloud同期パターンは単純ではありませんが、Appleのドキュメント化されたパターンに従っており、agentはそれを理解しました。エッジケース(バックグラウンド同期)には、人間のドメイン知識が必要でした。十分に文書化されていないためです。

ケーススタディ 5: Starfield DestroyerのGame Center統合(成功)

タスク: 宇宙シューティングにGame Centerのリーダーボードと実績を追加することでした。

agentがうまくできたこと: - アプリのエントリーポイントにGKLocalPlayer.local.authenticateHandlerを実装しました - スコア送信と実績報告のメソッドを持つGameCenterManagerを作成しました - すべてのGame Center操作の前に、認証状態チェックを追加しました - オフライン時のケースを適切に扱いました(Game Centerなしでもゲームはプレイでき、再接続時に送信されます) - 8機の機体進行システムに合わせた実績定義を作成しました

手動作業が必要だったこと: - App Store Connectでリーダーボードと実績を作成する(Webポータルであり、agentはアクセスできません) - XcodeでGame Centerエンタイトルメントを設定する - サンドボックスのGame Centerアカウントでテストする(実機での手動サインインが必要です)


エージェントを使ったプロジェクトライフサイクル

新しい iOS プロジェクトを始める

エージェント支援で新しいプロジェクトを始める場合の最適なワークフローは次のとおりです。

フェーズ 1: 人間によるセットアップ(15〜30分) 1. Xcode プロジェクトを作成します(File > New > Project) 2. 署名とCapabilitiesを設定します 3. デプロイメントターゲットと対応する実行先を設定します 4. 必要なエンタイトルメントを追加します(HealthKit、Game Center など) 5. プロジェクトの識別情報とルールを含む最初の CLAUDE.md を作成します

フェーズ 2: エージェントによる実装(数時間〜数日) 1. エージェントがデータモデルを作成します(SwiftData、Core Data、またはプレーンな構造体) 2. エージェントが、文書化されたパターンに従ってビューを構築します 3. エージェントが manager/service クラスにビジネスロジックを実装します 4. エージェントがユニットテストを書きます 5. MCP による build-test-fix ループを実行します(自律)

フェーズ 3: 人間による統合(30〜60分) 1. エージェントが作成したファイルを Xcode ターゲットに追加します 2. 署名とエンタイトルメントを確認します 3. 実機でテストします 4. ビジュアルレイアウトと UX をレビューします 5. App Store Connect に提出します

既存プロジェクトを保守する

確立済みのアプリで継続的に開発する場合は、次のようにします。

You: Here's the next feature for Return: add a "Focus Score" that
     calculates from session duration and consistency. Show it on
     the main timer view. Build and test.

Claude: [reads CLAUDE.md, understands patterns]
        [reads TimerManager.swift, Settings.swift]
        [creates FocusScore.swift  model with calculation logic]
        [creates FocusScoreView.swift  display component]
        [integrates into ContentView.swift]
        [calls build_sim  1 error: missing import]
        [fixes import]
        [calls build_sim  success]
        [writes FocusScoreTests.swift]
        [calls test_sim  all pass]

エージェントの有効性は、CLAUDE.md がプロジェクトの現在の状態をどれだけ正確に反映しているかに比例します。重要な新機能を追加したとき、アーキテクチャパターンを変更したとき、新しいフレームワークを導入したときは、CLAUDE.md を更新してください。

エージェントに関与させるべき場合とそうでない場合

タスク エージェント? 理由
新しい SwiftUI ビュー はい エージェントは宣言型 UI が得意です
SwiftData モデルの変更 はい 明確に定義でき、テスト可能です
ユニットテスト はい 機械的で、パターンに基づいています
リファクタリング はい 体系的で、複数ファイルにまたがります
ビルドエラーの診断 はい(MCP 経由) 構造化されたフィードバックループです
新しい Xcode ターゲット いいえ Xcode UI と .pbxproj の変更が必要です
署名とプロビジョニング いいえ ポータルベースで、エージェントからアクセスできません
ビジュアルの仕上げ いいえ 人間の美的判断が必要です
Metal シェーダーのチューニング いいえ デバイスでの GPU テストが必要です
App Store への提出 いいえ ポータルと Xcode Organizer が必要です
パフォーマンスプロファイリング いいえ Instruments が必要です
アクセシビリティ監査 一部 エージェントはラベルを追加できますが、VoiceOver の確認は人間が行います

エージェント定義を設定する

Claude Code のエージェント定義システム(.claude/agents/)を使う場合は、iOS 専用エージェントを作成します。

---
name: ios-developer
description: iOS development agent with MCP build tools and SwiftUI expertise
tools:
  - XcodeBuildMCP
  - xcode
---

# iOS Developer Agent

You are an iOS development agent for apps targeting iOS 26+ with SwiftUI.

## Architecture Rules
- @Observable for all view models (NEVER ObservableObject)
- NavigationStack for all navigation (NEVER NavigationView)
- SwiftData for persistence
- Swift 6.2 strict concurrency
- @MainActor on all Observable classes

## Build & Test — Always Use MCP

Prefer MCP tools over raw shell commands for ALL build operations:

- **Build**: `build_sim` / `build_device` (NOT `xcodebuild` via Bash)
- **Test**: `test_sim` / `test_device` (NOT `xcodebuild test` via Bash)
- **Simulators**: `list_sims`, `boot_sim`, `open_sim`
- **Debug**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Apple docs**: `DocumentationSearch` (NOT WebSearch for Apple APIs)
- **Swift verification**: `ExecuteSnippet` (NOT `swift` via Bash)

MCP returns structured JSON. Bash returns unstructured text.

## File Management Rules
- NEVER modify .pbxproj, .xcodeproj/, .xcworkspace/, .xib, .storyboard
- Create Swift files in the correct directory
- Report files that need manual addition to Xcode targets

## SwiftData Rules
- @Model classes are automatically Observable — do not add @Observable
- Use @Bindable for form bindings to model properties
- Use @Query in views, modelContext.fetch() elsewhere
- Document relationship delete rules

## When You Get Stuck
- Build errors: use `build_sim` via MCP for structured output
- API questions: use `DocumentationSearch` via Apple MCP
- Swift verification: use `ExecuteSnippet` via Apple MCP
- Never guess — verify with tools

Claude Code セッションでは、このエージェントを @ios-developer で参照します。


エージェント支援 iOS のテストパターン

明確なガイダンスを与えると、エージェントは優れたユニットテストを書けます。最も良い結果につながるパターンを紹介します。

テストファイルの構成

# In CLAUDE.md:
## Test Structure

Tests mirror source structure:
- `ReturnTests/TimerManagerTests.swift` tests `TimerManager.swift`
- `ReturnTests/SettingsTests.swift` tests `Settings.swift`
- `ReturnTests/ConstantsTests.swift` tests `Constants.swift`

Test naming: `test_<what>_<condition>_<expected>`
Example: `test_start_whenStopped_transitionsToRunning`

テストを依頼するプロンプト

効果的なテストプロンプト:

Write unit tests for TimerManager covering:

1. Initial state is .stopped with timeRemaining == selectedDuration
2. start() transitions state to .running
3. pause() from .running transitions to .paused
4. reset() from any state returns to .stopped with original duration
5. start() from .paused resumes (state becomes .running)
6. Edge case: reset() when already stopped is a no-op
7. Edge case: pause() when already paused is a no-op

Follow the existing test pattern in SettingsTests.swift.
Use setUp() to create a fresh TimerManager for each test.

これが機能する理由: 番号付きの受け入れ条件により、エージェントにチェックリストを渡せます。既存のテストファイルを参照することで、パターンを確立できます。setUp() の使い方を指定すると、エージェントが絡み合ったテスト状態を作るのを防げます。

効果の低いテストプロンプト:

Write tests for TimerManager.

これでは汎用的で浅いテストになり、エッジケースを見逃しやすく、プロジェクトのパターンに従わない可能性があります。

Async テストパターン

タイマー ベースや async コードをテストする場合は、次のようにします。

// Agent produces this pattern when guided correctly:
final class TimerManagerTests: XCTestCase {
    var sut: TimerManager!

    @MainActor
    override func setUp() {
        super.setUp()
        sut = TimerManager()
    }

    @MainActor
    func test_start_whenStopped_transitionsToRunning() {
        // Given
        XCTAssertEqual(sut.state, .stopped)

        // When
        sut.start()

        // Then
        XCTAssertEqual(sut.state, .running)
    }

    @MainActor
    func test_timerCountsDown_afterOneSecond() async throws {
        // Given
        sut.selectedDuration = 10
        sut.reset()
        sut.start()

        // When
        try await Task.sleep(for: .seconds(1.1))

        // Then
        XCTAssertLessThanOrEqual(sut.timeRemaining, 9.0)
    }
}

エージェントに再確認させるべき重要なパターン: - @MainActor クラスをテストするテストメソッドには @MainActor を付ける - Task.sleep や async 処理を使うテストには async throws を使う - 時間ベースのアサーションには許容誤差を持たせる(正確に 1.0 秒ではなく、1.1 秒など) - テスト分離のために、クリーンな setUp() / tearDown() を用意する

Snapshot Testing

ビジュアルリグレッション検出には、swift-snapshot-testing の追加を検討してください。

Add snapshot tests for the main timer view in three states:
1. Stopped (showing full duration)
2. Running (showing countdown)
3. Completed (showing 00:00 with completion state)

Use SnapshotTesting library. Create reference images on first run.

エージェントは snapshot テストを正しくセットアップできますが、参照画像をレビューすることはできません。最初のスナップショットは人間がレビューし、その後はエージェントのテストが将来の変更でビジュアルリグレッションを検出します。

iOS プロジェクトのコンテキストウィンドウ管理

1Mのコンテキストウィンドウ(Opus 4.6)は大きいですが、無限ではありません。iOS プロジェクトには、コンテキスト管理で固有の考慮点があります。

iOS ファイルのトークンコスト

ファイル種類 一般的なサイズ 概算トークン数
SwiftUI ビュー(シンプル) 50-100行 500-1,000
SwiftUI ビュー(複雑) 200-400行 2,000-4,000
SwiftData モデル 30-80行 300-800
Manager/service クラス 100-300行 1,000-3,000
Metal shader (.metal) 50-200行 500-2,000
Unit test ファイル 50-200行 500-2,000
CLAUDE.md 100-300行 1,000-3,000
MCP response(build) さまざま 200-2,000
MCP response(test) さまざま 500-5,000

50ファイルのプロジェクトの場合: すべてのファイルを読むと、およそ50,000-100,000トークンを消費します。1Mのウィンドウには十分収まります。Agent はプロジェクト全体をコンテキストに保持できます。

100ファイル以上のプロジェクトの場合: 選択的に読む必要が出てきます。Agent はまず CLAUDE.md(ファイル構造の注釈)を読み、その後必要に応じて特定のファイルを読みます。だからこそ、CLAUDE.md のファイル注釈が重要です。すべてを読まなくても、Agent を適切なファイルへ導けます。

大規模プロジェクト向けの戦略

  1. 詳細な CLAUDE.md ファイル注釈 — Agent がファイルマップを読み、関連ファイルへ直接移動できます
  2. Subagent への委任 — 探索や調査を subagent に振り分けます(クリーンなコンテキストで実行し、要約を返します)
  3. 焦点を絞ったプロンプト — 「SettingsView.swift に新しい toggle を追加する」は、「設定を更新する」より適切です
  4. セッション境界 — 長いセッションを延ばすより、無関係な機能では新しいセッションを開始します
  5. /compact を使う — Claude Code の compaction コマンドは会話を要約し、コンテキストを空けます

MCP のトークン効率

MCP を使う強力な理由の1つは、構造化された JSON responses が、生の xcodebuild 出力よりはるかに少ないトークンで済むことです。

シナリオ 生の Bash トークン数 MCP トークン数 削減率
成功した build 3,000-10,000 200-500 85-95%
失敗した build(1 error) 3,000-10,000 300-800 90-92%
Test results(20 tests) 2,000-5,000 500-1,000 75-80%
Simulator list 500-2,000 200-400 60-80%

10-20回の build cycle がある一般的な開発セッションでは、MCP は生の xcodebuild と比べて30,000-150,000トークンを節約できます。その分のトークンを、実際のコード推論に使えます。


トラブルシューティング

“build_sim failed — scheme not found”

Agent が scheme 名を推測しています。修正方法:

Use discover_projs and list_schemes to find the correct scheme name
for this project before building.

または、scheme 名を CLAUDE.md に明示的に追加します。

## Build
Primary scheme: `Return` (iOS)
Watch scheme: `ReturnWatch` (watchOS)
TV scheme: `ReturnTV` (tvOS)

“xcrun mcpbridge — command not found”

Xcode 26.3以降が必要です。xcodebuild -version で確認してください。Xcode 26.3以降を使っているのにコマンドがまだ失敗する場合:

# Ensure Xcode command line tools are selected
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

# Verify
xcrun mcpbridge --help

“MCP tools not appearing in Claude Code”

セッション途中で登録した MCP tools は、再起動するまで表示されない場合があります。Claude Code を終了し、新しいセッションを開始してください。

# Exit current session (Ctrl+C or /exit)
# Start fresh
claude

その後、確認します。

You: List all available MCP tools from XcodeBuildMCP.

“Agent keeps using xcodebuild via Bash instead of MCP”

Agent が Tool Search 経由で MCP tools を発見できていません。修正方法は2つあります。

  1. CLAUDE.md に明示的なガイダンスを追加するAgent に MCP の使い方を教えるを参照)
  2. 直接プロンプトする: “Use the build_sim MCP tool, not xcodebuild via Bash”

“Build succeeds but agent reports failure”

XcodeBuildMCP は xcodebuild 出力を解析します。build がエラーのように見える警告を出す場合(非推奨警告でよくあります)、Agent が結果を誤解することがあります。MCP response の実際の status field を確認してください。

“Simulator hangs during boot”

すべての simulators を終了して再起動します。

xcrun simctl shutdown all
xcrun simctl boot "iPhone 16 Pro"

または、Agent に依頼します。

Shut down all simulators, then boot a fresh iPhone 16 Pro.

“Agent tried to modify .pbxproj despite CLAUDE.md rules”

CLAUDE.md のルールは提案です。Hooks は強制です。.pbxproj への書き込みをブロックする PreToolUse hook がない場合、Agent はいずれ変更を試みます。hook をインストールしてください。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files.\" >&2; exit 2; fi'"
      }
    ]
  }
}

Rules は「やめてください」と伝えます。Hooks は「できません」と止めます。

FAQ

どのagent runtimeから始めるべきですか?

Claude Code CLI with XcodeBuildMCPから始めましょう。最も深いMCP統合、最も成熟したhookシステム、そしてiOSプロジェクト全体をworking memoryに保持できる1M context window(Opus 4.6)があります。まずはここから始め、workflowが成熟してきたら、review用にCodex、短いinline編集用にXcode native agentsを追加してください。

両方のMCPサーバーが必要ですか?

ほとんどの開発者には、XcodeBuildMCPだけでニーズの90%(build、test、simulator、debugging)をカバーできます。documentation検索、Swift REPL verification、SwiftUI preview renderingが必要な場合は、AppleのXcode MCPを追加してください。2つのサーバーは独立しているため、あとからいつでも追加できます。

agentsは新しいXcodeプロジェクトをゼロから作成できますか?

XcodeBuildMCPには、新しいXcodeプロジェクトをscaffoldするcreate_projectツールがあります。ただしproductionアプリでは、まずXcodeでプロジェクトを作成することをおすすめします。signing、capabilities、target configurationを正しく設定するためです。そのうえで、すべてのcode implementationにagentsを使います。Xcodeのnew project wizardに5分かけることで、agentが生成したproject configuration問題に何時間も費やす事態を避けられます。

agentsはSwift Package Manager dependenciesをどう扱いますか?

かなりうまく扱えます。Package.swiftは標準的なSwiftファイルなので、agentsは安定して読み書きできます。dependenciesの追加、version rangeの更新、targetsの設定はいずれも機能します。制約があるのは.xcodeprojベースのdependency管理(Xcodeのpackage resolution UI)です。これはXcodeが管理する領域なので、agentで編集すべきではありません。

agentsはApp Storeにsubmitできますか?

いいえ。App Store submissionには、XcodeのOrganizer、provisioning profiles、screenshots、metadata、App Store Connect portalが関わります。これらはMCPやcommand-line tools経由で、agentsが意味のある形で操作できるものではありません。agentsが担当できるのはarchiveの手前まで、つまりimplementation、testing、bug fixing、documentationです。submissionの最後の一歩は、引き続き人間が操作します。

ただし、agentsはApp Store metadataの作成には役立ちます。最新の変更内容をもとに、アプリのdescription、keywords、what’s-new textを書くよう依頼してください。これはagentsが得意なtext generation作業です。

agent支援のiOS開発でsecretsやAPI keysをどう扱えばよいですか?

secretsは絶対にcommitしないでください。backend APIsに接続するiOSアプリでは、次のようにします。

  1. 環境別の設定には.xcconfigファイルを使います
  2. .xcconfigファイルを.gitignoreに追加します
  3. Info.plistのbuild settings経由でconfig valuesを参照します
  4. 必要なsecretsはCLAUDE.mdに記録しますが、実際の値は含めません
## Configuration

API base URL and keys are in `Config.xcconfig` (not committed).
Required keys:
- `API_BASE_URL` — Backend server URL
- `API_KEY` — Authentication token

Create `Config.xcconfig` from `Config.xcconfig.template`.

agentはkeysが存在することと使われる場所を把握しますが、実際の値を見ることはありません。

SwiftUI animationsはどうですか。agentsは書けますか?

agentsはanimation codeを構文的にはうまく書けますが、結果を視覚的に検証できません。単純なanimations(.animation(.spring()).transition(.slide)withAnimation { })なら正しい結果になります。正確なtimingが必要な複雑なmulti-step animationsは、agentsにはできないvisual iterationが必要です。

有効: 「timerがstate間でtransitionするときにspring animationを追加してください。」

無効: 「timer animationが気持ちよく感じられるようにしてください。」(主観的で、visual tuningが必要です。)

agentsはerror handling patternsをどう扱いますか?

非常にうまく扱えます。agentsはSwiftのdo/catchResultasync throws patternsを理解しています。

Implement error handling for the HealthKit authorization flow:
1. Check HKHealthStore.isHealthDataAvailable()  show alert if not
2. Request authorization  handle denial gracefully
3. On write failure  retry once, then show error
4. All errors should be user-facing with localized descriptions

agentsは適切なuser-facing messagesを含むstructured error handlingを生成します。ただし、ときどきerrorsを過剰に扱うことがあります(propagateすべきexceptionsをcatchするなど)。catch blocksはreviewしてください。

accessibility implementationにagentsを使えますか?

一部は使えます。agentsはaccessibility labels、hints、traitsを正しく追加できます。

Add accessibility labels to all interactive elements in TimerView:
- Timer display: current time remaining
- Start/Pause button: current state and action
- Reset button: "Reset timer"
- Duration picker: selected duration

agentsにできないことは、VoiceOverのnavigation orderが正しいかの検証、Dynamic Type scalingのtest、color contrast ratiosの評価です。検証にはXcodeのAccessibility Inspectorを使ってください。

SwiftDataを使っていない場合、Core Data migrationはどう扱いますか?

agentsはCore Data migration mappingsやmodel versionsを書けますが、手動のXcode手順(新しいmodel versionsの作成、current versionの選択)は自動化できません。SwiftDataではなくまだCore Dataを使っている場合は、CLAUDE.mdにmodel version historyを記録してください。

## Core Data Model Versions
- V1: Initial (GroceryList, GroceryItem)
- V2: Added Category model (current)
- Migration: Lightweight automatic for V1→V2

agentsはSwiftUI previewsをどう扱いますか?

方法は2つあります。 1. Apple Xcode MCPのRenderPreviewツールはpreviewsをheadlessにrenderし、結果を返します。agentはpreviewがcompileされ、errorsなしでrenderされることを確認できますが、visual correctnessは評価できません。 2. build_simによるbuild-based verificationでは、preview providersがcompileされることを確認できます。previewがruntimeでcrashしてもbuildは成功します。crashが現れるのは、Xcodeがpreviewをrenderしようとしたときだけです。

previewsのvisual verificationには、やはりXcodeを開く必要があります。

visionOSとApple Vision Proはどうですか?

同じpatternsが適用できます。XcodeBuildMCPはvisionOS simulatorsをサポートしており、architectural patterns(@Observable、NavigationStack、SwiftData)も同じです。RealityKit固有のcode(3D content、immersive spaces、hand tracking)はMetalと同じ制約があります。agentsは正しいcodeを書けますが、spatial outputは検証できません。

agentsが苦しくなるproject sizeはどのくらいですか?

制約になるのはcontext window sizeです。Opus 4.6の1M token windowがあれば、Claude Codeは約50〜70個のSwiftファイルを同時にactive working memoryへ保持できます。さらに大きなプロジェクトでは、agentはfile searchとselective readingを使い、codebaseの一部を対象に作業します。100以上のファイルがあるプロジェクトでも問題なく動きます。すべてをcontextに保持するのではなく、必要に応じてファイルを読むだけです。

実用上の限界はfile countではなく、codebase coherenceです。詳細なCLAUDE.mdがある、よくdocumentedされた200ファイルのプロジェクトのほうが、documentationのない30ファイルのプロジェクトより良い結果になります。

iOS開発でagentsを使うにはSwiftを知っている必要がありますか?

agent outputをreviewし、architectural decisionsを下せる必要があります。すべての行を自分で書く必要はありませんが、agentが誤った選択をしたときに気づける程度にはSwiftを理解している必要があります。特にconcurrency、memory management、framework-specific patternsの周辺です。agentは既存のskillを10倍に増幅するものであり、代替するものではありません。

agentsはSwiftファイルのmerge conflictsをどう扱いますか?

agentsはSwift source filesのmerge conflictsを安定して解決できます。標準的なconflict markers(<<<<<<<=======>>>>>>>)は、すべてのagent runtimesがよく理解しています。ただし、.pbxprojファイルのmerge conflictsは引き続き手動で解決する作業です。.pbxproj conflictsの解決をagentsに依頼しないでください。

iOS開発でagentsを実行するcostはどのくらいですか?

AnthropicのMax plan(Opus 4.6、1M context)では、一般的なiOS development sessionは30〜120分で、200K〜800K tokensを処理します。MCP tool callsによるoverheadは最小限です(structured JSON responsesは、raw build outputと比べてtoken効率が高いためです)。costは、他のcodebaseでClaude Codeを実行する場合と同程度です。iOS開発がweb developmentより大幅に高くなったり安くなったりするわけではありません。

UIKit projectsでもagentsを使えますか?

はい。ただしagentsはSwiftUIのほうが効果的です。UIKitはboilerplateが多く、declarative structureが少なく、agentsが編集できないInterface Builder filesを伴うこともよくあります。UIKit projectがある場合は、UIは手動で扱いながらmodel layerやbusiness logicにagentsを使うか、viewsを段階的にSwiftUIへ移行することを検討してください。

agentsはlocalizationをどう扱いますか?

agentsは.xcstrings(Xcode string catalog)ファイルを効果的に作成・編集できます。新しいlocalization keysの追加、translationsの提供、languages間のconsistency維持が可能です。.xcstringsファイルのstructured JSON formatはagentに扱いやすい形式です。.stringsファイル(legacy format)でも、agentsはうまく処理できます。key-value formatが単純だからです。


iOSでよくあるAgentのミス(と防ぎ方)

ここでは、8つのiOSプロジェクトで数千回のAgentとのやり取りを通じて観察した、繰り返し起きるエラーをまとめています。それぞれに予防策があります。

ミス1: Observableパターンを混在させる

何が起きるか: Agentがあるファイルでは@Observableを使い、別のファイルではObservableObjectを使います。あるいは、すでにObservableである@Modelクラスに@Observableを追加してしまいます。

予防策: CLAUDE.mdに明示的なルールを書きます。

- NEVER use ObservableObject — use @Observable
- NEVER add @Observable to @Model classes (already Observable)
- NEVER use @StateObject — use @State with @Observable
- NEVER use @ObservedObject — access @Observable properties directly

ミス2: クロージャでRetain Cycleを作る

何が起きるか: Agentがselfを強参照でキャプチャするクロージャを作ります。特にTimer.publishNotificationCenter、completion handlerで起きやすいです。

予防策: CLAUDE.mdにクロージャのパターンを含めます。

## Closure Pattern
- Timer callbacks: use `[weak self]` and guard
- NotificationCenter observers: store in `Set<AnyCancellable>` and use `[weak self]`
- Completion handlers: use `[weak self]` for any closure stored beyond the call site

ミス3: @MainActor要件を無視する

何が起きるか: Agentが@MainActor分離なしで@Observableクラスを作り、UI更新がメインスレッド外で発生したときにSwift 6.2の並行処理警告やランタイムクラッシュを引き起こします。

予防策:

## Concurrency Rule
ALL @Observable classes MUST be @MainActor:
```swift
@Observable
@MainActor
final class SomeManager { }
```

ミス4: Destination Closure付きのNavigationLinkを使う

何が起きるか: Agentが、型安全なNavigationLink(value:) + .navigationDestination(for:)パターンではなく、非推奨のNavigationLink(destination:label:)を使います。

予防策:

## Navigation Pattern
ALWAYS use value-based navigation:
```swift
NavigationLink(value: item) { ItemRow(item: item) }
.navigationDestination(for: Item.self) { ItemDetailView(item: $0) }
```
NEVER use: `NavigationLink(destination: ItemDetailView(item: item)) { }`

ミス5: Simulator名をハードコードする

何が起きるか: Agentが、システムに存在しない可能性のある特定のSimulator名(”iPhone 16 Pro”)を使ってビルドコマンドを書きます。

予防策: これはMCPが処理します。list_simsが利用可能なSimulatorを検出します。CLAUDE.mdでは次のようにします。

## Simulators
Do NOT hardcode simulator names. Use `list_sims` MCP tool to discover
available devices, then `boot_sim` with the discovered device ID.

ミス6: 間違ったディレクトリにファイルを作る

何が起きるか: Agentが新しいViewファイルをViews/サブディレクトリではなくプロジェクトルートに作ったり、modelを間違ったグループに置いたりします。

予防策: CLAUDE.mdのファイル構造アノテーションが配置を案内します。加えて、次のようにします。

## File Placement Rules
- Views → `AppName/Views/`
- Models → `AppName/Models/`
- Managers → `AppName/Managers/`
- Extensions → `AppName/Extensions/`
- Tests → `AppNameTests/`

ミス7: Platform Availabilityを扱わない

何が起きるか: Agentが、tvOS向けにもコンパイルされる共有コードでHealthKitを使ったり(tvOSではHealthKitは利用不可)、watchOSコードでActivityKitを使ったりします。

予防策:

## Platform Guards
- HealthKit: `#if canImport(HealthKit)` (unavailable on tvOS)
- ActivityKit: `#if canImport(ActivityKit)` (iOS only)
- WatchKit: `#if os(watchOS)`
- UIKit haptics: `#if os(iOS)` (unavailable on tvOS, watchOS uses WKHaptic)

ミス8: シンプルな機能を過剰設計する

何が起きるか: 本来は20行のユーティリティ関数で済むはずのものに対して、Agentがprotocol、protocol extension、具体実装、factory、dependency injection containerを作ってしまいます。

予防策: シンプルさの原則を含めます。

## Architecture Principle
Prefer the simplest solution that handles the requirements.
- Direct implementation over protocol abstraction (unless you have 2+ conforming types)
- Concrete types over generics (unless reuse is proven)
- Extensions on existing types over new wrapper types

正直な評価

AI Agentで8つのiOSアプリを出荷してきた結果をまとめると、次のようになります。

Agentが変えたもの: 実装速度です。数日かかっていたことが数時間で済むようになりました。SwiftUI View、SwiftData model、unit test、refactoringは、いまでは主にAgentが生成し、人間がレビューするものになっています。

Agentが変えなかったもの: アーキテクチャ判断、ビジュアルデザイン、パフォーマンス最適化、App Store提出です。これらは今も人間主導です。

倍率効果は本物ですが、限界もあります。 8アプリのポートフォリオ全体での主観的な見積もりでは、適切なMCPとhook設定があり、よく文書化されたプロジェクトでは、機能追加までの時間が3〜5倍改善しました。これはcontrol groupと比較して測定したものではありません。同じコードベース内で、Agent支援による機能実装と同等の単独作業を、実時間で比較したものです。文書化されておらずhookもないプロジェクトでは、おそらく1.5〜2倍程度です。Agentが構築するよりも推測に時間を使いすぎるためです。24

投資に見合うもの: CLAUDE.md、hook、MCP設定に使う時間です。セットアップに1時間かけるたびに、Agentのミスを修正する多くの時間を節約できます。設定こそがプロダクトであり、Agentは実行エンジンです。

意外だったこと: MCPサーバーが、やり取りの構造を大きく変えたことです。MCP以前のAgentは、Swiftを理解する高機能なテキストエディタでした。MCP以後は、書き、ビルドし、テストし、デバッグし、反復する開発パートナーになりました。構造化されたフィードバックループこそが、コードを書くAgentと、コードを出荷するAgentの違いです。

過去の自分に伝えるなら: まず最小のアプリ(Reps、14ファイル)から始め、MCPとhookのセットアップを正しく整え、充実したCLAUDE.mdを書き、そのパターンを大きなプロジェクトへ広げましょう。63ファイルのマルチプラットフォームアプリから始めてはいけません。インフラへの投資は、プロジェクトの規模に関係なく同じです。小さなプロジェクトで一度行い、それをほかのすべてにコピーします。

今後: Xcode 26.3のネイティブAgent統合は終点ではなく始まりです。AppleがMCPサポートを出荷したことで、ツールチェーンはAgent-first開発へ向かっています。今のうちにAgentと相性のよいプロジェクト構造、つまり整理されたCLAUDE.mdファイル、テストしやすいアーキテクチャ、自動化されたhookへ投資する開発者は、ツールの改善とともにその投資を複利で伸ばしていけるでしょう。


クイックリファレンスカード

インストール(1回限りのセットアップ)

# XcodeBuildMCP (59 tools)
claude mcp add XcodeBuildMCP -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

# Apple Xcode MCP (20 tools)
claude mcp add --transport stdio xcode -s user -- xcrun mcpbridge

# Codex MCP setup
codex mcp add xcode -- xcrun mcpbridge

# Verify
claude mcp list

必須のCLAUDE.mdセクション

1. Project identity (bundle ID, target OS, architecture)
2. File structure with annotations
3. Build and test commands
4. Key patterns and rules
5. Prohibitions (NEVER touch .pbxproj)
6. Framework-specific context

必須のHooks

{
  "PreToolUse": [{ "matcher": "Edit|Write", "command": "block .pbxproj" }],
  "PostToolUse": [{ "matcher": "Edit|Write", "command": "swiftformat" }]
}

アーキテクチャルール

@Observable         (not ObservableObject)
NavigationStack     (not NavigationView)
@State              (not @StateObject)
SwiftData @Model    (not Core Data)
async/await         (not completion handlers)
@MainActor          (on all Observable classes)
.glassEffect()      (Liquid Glass, iOS 26+)

MCPツールの優先順位

Build:     build_sim          (not xcodebuild via Bash)
Test:      test_sim           (not xcodebuild test via Bash)
Sim:       list_sims/boot_sim (not xcrun simctl via Bash)
Docs:      DocumentationSearch (not WebSearch)
REPL:      ExecuteSnippet     (not swift via Bash)

変更履歴

日付 変更内容
2026-06-08 WWDC 2026 / iOS 27 beta。 「iOS 27 and WWDC 2026: What Your Agent Now Builds With」セクションと TL;DR メモを追加しました。6月8日の基調講演時点で iOS 27 は beta ですが、出荷版は引き続き iOS 26 です。そのため、このセクションでは、エージェント開発ワークフロー(runtimes、MCP、CLAUDE.md、hooks)は変わらないまま、新しい frameworks を iOS 27 beta SDK に対して何をターゲットにするかとして位置づけています。エージェントに関連する追加項目は、それぞれ検証済みの詳説にクロスリンクしています。Foundation Models GenerationOptions.ToolCallingMode + 組み込み Vision tools(OCRTool/BarcodeReaderTool)、App Intents LongRunningIntent/performBackgroundTaskSyncableEntityIndexedEntityQuery、新しい Core AI framework(Apple Silicon 上で独自モデルを実行)、新しい Evaluations framework(モデル品質のための XCTest)、さらに SwiftData observation/history、HealthKit workout zones、SwiftUI iOS 27 です。Xcode バージョンの指針は変更していません。Apple は検証済みの「Xcode 27」バージョンを公開していないため、このガイドでは Xcode 26.5 stable の推奨を維持しています。operator note として、2026年6月以前のモデルは iOS 26 の形をデフォルトにするため、エージェントのコンテキストでこれらの frameworks を明示するようにしています。
2026-05-28 Beta channel + WWDC26 の位置づけ。 Apple Developer(5月26日)は、iOS 26.6、iPadOS 26.6、macOS 26.6、tvOS 26.6、visionOS 26.6、watchOS 26.6 の beta リリースと Xcode 26.6 beta を発表しました。call to action では、新しい beta SDKs に対して Xcode 26.5 でビルドとテストを行うよう具体的に述べています。そのため、エージェントワークフローでは DEVELOPER_DIR を beta に切り替えるのではなく、安定版 Xcode 26.5(build 17F42)に xcode-select を固定したまま、将来互換性テスト用に beta SDKs を並行インストールするのがよいでしょう。WWDC26(5月18日発表) は 2026年6月8日から12日に予定されています。Swift、SwiftUI、App Intents、Foundation Models、オンデバイスのエージェント APIs にとって、次の大きな転換点になる可能性があります。このガイドの Coding Intelligence と Foundation Models の指針は、引き続き Xcode 26.5 stable を対象にしています。beta-channel SDKs は、production のエージェントワークフロー向け基盤としてはまだ推奨していません。Apple Developer(5月21日)は、オーストラリアとベトナム向けの年齢レーティング変更も発表しました。2026年6月18日から有効です。エージェントとは直接関係しませんが、ポートフォリオの compliance 上は注意しておく価値があります。
2026-05-24 Xcode 26.5 stable のリリース日を 2026-05-11 に修正し、Apple の releases ページに基づいて build を 17F42 に固定しました。今回のローカル検証では、xcodebuild -versionXcode 26.5 / Build version 17F42 を返しました。また、xcodebuildmcp の npm latest は 2.5.2time.modified2026-05-12T07:40:41.737Z でした。18
2026-05-16 推奨 Xcode を 26.5+(2026-05-11 リリース)に引き上げました。新しい Coding Intelligence 機能のうち、エージェントワークフローで重要なものが 2 つあります。coding assistant でメッセージをキューに入れられるようになり、次の依頼を並べる前に応答を待つ必要がなくなりました。また、エージェントが進行前に確認質問をできるようになりました。どちらも、Xcode ネイティブのエージェントを Claude Code や Codex セッションと並行して実行するときの摩擦を減らします。18 XcodeBuildMCP の最新性チェック: v2.5.2(2026-05-12)が最新で、同梱 AXe 1.7.0 と log-capture filter-validation 問題の修正が追加されています。v2.1.0+ からの xcodebuildmcp init フローは、引き続き推奨インストール手順です。
2026-04-28 エージェントワークフロー向けの推奨 Xcode を 26.4+ に引き上げました(26.4.1、2026-04-16、build 17E202 が最新 stable で、bug-fix のみ)。エージェントが書くテストとローカライゼーションに役立つ Xcode 26.4 機能(2026-03-24、build 17E192)を引用しました。Swift Testing の画像添付、Issue.record の severity、添付 crashlogs 付きの UI-test crash warnings(特に XCUIApplication(bundleIdentifier:) / XCUIApplication(url:) apps 向け)、String Catalog editor の改善です。手動 MCP 設定の代替として、xcodebuildmcp init auto-installer(v2.1.0+、2026-02-23)を追加しました。
2026-04-27 App Store Connect: 2026-04-28 から Xcode 26+ での提出が必須になります。Foundation Models に SystemLanguageModel.contextSizetokenCount(for:) APIs が追加されました(iOS 26.4 に back-deploy)。エージェントが生成する FM prompt-budget code のパターンを追加しました。iOS 26.4.2(4月22日)と iOS 26.5 beta 3(4月20日)は、エージェント toolchain に影響する変更なしでリリースされました。
2026-04-13 初回公開。8 apps、3 runtimes、MCP setup、CLAUDE.md patterns、hooks、case studies。

参照


  1. XcodeBuildMCP には、デフォルトで Sentry テレメトリが含まれています。プロジェクトのプライバシードキュメントでは、送信される内容として、エラーメッセージ、スタックトレース、場合によってはファイルパスが詳しく説明されています。XCODEBUILDMCP_SENTRY_DISABLED=true 環境変数を設定すると、完全にオプトアウトできます。 

  2. Anthropic、「Model Context Protocol Specification」、modelcontextprotocol.io/specification。MCP 仕様では、XcodeBuildMCP と Apple の Xcode MCP の両方が実装している JSON-RPC トランスポート、ツール検出、リソースプロトコルを定義しています。 

  3. XcodeBuildMCP、github.com/getsentry/XcodeBuildMCP。Sentry が保守するオープンソースです。シミュレーター、デバイス、デバッグ、UI 自動化ワークフローにまたがる 59 個のツールがあります。セマンティックバージョニングと changelog に対応しています。 

  4. Apple は Xcode 26.3 のインテリジェント開発者ツール施策の一部として Xcode MCP サーバーを導入し、MCP を AI コーディングアシスタントと Xcode ツールチェーンの間にあるインターフェース層として位置づけました。公式ドキュメントについては Xcode Release Notes をご覧ください。 

  5. Rudrank Riyam、「Exploring Xcode Using MCP Tools」、rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients、2026年。Apple の MCP ツール数、XPC 依存関係、ドキュメント検索機能についての独立した確認です。 

  6. Jimenez, C.E., Yang, J., Wettig, A., et al.、「SWE-bench: Can Language Models Resolve Real-World GitHub Issues?」ICLR 2024。arxiv.org/abs/2310.06770。構造化されたツールアクセスを持つ agent は、非構造化シェルコマンドのみに制限された agent を大きく上回りました。この結果は、agent の有効性における構造化 MCP インターフェースの価値を裏づけています。 

  7. Claude Code CLI ドキュメント、code.claude.com。hook システム、MCP 設定、subagent 委任、agent 定義。 

  8. SwiftFormat、github.com/nicklockwood/SwiftFormat。一貫したコードスタイルのために PostToolUse hooks で使用する Swift フォーマットツールです。 

  9. XcodeBuildMCP 公式サイト、xcodebuildmcp.com。CLI 出力例により、59 個の MCP ツールを確認できます。ツールカテゴリは、シミュレーター、デバイス、デバッグ、UI 自動化です。Homebrew または npx でインストールできます。 

  10. Swiftjective-C、「Agentic Coding in Xcode 26.3 with Claude Code and Codex」、swiftjectivec.com、2026年2月。Xcode 26.3 には Settings > Intelligence 経由でネイティブの Claude Agent と Codex ランタイムサポートが搭載されていることを確認しています。xcrun mcpbridge 経由で 20 個の MCP ツールが公開されます。 

  11. Blake Crosley、「Two MCP Servers Made Claude Code an iOS Build System」、blakecrosley.com/blog/xcode-mcp-claude-code、2026年2月。同じ著者の iOS 開発ワークフローに基づく、セットアップ手順と実運用での結果です。 

  12. Foundation Models in iOS 27: Tool-Calling Control。Apple の Foundation Models に関する iOS 27 ベータドキュメント(GenerationOptions.ToolCallingModeOCRToolBarcodeReaderTool)を出典としています。WWDC 2026、2026年6月8日確認。 

  13. App Intents in iOS 27: Background, Sync, Spotlight。Apple の App Intents に関する iOS 27 ベータドキュメント(LongRunningIntentperformBackgroundTask(options:operation:)SyncableEntityIndexedEntityQuery)を出典としています。WWDC 2026、2026年6月8日確認。 

  14. Core AI: Running Models on Apple Silicon。Apple Silicon 上で独自モデルを実行するための新しい iOS 27 / macOS 27 Core AI フレームワークを扱っています。WWDC 2026、2026年6月8日確認。 

  15. Evaluations: XCTest for Model Quality。テストスイートでモデル出力品質を測定するための新しい macOS 27 Evaluations フレームワークを扱っています。WWDC 2026、2026年6月8日確認。 

  16. SwiftData in iOS 27: Observation and HistoryHealthKit in iOS 27: Workout Zones, New TypesWhat’s New in SwiftUI for iOS 27。いずれも Apple の iOS 27 ベータドキュメントを出典としています。WWDC 2026、2026年6月8日確認。 

  17. Apple Developer News、“Upcoming Requirements”。2026-04-28 の項目には、「App Store Connect にアップロードされるアプリは、iOS 26、iPadOS 26、tvOS 26、visionOS 26、または watchOS 26 向けの SDK を使用して、Xcode 26 以降でビルドされている必要があります」とあります。この要件で列挙されているプラットフォームには macOS は含まれていません。 

  18. Apple、“Xcode 26.5 Release Notes” および “Xcode 26.5 (17F42) - Releases”。Xcode 26.5 は Apple により 2026-05-11 に build 17F42 として掲載されました。リリースノートから引用した Coding Intelligence の機能は 2 つあります。現在の応答が完了するのを待たずに coding assistant にメッセージをキューイングできること(174563016)と、agent が作業を進める前に文脈を集めるための確認質問をできること(175182375)です。また、12か月契約の月額サブスクリプション向け StoreKit Testing サポート(PricingTerms モデル、billingPlanType PurchaseOptionTransactionSubscriptionRenewalInfoCommitmentInfo)と、async/await 操作中にスレッドを移動する Swift Tasks をステップ実行する際の Swift デバッガ修正も含まれます。2026-05-24 の現行セッション検証では、xcodebuild -versionXcode 26.5Build version 17F42 を返し、npm view xcodebuildmcp version dist-tags.latest time.modified --json は latest 2.5.2time.modified 2026-05-12T07:40:41.737Z を返しました。あわせて参照: 9to5Mac、“Xcode 26.5 adds two features that make agentic coding more useful”、2026-05-12。 

  19. Apple、“Xcode 26.4 Release Notes”。Xcode 26.4(2026-03-24、build 17E192)。リリースノートから引用した機能は次のとおりです。Swift Testing は CGImageNSImageUIImageCIImage による画像添付をサポートするようになりました。Issue.record は重大度レベルを受け付けます。一部の UI-test アプリクラッシュ、具体的には XCUIApplication(bundleIdentifier:) または XCUIApplication(url:) を通じて操作されるアプリのクラッシュは、テスト失敗ではなく crashlog 添付の警告として報告されます。String Catalog エディタには、エントリの cut/copy/paste、言語の削除、既存言語からの翻訳事前入力に加えて、BUILD_ONLY_KNOWN_LOCALIZATIONS 設定が追加されました。 

  20. Apple Developer News、“Xcode 26.4.1 (Build 17E202) Now Available”、2026-04-16。バグ修正のみのドットリリースです。iOS / macOS / visionOS 26.4 より前の環境でシンボル不足により発生する MetricKit クラッシュと、Swift の async スタック割り当てバグ(swift_asyncLet_finish における “freed pointer was not the last allocation”)を修正しています。 

  21. getsentry/XcodeBuildMCP v2.1.0 release、2026-02-23。agent skills と MCP 設定を 1 ステップでインストールする xcodebuildmcp init CLI コマンドを追加し、単体の install-skill.sh スクリプトを置き換えました。Claude Code、Cursor、Codex を自動検出します。--print(未対応クライアント向けに設定を stdout へ出力)と --uninstall(削除)をサポートしています。 

  22. InfoQ、“Apple Adds Context Window Management to Foundation Models”、2026年3月。新しい SystemLanguageModel.contextSizetokenCount(for:) APIs を記録し、@backDeployed(before: iOS 26.4) アノテーションを確認しています。従来のコミュニティによる 4096-token ハードコードという推測を置き換えるものです。 

  23. ファイル数は、2026-04-27 に 8 つの非公開アプリリポジトリそれぞれで実行した find . -name '*.swift' -not -path '*/Tests/*' | wc -l から算出しています。テストファイルは除外しています。合計は §The Portfolio のアプリ別内訳表と内部的に整合しています。 

  24. 主観的な実時間の見積もりであり、対照群との測定ではありません。3-5x という数字は、2026年の agent 支援機能と、agent ワークフロー導入前に同じコードベースで単独実装して出荷した同等機能との time-to-feature 比較について、著者の記憶に基づくものです。ベンチマークではなく、MCP と hook のセットアップ後に期待できる目安として扱ってください。 

NORMAL ios-agent-development.md EOF