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

Créer des applications iOS avec des agents IA : le guide du praticien

# Créez des applications iOS plus rapidement avec des agents IA. Claude Code, Codex CLI, Xcode 26.3 natif, MCP, modèles CLAUDE.md, hooks, leçons tirées de 8 applications.

words: 14297 read_time: 72m updated: 2026-04-28 22:16
$ less ios-agent-development.md

TL;DR : Trois runtimes d’agents livrent désormais du code pour iOS : Claude Code CLI avec MCP, Codex CLI avec MCP, et les agents Intelligence natifs de Xcode 26.3. Deux serveurs MCP (XcodeBuildMCP avec 59 outils et xcrun mcpbridge d’Apple avec 20 outils) donnent aux agents un accès structuré aux builds, aux tests, aux simulateurs et au débogage. Ce guide couvre de vrais patterns CLAUDE.md, des configurations de hooks, et des évaluations honnêtes de ce qui fonctionne et de ce qui casse — tirées de 8 applications iOS en production totalisant 293 fichiers Swift.17 Les agents excellent sur les vues SwiftUI, les modèles SwiftData, le refactoring et le diagnostic des erreurs de build. Ils échouent sur les modifications de .pbxproj, la signature de code et le débogage visuel. L’écart entre « l’agent écrit du Swift » et « l’agent livre une application iOS » se comble par la configuration, pas par le prompting.

J’ai construit 8 applications iOS avec des agents de codage IA. Pas des prototypes — des applications dans l’App Store, avec des intégrations HealthKit, des shaders Metal, de la physique SpriteKit, de la synchronisation iCloud, des Live Activities, des classements Game Center et des cibles multi-plateformes couvrant iOS, watchOS et tvOS. Chaque ligne de Swift dans ces applications a été soit écrite par un agent et relue par moi, soit écrite par moi et refactorisée par un agent. Selon mon estimation, les agents ont géré l’essentiel de l’écriture au niveau des lignes ; je me suis chargé de la relecture, du périmètre et des parties qui exigent un jugement humain (finitions visuelles, signature, optimisation des performances, soumission à l’App Store).

Ce guide est la référence que j’aurais aimé avoir quand j’ai commencé. Il couvre toute la pile : quel runtime d’agent utiliser, comment configurer les serveurs MCP pour un accès structuré au build, ce qu’il faut mettre dans votre CLAUDE.md, quels hooks empêchent l’agent de détruire votre projet Xcode, et — surtout — où les agents échouent et où vous devez reprendre le volant.

Points clés à retenir

Pour les développeurs iOS qui débutent avec les agents IA :

  • Commencez avec Claude Code CLI + XcodeBuildMCP. C’est le runtime le plus mature avec la couverture d’outils MCP la plus profonde. Installez deux commandes, ajoutez un CLAUDE.md à votre projet, et l’agent peut compiler, tester et déboguer sans que vous ayez à copier les messages d’erreur.
  • Ne laissez jamais un agent modifier .pbxproj. C’est la règle la plus importante. Un hook PreToolUse qui bloque les écritures sur .pbxproj et .xcodeproj/ vous épargnera des heures de récupération.
  • Votre CLAUDE.md est le document d’onboarding de l’agent. Les heures que vous y consacrez vous sont rendues sur chaque session d’agent qui touche au projet.

Pour les utilisateurs expérimentés d’agents qui ajoutent iOS à leur workflow :

  • MCP transforme la boucle de build iOS. Avant MCP, les agents écrivaient du Swift mais ne pouvaient pas vérifier qu’il compilait. Avec XcodeBuildMCP, l’agent écrit le code, le compile, lit les erreurs structurées, les corrige et exécute les tests — de manière autonome.
  • Trois runtimes répondent à des besoins différents. Claude Code CLI pour les sessions agentiques approfondies, Codex CLI pour le travail batch en headless, les agents natifs de Xcode 26.3 pour des correctifs inline rapides sans quitter l’IDE.
  • L’infrastructure de hooks se transpose. Vos formateurs PostToolUse, vos bloqueurs PreToolUse et vos hooks de runner de tests existants fonctionnent à l’identique sur les projets iOS, avec des ajustements de chemins mineurs.

Pour les responsables d’équipe qui évaluent le développement iOS assisté par IA :

  • L’efficacité des agents évolue avec la documentation du projet, pas avec sa taille. Une application de 63 fichiers avec un CLAUDE.md détaillé produit de meilleurs résultats d’agent qu’une application de 14 fichiers sans aucune documentation.
  • La frontière du .pbxproj est non négociable. Les agents ne peuvent pas modifier de manière fiable les fichiers de projet Xcode. Votre workflow doit prévoir l’ajout manuel des fichiers aux cibles Xcode.
  • ROI honnête : les agents gèrent l’essentiel de l’implémentation sur des projets bien documentés — visible dans l’application TV de 15 fichiers livrée en 3 heures de travail assisté par agent (étude de cas ci-dessous). Le travail restant — finitions visuelles, signature, optimisation des performances, soumission à l’App Store — exige un jugement humain.

Choisissez votre parcours

Ce dont vous avez besoin Allez ici
Configurer MCP pour la première fois MCP Setup : The Complete Configuration — installez les deux serveurs, vérifiez, configurez les agents
Écrire un CLAUDE.md pour votre projet iOS CLAUDE.md Patterns for iOS Projects — exemples réels tirés de 8 applications
Comparer les trois runtimes d’agents Three Agent Runtimes for iOS — Claude Code vs. Codex vs. Xcode natif
Comprendre ce que les agents savent et ne savent pas faire What Agents Do Well et What Agents Do Poorly
Mettre en place des hooks pour le développement iOS Hooks for iOS Development — format-on-save, protection .pbxproj, runners de tests
Référence approfondie (cette page) Continuez à lire — tout, du setup aux patterns avancés

Comment utiliser ce guide

C’est une référence de plus de 3 000 lignes. Commencez là où votre niveau d’expérience correspond :

Expérience Commencez ici Puis explorez
Nouveau sur iOS et les agents PrerequisitesMCP SetupYour First Agent Session CLAUDE.md Patterns, What Works/Doesn’t
Développeur iOS, nouveau sur les agents Three RuntimesMCP SetupCLAUDE.md Hooks, Architecture Patterns
Utilisateur d’agents, nouveau sur iOS Architecture PatternsWhat Agents Do PoorlyCLAUDE.md Framework-Specific Context, Advanced Workflows
Expérimenté sur les deux Advanced WorkflowsHooksMulti-Platform Patterns Runtime Comparison, The Portfolio

Table des matières

  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

Ressources connexes

Sujet Ressource
Configuration MCP pour Xcode (article de blog plus court) Two MCP Servers Made Claude Code an iOS Build System
Référence complète Claude Code CLI Claude Code CLI: The Complete Guide
Référence Codex CLI Codex CLI: The Complete Guide
Plongée dans le système de hooks Anatomy of a Claw: 84 Hooks as an Orchestration Layer
Patterns d’architecture d’agents Agent Architecture Guide

Le portefeuille : 8 applications, 293 fichiers

Avant de plonger dans la configuration, voici les sources dont s’inspire ce guide. Il ne s’agit pas de projets jouets — ils couvrent cinq frameworks Apple, trois plateformes et toute la gamme de complexité iOS, depuis un suivi d’entraînement de 14 fichiers jusqu’à un minuteur de méditation multiplateforme de 63 fichiers.

Application Stack Fichiers Complexité
Banana List SwiftUI + SwiftData + synchronisation iCloud Drive + serveur MCP pour Claude Desktop 53 CRUD complet, synchronisation iCloud, serveur MCP personnalisé qui expose les données de l’application à Claude Desktop
Ace Citizenship Application d’étude SwiftUI + backend FastAPI 26 Client-serveur, intégration REST API, moteur de quiz
TappyColor Jeu d’association de couleurs SpriteKit 30 Boucle de jeu, physique, gestion tactile, effets de particules
Return Minuteur de méditation zen — iOS 26+, watchOS, tvOS 63 HealthKit, Live Activities, exécution prolongée Watch, navigation focus TV, synchronisation des sessions iCloud
amp97 Shaders Metal + visualisation audio 41 Pipeline de rendu Metal personnalisé, analyse audio, calcul GPU en temps réel
Reps Suivi d’entraînement SwiftUI + SwiftData 14 Application minimale viable, patterns SwiftData épurés
Water Suivi d’hydratation SwiftUI + SwiftData + Metal + HealthKit 34 Simulation de fluide Metal, journalisation de la consommation d’eau HealthKit, widget
Starfield Destroyer Shoot ‘em up spatial SpriteKit + Metal 32 99 niveaux, 8 vaisseaux, classements Game Center, post-traitement Metal

Pourquoi le nombre de fichiers compte : l’efficacité des agents est corrélée à la lisibilité du projet, pas à sa taille. Return (63 fichiers) produit de meilleurs résultats agentiques qu’amp97 (41 fichiers) parce que Return dispose d’un CLAUDE.md détaillé avec annotations de fichiers, diagrammes d’architecture et patterns explicites. Les shaders Metal d’amp97 sont intrinsèquement plus difficiles à appréhender pour les agents, indépendamment de la qualité de la documentation.


Prérequis

Avant de mettre en place un runtime d’agent pour le développement iOS :

Échéance App Store Connect : à partir du 28 avril 2026, les applications téléversées sur App Store Connect doivent être construites avec Xcode 26 ou ultérieur en utilisant les SDKs pour iOS 26, iPadOS 26, tvOS 26, visionOS 26 ou watchOS 26.12 (Les soumissions macOS ne sont pas concernées par cette exigence.) Si votre équipe est encore sur Xcode 16.x, la chaîne d’outils assistée par agent présentée dans ce guide fait office de levier — aucun des serveurs MCP ci-dessous ne fonctionne sans Xcode 26.3+ de toute façon.

Requis : - macOS 15+ (Sequoia) ou macOS Tahoe - Xcode 26.3+ installé et configuré (le seuil minimal pour xcrun mcpbridge) ; Xcode 26.4+ recommandé pour les pièces jointes d’images Swift Testing, la sévérité des problèmes enregistrés, les avertissements de plantage des tests UI avec journaux de crash, et les améliorations de l’éditeur String Catalog.13 Xcode 26.4.1 (16 avril 2026, build 17E202) est la dernière version stable — corrections de bugs uniquement.14 - Au moins un runtime iOS Simulator installé - Un compte Anthropic API (pour Claude Code) ou un compte OpenAI (pour Codex)

Recommandé : - SwiftFormat installé (brew install swiftformat) — utilisé par les hooks de formatage à la sauvegarde - SwiftLint installé (brew install swiftlint) — optionnel mais utile pour faire respecter le style - Familiarité avec le terminal — les trois runtimes fonctionnent depuis la ligne de commande ou s’y intègrent

Vérifiez votre installation Xcode :

# Check Xcode version
xcodebuild -version
# Expected: Xcode 26.3 or later (26.4+ 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")

Si xcrun mcpbridge retourne « command not found », vous avez besoin de Xcode 26.3 ou ultérieur. Installez ou mettez à jour Xcode via l’App Store ou developer.apple.com. Remarque : xcode-select --install n’installe que les Command Line Tools, qui n’incluent pas mcpbridge — vous avez besoin du Xcode.app complet.


Trois runtimes d’agents pour iOS

Trois runtimes distincts peuvent écrire, compiler et tester du code iOS. Ils ne sont pas interchangeables — chacun a des forces différentes, des modèles d’intégration MCP différents et des cas d’usage idéaux différents.

1. Claude Code CLI

Ce que c’est : l’assistant de codage agentique en terminal de Anthropic. Il lit votre base de code, exécute des commandes, modifie des fichiers et se connecte à des outils externes via MCP.

Intégration MCP : prise en charge complète à la fois de XcodeBuildMCP et du MCP Xcode d’Apple. L’agent découvre les outils via le protocole MCP et les appelle avec des paramètres structurés. 59 + 20 outils répartis entre les deux serveurs.

Installation :

# 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

Alternative — installateur automatique xcodebuildmcp init (v2.1.0+, 2026-02-23) :

Si vous préférez éviter le câblage manuel de MCP, XcodeBuildMCP v2.1.0+ embarque une sous-commande init qui détecte automatiquement Claude Code, Cursor ou Codex et installe les compétences d’agent ainsi que la configuration MCP en une seule étape :

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

Options : --print (écrire la configuration sur stdout pour les clients non pris en charge), --uninstall (désinstaller). Évitez cette commande si vous voulez un contrôle explicite sur les serveurs MCP câblés et leur portée ; les invocations manuelles claude mcp add ci-dessus vous donnent ce contrôle.15

Idéal pour : les sessions d’implémentation approfondies — création de nouvelles fonctionnalités, refactorisation à travers plusieurs fichiers, débogage de problèmes complexes, exécution autonome de boucles compilation-test-correction. La fenêtre de contexte de 1M de Claude Code (avec Opus 4.6) signifie que l’agent peut conserver la plupart des projets iOS de petite à moyenne taille en mémoire de travail — d’après mon expérience, jusqu’à environ 50 fichiers selon leur taille.

Session typique :

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]

La différence clé par rapport au workflow pré-MCP : l’agent ne vous demande jamais de compiler manuellement ou de coller la sortie d’erreur. La boucle compilation-erreur-correction est autonome.

2. Codex CLI

Ce que c’est : l’agent de codage en terminal d’OpenAI. Similaire en concept à Claude Code mais utilise des modèles OpenAI (GPT-4o, o3) et possède un modèle d’autorisations différent.

Intégration MCP : Codex prend en charge MCP via la commande codex mcp add. Le MCP Xcode d’Apple fonctionne directement :

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

XcodeBuildMCP fonctionne également avec Codex via la même commande npx :

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

Idéal pour : les opérations batch sans interface, l’intégration CI/CD et les tâches pour lesquelles vous voulez un second avis d’une autre famille de modèles. Le mode sandbox de Codex exécute le code dans des environnements isolés, ce qui s’avère utile pour des opérations destructives comme l’exécution de suites de tests qui modifient l’état.

Différences clés par rapport à Claude Code : - Utilise des modèles OpenAI au lieu des modèles Claude - Tailles de fenêtre de contexte et économie de tokens différentes - Modèle d’autorisations sandbox-first (plus restrictif par défaut) - Écosystème MCP plus restreint (moins de serveurs communautaires testés) - Système de hooks disponible (v0.119.0+) mais moins mature que celui de Claude Code — moins de types d’événements et pas de champ if conditionnel

Quand utiliser Codex plutôt que Claude Code pour iOS :

Utilisez Codex lorsque vous voulez de la diversité de modèles — faire relire le code écrit par un premier agent par un second permet de détecter différentes classes d’erreurs. Le workflow collab (Claude construit, Codex relit) s’avère efficace pour iOS car les patterns SwiftUI qui semblent corrects à une famille de modèles peuvent avoir des problèmes subtils qu’une autre détecte. Les shaders Metal et les patterns de concurrence bénéficient particulièrement d’une relecture par double modèle.

3. Agents natifs Xcode 26.3

Ce que c’est : Apple a intégré directement des agents de codage IA dans le panneau Intelligence de Xcode. Depuis Xcode 26.3, vous pouvez configurer Claude Agent et Codex comme fournisseurs d’intelligence dans Xcode Settings > Intelligence.

Installation :

  1. Ouvrez Xcode 26.3+
  2. Naviguez vers Settings > Intelligence
  3. Ajoutez un nouveau fournisseur :
  4. Pour Claude : sélectionnez « Claude Agent », saisissez votre clé API Anthropic
  5. Pour Codex : sélectionnez « Codex », saisissez votre clé API OpenAI
  6. L’agent apparaît dans la barre latérale Intelligence et peut être invoqué en ligne

Idéal pour : les modifications rapides en ligne, la complétion de code avec un raisonnement de niveau agent, et les développeurs qui préfèrent ne pas quitter Xcode. L’intégration native signifie que l’agent a un accès direct au contexte du projet Xcode — fichiers ouverts, cibles de build, configuration de scheme — sans pont MCP.

Limitations par rapport aux agents CLI : - Pas de système de hooks — vous ne pouvez pas imposer le format-on-save ou bloquer les écritures .pbxproj - Pas de chargement de CLAUDE.md — l’agent ne lit pas vos fichiers de configuration au niveau projet - Autonomie limitée — l’agent opère sur le fichier courant ou la sélection, pas sur l’ensemble du projet - Pas de délégation à des sous-agents — les tâches complexes en plusieurs étapes ne peuvent pas être parallélisées - Pas de configuration de serveur MCP — l’agent utilise uniquement les outils intégrés à Xcode

Quand utiliser les agents natifs Xcode :

Pour des modifications rapides et ciblées où passer au terminal représente un coût excessif. « Ajoutez une propriété calculée à ce modèle. » « Écrivez un test unitaire pour cette fonction. » « Refactorisez cette vue pour utiliser @Observable. » Des tâches qui touchent un ou deux fichiers et ne nécessitent pas de cycle compilation-test.

Pour tout ce qui nécessite de la compilation, des tests, de la refactorisation multi-fichiers ou une correction d’erreur autonome, utilisez un agent CLI avec MCP.

Matrice comparative des runtimes

Capacité Claude Code CLI Codex CLI Xcode 26.3 natif
Prise en charge MCP Complète (79 outils) Complète (79 outils) Outils Xcode intégrés uniquement
Système de hooks Oui (mature) Oui (basique, v0.119.0+) Non
CLAUDE.md / config projet Oui Équivalent codex.md Non
Compilation-test-correction autonome Oui (via MCP) Oui (via MCP) Partielle (en ligne uniquement)
Délégation à des sous-agents Oui (jusqu’à 10 en parallèle) Non Non
Fenêtre de contexte 1M tokens (Opus 4.6) Varie selon le modèle Varie selon le fournisseur
Opérations multi-fichiers Accès complet à la base de code Accès complet à la base de code Fichier courant / sélection
Protection .pbxproj Via hooks Manuelle N/A (utilise Xcode nativement)
Format-on-save Via hooks PostToolUse Outillage externe Paramètres Xcode
Capacité hors ligne Non Non Non
Modèle de coût Usage API Anthropic Usage API OpenAI Usage API du fournisseur

La recommandation : utilisez Claude Code CLI comme runtime principal. Utilisez les agents natifs Xcode 26.3 pour les modifications rapides en ligne. Utilisez Codex CLI pour les passes de relecture et les opérations batch. Les trois se complètent au lieu de se concurrencer.

Configuration de MCP : la configuration complète

MCP (Model Context Protocol) est ce qui transforme un agent qui « écrit du Swift en espérant que vous le compiliez » en un agent qui « écrit du Swift, le compile, lit les erreurs structurées et les corrige ». Cette section va plus en profondeur que l’article de blog — couvrant les deux serveurs, toutes les méthodes d’installation, la vérification et la configuration de l’agent qui garantit que les outils sont effectivement utilisés.

XcodeBuildMCP : 59 outils pour le développement iOS sans tête

XcodeBuildMCP encapsule xcodebuild, xcrun simctl et LLDB dans 59 outils MCP structurés. Il fonctionne sans que Xcode soit lancé — l’ensemble du cycle build-test-debug s’exécute en mode headless via les outils en ligne de commande d’Apple.

Options d’installation :

# 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

L’option -s user rend le serveur disponible globalement dans tous les projets. Omettez-la pour une installation à portée de projet (utile si vous ne voulez MCP que dans les projets iOS, pas dans les projets web).

La variable d’environnement -e XCODEBUILDMCP_SENTRY_DISABLED=true désactive la télémétrie de rapport de plantage. XcodeBuildMCP inclut Sentry par défaut, qui envoie des données d’erreur incluant les chemins de fichiers. Désactivez-la sauf si vous souhaitez contribuer aux diagnostics du projet.1

Inventaire complet des outils (59 outils répartis en 8 catégories) :

Catégorie Outils Ce qu’ils font
Découverte de projet discover_projs, list_schemes, list_targets Trouve les fichiers .xcodeproj/.xcworkspace, liste les schémas et cibles disponibles
Compilation build_sim, build_device, build_mac Compile avec une sortie JSON structurée des erreurs/avertissements par fichier et ligne
Tests test_sim, test_device Exécute les tests avec des résultats de réussite/échec par méthode
Cycle de vie du simulateur list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults Crée, démarre, gère et configure les simulateurs
Gestion des appareils list_devices, install_device, launch_device Déploiement et gestion des appareils physiques
Débogage debug_attach_sim, debug_attach_device, debug_breakpoint, debug_stack, debug_variables, debug_eval, debug_continue, debug_step, debug_detach Intégration LLDB complète avec points d’arrêt et inspection des variables
Automatisation de l’interface snapshot_ui, screenshot, tap, swipe, type_text Interaction automatisée et capture visuelle
Échafaudage de projet create_project, add_file, add_package Crée des projets et ajoute des dépendances

Les outils les plus importants pour le travail quotidien :

  1. build_sim — Vous l’appellerez des centaines de fois. Il retourne du JSON avec les erreurs catégorisées par fichier, ligne et sévérité. L’agent lit l’erreur, navigue jusqu’au fichier et la corrige sans que vous ayez à intervenir.

  2. test_sim — Retourne les résultats par méthode de test. L’agent sait exactement quel test a échoué et pourquoi, pas seulement « les tests ont échoué ».

  3. list_sims + boot_sim — Gestion des simulateurs sans avoir à mémoriser les options de xcrun simctl. L’agent découvre les runtimes disponibles et choisit un appareil approprié.

  4. discover_projs + list_schemes — Introspection de projet. L’agent n’a pas besoin de deviner le nom de votre schéma ou la structure de votre workspace.

  5. debug_attach_sim + debug_stack + debug_variables — Débogage LLDB à distance. L’agent peut poser des points d’arrêt, inspecter les variables et exécuter le code pas à pas sans que vous ayez à ouvrir le débogueur.

Apple Xcode MCP : 20 outils faisant le pont avec Xcode

Le serveur MCP d’Apple est livré avec Xcode 26.3 via xcrun mcpbridge. Il communique avec un processus Xcode en cours d’exécution via XPC (le framework de communication inter-processus d’Apple), exposant un état interne qu’aucun outil CLI ne peut atteindre.

Installation :

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

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

Nécessite Xcode 26.3+ et un processus Xcode en cours d’exécution. Si Xcode n’est pas ouvert, chaque appel MCP via ce serveur échouera ou se bloquera. XcodeBuildMCP n’a pas cette limitation.

Inventaire des outils (20 outils répartis en 5 catégories) :

Catégorie Outils Ce qu’ils font
Opérations sur les fichiers XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep Lit/écrit des fichiers dans le contexte du projet Xcode
Build et test BuildProject, GetBuildLog, RunAllTests, RunSomeTests Compile et teste avec le système de build interne de Xcode
Diagnostics XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile Diagnostics de code en temps réel (pas seulement les erreurs de compilation)
Code et documentation ExecuteSnippet, DocumentationSearch Exécution Swift REPL et recherche dans la documentation Apple
Aperçus RenderPreview Rendu headless des aperçus SwiftUI

Outils uniques à Apple MCP (non disponibles dans XcodeBuildMCP) :

  1. DocumentationSearch — Effectue des recherches dans la documentation développeur d’Apple, y compris les sessions WWDC. Plus rapide et plus fiable qu’une recherche web pour les questions sur les API Apple. Demandez « est-ce que HKQuantityType(.dietaryWater) est valide ? » et obtenez une réponse définitive depuis la source.

  2. ExecuteSnippet — Exécution Swift REPL dans le contexte du projet. L’agent peut vérifier le comportement des API, tester des conversions de types et valider des expressions sans compiler l’application complète.

  3. RenderPreview — Effectue un rendu headless des aperçus SwiftUI. L’agent peut vérifier si une vue se rend sans erreurs, bien qu’il ne puisse pas évaluer la correction visuelle (le rendu est retourné sous forme de données, pas inspecté visuellement).

  4. XcodeListNavigatorIssues — Retourne les diagnostics en temps réel de l’analyseur Xcode, pas seulement les erreurs de compilation. Détecte les problèmes comme les variables non utilisées, les cycles de rétention potentiels et les avertissements de dépréciation que le système de build ne fait pas remonter.

Pourquoi les deux serveurs

Ils se chevauchent pour les builds et les tests mais diffèrent fondamentalement :

┌─────────────────────────────────────────────────────────────────┐
                     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                                             
  └─────────────────────┘         └─────────────────────┘       
                                                                 
└─────────────────────────────────────────────────────────────────┘

Utilisez XcodeBuildMCP pour : Le cycle build-test-debug. Il fonctionne sans que Xcode soit ouvert, consomme moins de mémoire système et offre une gestion plus riche des simulateurs et appareils. C’est votre outil de build principal.

Utilisez Apple Xcode MCP pour : Les recherches dans la documentation, la vérification Swift REPL, le rendu d’aperçus SwiftUI et les diagnostics en temps réel. Gardez Xcode ouvert pendant les sessions qui nécessitent ces capacités.

En pratique : J’utilise XcodeBuildMCP pour environ 90 % des appels MCP et Apple Xcode MCP pour la documentation et la vérification REPL. L’agent utilise XcodeBuildMCP par défaut pour les builds et les tests parce qu’il est plus rapide (pas de surcharge de processus Xcode) et plus fiable (pas de dépendance XPC).

Vérification

Après avoir installé les deux serveurs, vérifiez qu’ils sont connectés :

# List all configured MCP servers
claude mcp list

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

Si un serveur affiche « Disconnected » ou n’apparaît pas :

  1. XcodeBuildMCP ne se connecte pas : Assurez-vous que Node.js est installé (node --version). La commande npx nécessite Node.js 18+.
  2. Apple Xcode MCP ne se connecte pas : Assurez-vous que Xcode 26.3+ est installé et que la commande xcrun mcpbridge fonctionne dans votre terminal. Ouvrez Xcode au moins une fois pour accepter le contrat de licence.
  3. Aucun des deux n’apparaît : Redémarrez Claude Code (claude dans un nouveau terminal). Les serveurs MCP enregistrés en milieu de session peuvent ne pas apparaître avant un redémarrage.

Apprendre à l’agent à utiliser MCP

Installer les serveurs MCP est nécessaire mais insuffisant. Sans directives explicites, l’agent peut se rabattre sur l’exécution de xcodebuild via Bash (sortie non structurée, gaspillage de tokens de contexte) ou utiliser une recherche web pour la documentation Apple (plus lent, moins fiable).

Ajoutez ceci à votre CLAUDE.md ou à la définition de votre agent :

## Build & Test — Toujours utiliser MCP

Privilégiez les outils MCP aux commandes shell brutes pour TOUTES les opérations de build :

- **Build** : `build_sim` / `build_device` (PAS `xcodebuild` via Bash)
- **Test** : `test_sim` / `test_device` (PAS `xcodebuild test` via Bash)
- **Simulateurs** : `list_sims`, `boot_sim`, `open_sim` (PAS `xcrun simctl` via Bash)
- **Debug** : `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Documentation Apple** : `DocumentationSearch` (PAS WebSearch pour les APIs Apple)
- **Vérification Swift** : `ExecuteSnippet` (PAS `swift` via Bash)
- **Aperçus** : `RenderPreview` pour la vérification SwiftUI sans interface

MCP retourne des JSON structurées. Bash retourne du texte non structuré.
Les données structurées consomment moins de tokens et permettent un meilleur diagnostic des erreurs.

Cette directive garantit que l’agent privilégie d’emblée les outils MCP. Sans elle, vous observerez l’agent construire de longues commandes xcodebuild via Bash, consommer des milliers de tokens de contexte pour analyser la sortie, et parfois identifier à tort l’erreur réelle.


Patterns CLAUDE.md pour les projets iOS

Votre CLAUDE.md est le fichier le plus important du projet pour le développement assisté par agent. C’est le document d’intégration de l’agent — la différence entre une nouvelle recrue qui a lu la documentation d’architecture et une qui devine.

Chaque projet iOS que je maintiens possède un CLAUDE.md. Voici les patterns qui fonctionnent, tirés des 8 applications.

Les sections essentielles

Chaque CLAUDE.md iOS a besoin de ces six sections. Tout le reste est optionnel.

1. Identité du projet

# Return - Zen Focus Timer

**Bundle ID :** `com.941apps.Return`
**Target :** iOS 26+ / macOS Tahoe / watchOS 26+ / tvOS 26+
**Architecture :** SwiftUI avec pattern @Observable, applications Watch et TV compagnons
**Version Swift :** 6.2
**Déploiement minimum :** iOS 26.0

Pourquoi cela compte : l’agent doit connaître la cible de déploiement avant d’écrire le moindre code. Un agent ciblant iOS 17 utilisera NavigationView et @ObservedObject. Un agent ciblant iOS 26 utilisera NavigationStack et @Observable. Le bundle ID importe pour les entitlements et la configuration HealthKit. La version Swift détermine le modèle de concurrence (async/await vs gestionnaires de complétion, concurrence stricte vs permissive).

2. Structure des fichiers avec annotations de finalité

## Structure des fichiers

```
Return/
├── ReturnApp.swift              # Point d'entrée de l'app, application du mode sombre
├── ContentView.swift            # Vue principale du timer avec arrière-plans à thème
├── TimerManager.swift           # État, logique et gestion des répétitions du timer
├── AudioManager.swift           # Lecture sonore avec AVAudioPlayer
├── Settings.swift               # Paramètres centralisés avec validation
├── SettingsSheet.swift          # Interface des paramètres
├── HealthKitManager.swift       # Journalisation des sessions de pleine conscience + sync inter-appareils
├── LiveActivityManager.swift    # Lock Screen/Dynamic Island
├── Theme.swift                  # Définitions des thèmes
├── ThemeManager.swift           # Gestion d'état des thèmes
├── VideoBackgroundView.swift    # Arrière-plans vidéo AVPlayer
├── GlassTextShape.swift         # Tracés de glyphes Core Text pour effet de verre
├── GlassTimerText.swift         # Texte du timer avec matériau de verre
└── Constants.swift              # Constantes de l'app
```

Les commentaires en ligne après chaque nom de fichier ne sont pas décoratifs. Ils constituent la documentation au plus fort effet de levier que vous puissiez écrire. Lorsque l’agent décide où ajouter une nouvelle fonctionnalité, ces annotations le guident vers le bon fichier dès la première tentative au lieu de lire chaque fichier pour comprendre la structure du projet.

Anti-pattern : lister les fichiers sans annotations. TimerManager.swift ne dit rien à l’agent sur le fait qu’il gère l’état, l’interface ou les deux. TimerManager.swift # État, logique et gestion des répétitions du timer lui dit exactement ce qui y appartient et ce qui n’y appartient pas.

3. Commandes de build et de test

## Build & Test

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

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

Exécuter les tests tvOS :
```bash
xcodebuild -scheme ReturnTV -destination 'platform=tvOS Simulator,name=Apple TV' test
```

**Privilégiez les outils MCP** (`build_sim`, `test_sim`) à ces commandes brutes.
MCP retourne des JSON structurées avec des erreurs catégorisées.

Incluez les commandes brutes même si l’agent doit privilégier MCP. Les commandes brutes servent de documentation de repli et rendent explicites les noms de scheme et les destinations.

4. Patterns et règles clés

## Patterns clés

### Architecture Observable
- TOUS les view models utilisent `@Observable` (JAMAIS `ObservableObject`)
- TOUTE la navigation utilise `NavigationStack` (JAMAIS `NavigationView`)
- Gestion d'état via des classes `@Observable` avec isolation `@MainActor`

### Pattern Settings
- Singleton centralisé `Settings.shared`
- Tous les paramètres sont bornés à des plages valides avec validation
- Noms de sons validés contre une liste blanche
- Accès thread-safe via @MainActor

### Système audio
- `AVAudioPlayer` avec catégorie `.playback` (lecture en mode silencieux)
- Boucle audio silencieuse pour exécution en arrière-plan
- Lecture de cloche avec callbacks de complétion et obsolescence basée sur token

Ces patterns empêchent l’agent d’introduire des incohérences. Sans documentation explicite des patterns, l’agent utilisera parfois ObservableObject dans un fichier et @Observable dans un autre, ou créera un nouveau mécanisme de paramètres au lieu d’utiliser le singleton Settings.shared existant.

5. Ce que l’agent ne doit jamais faire

## Règles

- **NE JAMAIS modifier les fichiers .pbxproj** — créez les fichiers Swift, puis je les ajouterai manuellement à Xcode
- **NE JAMAIS modifier directement le contenu de .xcodeproj/**
- **NE JAMAIS ajouter de nouvelles dépendances de package** sans demander d'abord
- **NE JAMAIS changer la cible de déploiement**
- **NE JAMAIS modifier les fichiers d'entitlements** sauf demande explicite
- **NE JAMAIS utiliser NavigationView** — toujours NavigationStack
- **NE JAMAIS utiliser ObservableObject** — toujours @Observable
- **NE JAMAIS utiliser @StateObject** — toujours @State avec @Observable

Les interdictions explicites sont plus efficaces que les attentes implicites. L’agent suit les contraintes négatives de manière plus fiable que les suggestions positives parce qu’elles sont binaires (le faire / ne pas le faire) plutôt qu’heuristiques (privilégier ceci / parfois utiliser cela).

6. Contexte spécifique au framework

Cette section varie selon l’application. Incluez-la pour tout framework dont la configuration n’est pas évidente :

Pour les apps HealthKit :

## Configuration HealthKit

- Entitlement : `com.apple.developer.healthkit`
- Clés Info.plist :
  - `NSHealthShareUsageDescription` : « Return lit vos minutes de pleine conscience... »
  - `NSHealthUpdateUsageDescription` : « Return enregistre vos sessions de méditation... »
- Types de catégorie : `HKCategoryType(.mindfulSession)`
- Autorisation vérifiée à chaque écriture (l'utilisateur peut révoquer à tout moment)
- HealthKit est indisponible sur tvOS — protégez avec `#if canImport(HealthKit)`

Pour les apps SwiftData :

## Modèles SwiftData

### Relations entre modèles
- `GroceryList` a plusieurs `GroceryItem` (suppression en cascade)
- `GroceryItem` appartient à un seul `GroceryList`
- `GroceryItem` a un `Category` optionnel

### Configuration du Model Container
- Configuré dans la struct App avec `modelContainer(for:)`
- Versioning du schéma : actuellement V2
- Plan de migration : `GroceryMigrationPlan` gère V1 → V2

### Requêtes
- `@Query(sort: \GroceryItem.name)` pour les fetches triés
- `@Query(filter: #Predicate { !$0.isCompleted })` pour les éléments actifs
- Toujours utiliser `@Query` dans les vues, `modelContext.fetch()` dans les managers

Pour les apps SpriteKit :

## Hiérarchie de scène SpriteKit

```
GameScene (SKScene)
├── backgroundLayer (SKNode, zPosition: -100)
│   └── StarfieldNode (custom, défilement parallaxe)
├── gameLayer (SKNode, zPosition: 0)
│   ├── playerShip (PlayerNode, zPosition: 10)
│   ├── enemyContainer (SKNode, zPosition: 5)
│   └── bulletPool (SKNode, zPosition: 8)
├── effectsLayer (SKNode, zPosition: 50)
│   └── ParticleManager (gère les émetteurs d'explosion/traînée)
└── hudLayer (SKNode, zPosition: 100)
    ├── scoreLabel (SKLabelNode)
    └── healthBar (HealthBarNode)
```

- Catégories de physique définies dans `PhysicsCategory.swift` sous forme de bitmasks
- Détection de contact via `didBegin(_ contact:)` sur GameScene
- Pooling de projectiles : pré-allouer 50, recycler via `removeFromParent()` + ré-ajout

Pour les apps Metal :

## Pipeline Metal

- Pipeline de rendu : `MetalView``Renderer``ShaderLibrary`
- Pipeline de calcul : `AudioAnalyzer` → compute shader → sortie texture
- Struct d'uniformes partagée : `Uniforms` dans `ShaderTypes.h` (bridgé vers Swift)
- Timing des frames : `CADisplayLink` pilote la boucle de rendu
- Triple buffering : 3 frames en vol avec sémaphore

### Fichiers shader
- `Shaders.metal` — Shaders de rendu principaux (vertex + fragment)
- `Compute.metal` — Kernel compute pour l'analyse audio
- `PostProcess.metal` — Bloom et étalonnage couleur

### NE PAS modifier les shaders Metal sans tester sur appareil.
Le Metal du simulateur n'est pas représentatif du comportement GPU sur l'appareil.

Vrai CLAUDE.md : Banana List (SwiftUI + SwiftData + iCloud + serveur MCP)

Voici un exemple annoté montrant comment les six sections fonctionnent ensemble pour une application de complexité modérée. C’est le pattern CLAUDE.md que j’utilise pour Banana List, une application de liste de courses de 53 fichiers avec sync iCloud et un serveur MCP personnalisé qui expose les données de l’app à Claude Desktop :

# Banana List - Application de liste de courses

**Bundle ID :** `com.941apps.BananaList`
**Target :** iOS 26+
**Architecture :** SwiftUI + SwiftData + sync iCloud Drive
**Version Swift :** 6.2
**Déploiement minimum :** iOS 26.0

## Fonctionnalités principales

- Listes de courses avec articles, catégories et quantités
- Sync iCloud Drive via l'intégration SwiftData CloudKit
- Serveur MCP personnalisé exposant les données de liste à Claude Desktop
- Système de design Liquid Glass
- Retour haptique sur les interactions
- Feuilles de partage pour le partage de listes

## Structure des fichiers

```
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
```

## Modèles SwiftData

### Relations
- `GroceryList` possède plusieurs `GroceryItem` (suppression en cascade)
- `GroceryItem` appartient à un seul `GroceryList` (obligatoire)
- `GroceryItem` possède une `Category` optionnelle
- `Category` possède plusieurs `GroceryItem` (mise à nil lors de la suppression)

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

### Modèles de requête
- Listes : `@Query(sort: \GroceryList.name) var lists: [GroceryList]`
- Éléments actifs : `@Query(filter: #Predicate { !$0.isCompleted })`
- Par catégorie : filtrage en mémoire après extraction (limites des prédicats SwiftData)

## 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
```

Privilégiez les outils MCP (`build_sim`, `test_sim`) plutôt que les commandes brutes.

## Modèles clés

### Observable + SwiftData
- Les classes SwiftData `@Model` sont automatiquement Observable
- N'ajoutez PAS `@Observable` aux classes `@Model` (redondant, génère des avertissements)
- Utilisez `@Bindable` pour les liaisons bidirectionnelles aux propriétés du modèle dans les formulaires
- Utilisez `@Query` dans les vues, `modelContext.fetch()` dans le code hors vue

### Synchronisation iCloud
- Automatique via l'intégration SwiftData CloudKit
- Résolution de conflits : la dernière écriture l'emporte (comportement par défaut de CloudKit)
- État de synchronisation exposé via `CloudSyncManager.shared.syncState`
- Testez la synchronisation en exécutant l'app sur deux simulateurs avec le même compte iCloud

### Architecture du serveur MCP
- S'exécute comme un serveur WebSocket local sur le port 8765
- Expose 6 outils : listAll, getList, createList, addItem, completeItem, deleteItem
- Claude Desktop se connecte via la configuration MCP dans `~/.config/claude-desktop/config.json`

## Règles

- Ne modifiez JAMAIS le contenu de .pbxproj ou .xcodeproj
- Ne changez JAMAIS le schéma du modèle sans mettre à jour SampleData.swift
- N'utilisez JAMAIS `ObservableObject` — les modèles SwiftData sont déjà Observable
- N'utilisez JAMAIS `@StateObject` — utilisez `@State` avec des classes `@Observable`
- N'utilisez JAMAIS `NavigationView` — toujours `NavigationStack`
- N'ajoutez JAMAIS la macro `@Observable` aux classes `@Model`
- Utilisez TOUJOURS `@Bindable` pour les liaisons de formulaire aux propriétés du modèle
- Testez TOUJOURS les modifications de synchronisation iCloud sur deux instances de simulateur

CLAUDE.md réel : Reps (app SwiftData minimale — 14 fichiers)

Pour les petits projets, le CLAUDE.md peut être concis. Voici le modèle pour Reps, un tracker d’entraînement de 14 fichiers. Remarquez comment, même un CLAUDE.md court couvre les six sections essentielles :

# 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

Cela représente 40 lignes de CLAUDE.md pour un projet de 14 fichiers. Sa rédaction prend 10 minutes et fait gagner des heures de confusion à l’agent.

CLAUDE.md réel : Starfield Destroyer (SpriteKit + Metal — 32 fichiers)

Les projets de jeu nécessitent davantage de contexte spécifique au framework. L’agent doit comprendre le graphe de scène, les catégories physiques et la machine à états du jeu :

# 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

## Règles

- NE JAMAIS modifier .pbxproj
- NE JAMAIS modifier les bitmasks PhysicsCategory (cela casse toute la détection de collision)
- NE JAMAIS modifier l'ordre z de la hiérarchie de scène sans comprendre l'ordre de rendu
- NE JAMAIS modifier ShaderTypes.h sans mettre à jour les références Swift et Metal
- Ajoutez de nouveaux ennemis en sous-classant EnemyShip, pas en le modifiant
- Pooling de bullets : recyclez via removeFromParent() + ré-ajout, n'allouez jamais de nouveaux
- Game Center : vérifiez toujours isAuthenticated avant de soumettre des scores

CLAUDE.md réel : amp97 (Metal + visualisation audio — 41 fichiers)

Les projets Metal nécessitent le contexte spécifique au framework le plus important, car les agents ne peuvent pas vérifier la sortie visuelle :

# amp97 - Visualiseur audio

**Bundle ID :** `com.941apps.amp97`
**Cible :** iOS 26+
**Architecture :** pipeline de rendu Metal + analyse AVAudioEngine
**Version Swift :** 6.2

## Architecture

```
Entrée audio (microphone/fichier)
    → tap AVAudioEngine
    → FFT (vDSP)
    → tampons de fréquence/amplitude
    → shader compute Metal (analyse)
    → pipeline de rendu Metal (visualisation)
    → CADisplayLink (60 ips)
    → MTKView
```

## Structure des fichiers

```
amp97/
├── amp97App.swift               # Point d'entrée de l'app
├── Audio/
│   ├── AudioEngine.swift        # Configuration AVAudioEngine, installation du tap
│   ├── FFTProcessor.swift       # FFT vDSP, extraction des bins de fréquence
│   ├── AudioBuffer.swift        # Buffer circulaire pour les données audio
│   └── MicrophoneManager.swift  # Permission microphone, configuration de session
├── Rendering/
│   ├── MetalView.swift          # Wrapper MTKView pour SwiftUI
│   ├── Renderer.swift           # Boucle de rendu principale, état du pipeline
│   ├── ShaderLibrary.swift      # Gestion des shaders compilés
│   ├── BufferManager.swift      # Mises à jour d'uniformes en triple buffering
│   └── TextureManager.swift     # Cibles de rendu hors écran
├── Shaders/
│   ├── Shaders.metal            # Shaders vertex + fragment
│   ├── AudioCompute.metal       # Kernel compute d'analyse audio
│   ├── PostProcess.metal        # Bloom, étalonnage des couleurs
│   └── ShaderTypes.h            # Uniformes partagés (bridging header)
├── Visualizations/
│   ├── WaveformViz.swift        # Forme d'onde de type oscilloscope
│   ├── SpectrumViz.swift        # Barres de spectre de fréquence
│   ├── CircularViz.swift        # Visualisation radiale
│   └── VizSelector.swift        # Changement de visualisation
├── Views/
│   ├── MainView.swift           # Visualisation plein écran avec overlays
│   ├── ControlsOverlay.swift    # Lecture/pause, sélection de viz, gain
│   └── SettingsView.swift       # Source audio, sensibilité
└── Extensions/
    ├── SIMD+Extensions.swift    # Helpers de math vectoriel
    └── Color+Metal.swift        # Conversion UIColor → float4
```

## Pipeline Metal

### Uniformes (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;
```

### Pipeline de rendu
1. Passe compute : AudioCompute.metal traite les données FFT → texture
2. Passe de rendu : Shaders.metal lit la texture + les uniformes → visualisation
3. Passe de post-traitement : PostProcess.metal applique le bloom → sortie finale

### Gestion des buffers
- Triple buffering avec DispatchSemaphore(value: 3)
- Uniformes mis à jour à chaque frame sur le CPU, consommés par GPU 1-2 frames plus tard
- Buffer circulaire de données audio : 4096 échantillons, sans verrou, producteur/consommateur unique

## Règles

- NE JAMAIS modifier ShaderTypes.h sans mettre à jour LES DEUX côtés Swift et Metal
- NE JAMAIS dépasser 64 bins de fréquence (taille de buffer fixe dans le shader)
- NE JAMAIS tester la sortie visuelle Metal dans le simulateur — uniquement sur appareil
- NE JAMAIS modifier le format du tap du moteur audio (48 kHz, mono, float32)
- Discipline de triple buffering : signalez toujours le sémaphore dans le completion handler
- Session audio : catégorie .playAndRecord avec l'option .defaultToSpeaker

Adapter CLAUDE.md à la taille du projet

Le bon niveau de détail dépend du nombre de fichiers et de la complexité du framework :

Taille du projet Profondeur de CLAUDE.md Exemple
Petit (< 20 fichiers) Identité + liste de fichiers + règles Reps (14 fichiers) : patrons SwiftData de base, commandes de build, interdictions
Moyen (20-40 fichiers) + Contexte du framework + patrons clés TappyColor (30 fichiers) : hiérarchie de scène SpriteKit, catégories physiques, boucle de jeu
Grand (40+ fichiers) + Diagrammes d’architecture + cartes de relations + infos multi-cibles Return (63 fichiers) : architecture multiplateforme, diagramme de synchronisation de session, différences par plateforme
Spécialisé (Metal/GPU) + Diagrammes de pipeline + définitions de types partagés + dispositions de buffers amp97 (41 fichiers) : étapes du pipeline de rendu, struct d’uniformes, gestion des buffers

Le coût d’une sur-documentation est quasi nul (l’agent ignore ce dont il n’a pas besoin). Le coût d’une sous-documentation est élevé (l’agent invente des patrons qui entrent en conflit avec votre codebase).

Checklist CLAUDE.md

Utilisez cette checklist lors de la création ou de l’audit d’un CLAUDE.md pour un projet iOS :

  • [ ] Bundle ID et cible de déploiement spécifiés
  • [ ] Version Swift et patron d’architecture nommés
  • [ ] Structure de fichiers avec annotations de finalité en ligne
  • [ ] Commande de build avec scheme et destination corrects
  • [ ] Commande de test avec scheme et destination corrects
  • [ ] Préférence MCP notée (« préférer build_sim plutôt que xcodebuild »)
  • [ ] Règle @Observable (jamais ObservableObject)
  • [ ] Règle NavigationStack (jamais NavigationView)
  • [ ] Interdiction du .pbxproj
  • [ ] Contexte spécifique au framework (permissions HealthKit, relations SwiftData, hiérarchie SpriteKit, pipeline Metal)
  • [ ] Garde-fous de disponibilité de plateforme documentés (#if canImport, #if os)
  • [ ] Singletons clés et patrons partagés documentés
  • [ ] Limitations connues ou pièges signalés

Votre première session avec un agent

Avec MCP configuré et un CLAUDE.md dans votre projet, voici une présentation pas à pas d’une première session efficace. Celle-ci utilise Claude Code CLI mais le workflow s’applique à n’importe quel runtime.

Étape 1 : vérifier que l’agent peut voir votre projet

Vous : Résume ce projet. Avec quel scheme dois-je construire ?

Claude : [lit CLAUDE.md]
        [appelle discover_projs via MCP]
        [appelle list_schemes via MCP]

        C'est Return, un timer de méditation zen pour iOS 26+, watchOS et tvOS.
        Schemes disponibles : Return, ReturnWatch, ReturnTV, ReturnTests.
        Scheme principal pour iOS : Return.

Si l’agent ne fait pas référence au contenu de votre CLAUDE.md, vérifiez que le fichier se trouve à la racine du projet (même dossier que .xcodeproj ou Package.swift).

Étape 2 : lancer un build de vérification

Vous : Construis le scheme Return pour le simulateur iOS et rapporte les résultats.

Claude : [appelle list_sims  trouve iPhone 16 Pro sur iOS 26.2]
        [appelle boot_sim  démarre le simulateur]
        [appelle build_sim  construit le projet]

        Build réussi. 63 fichiers source compilés.
        2 avertissements :
        - HomeView.swift:132  UIScreen.main déprécié dans iOS 26.0
        - LogWaterIntent.swift:61  Le résultat de try? n'est pas utilisé
        0 erreur.

Étape 3 : exécuter les tests

Vous : Exécute tous les tests et rapporte les succès/échecs.

Claude : [appelle test_sim]

        12 tests exécutés :
         TimerManagerTests (5/5 réussis)
         SettingsTests (4/4 réussis)
         ConstantsTests (3/3 réussis)
        Tous les tests réussis.

Étape 4 : implémenter une fonctionnalité

Vous : Ajoute un nouveau thème « Rain » au système de thèmes. Suis le patron
     existant dans Theme.swift et ThemeManager.swift. Inclus un son
     ambiant de pluie. Construis et teste après l'implémentation.

Claude : [lit Theme.swift — comprend le patron de la struct Theme]
        [lit ThemeManager.swift — comprend l'enregistrement des thèmes]
        [lit les définitions de thèmes existantes]
        [ajoute le thème Rain à Theme.swift en suivant le patron existant]
        [enregistre le thème Rain dans ThemeManager.swift]
        [appelle build_sim  build réussi]
        [appelle test_sim  tous les tests réussis]

        Thème Rain ajouté :
        - Theme.swift : nouveau `static let rain` avec vidéo, cover, ambiant
        - ThemeManager.swift : ajouté au tableau `allThemes`
        - Build : succès (0 erreur, 2 avertissements existants)
        - Tests : 12/12 réussis

        Note : vous devrez ajouter rain_ambient.wav au projet
        et ajouter manuellement les modifications de Theme.swift à la cible Xcode
        (je n'ai pas modifié .pbxproj).

La note de l’agent concernant la non-modification de .pbxproj est le résultat des règles dans CLAUDE.md. Sans cette règle, l’agent aurait tenté de modifier le fichier projet et l’aurait probablement corrompu.


Ce que les agents font bien sur iOS

Voici les tâches pour lesquelles les agents produisent systématiquement des résultats corrects, prêts pour la production, avec un minimum de révision humaine.

Vues et modificateurs SwiftUI

Les agents possèdent une reconnaissance approfondie des motifs de la syntaxe déclarative SwiftUI. Composition de vues, chaînes de modificateurs, liaisons d’état et mise en page — tout cela correspond bien aux données d’entraînement de l’agent, car la surface API de SwiftUI est bien documentée et ses motifs sont très cohérents.

Là où les agents excellent : - Construire de nouvelles vues à partir d’une description (« créer une feuille de paramètres avec des bascules pour X, Y, Z ») - Appliquer des chaînes de modificateurs (.glassEffect(), .sensoryFeedback(), .navigationTitle()) - Convertir entre motifs de mise en page (VStack vers LazyVGrid, List vers ScrollView) - Implémenter des liaisons de formulaires @Bindable vers des modèles SwiftData - Construire des fournisseurs de prévisualisation avec des données d’exemple

Exemple de prompt qui produit d’excellents résultats :

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.

La précision compte. « Créer une vue de paramètres » produit un résultat générique. « Créer une SettingsView qui correspond au motif existant dans SettingsSheet.swift » produit un résultat cohérent avec votre base de code.

Modèles et requêtes SwiftData

Les agents gèrent de manière fiable la macro @Model de SwiftData, les relations et les motifs @Query. La nature déclarative du framework (similaire à Django ORM ou SQLAlchemy) correspond bien aux motifs que l’agent a rencontrés dans de nombreuses bases de code.

Là où les agents excellent : - Définir des classes @Model avec des relations - Écrire des @Query avec des descripteurs de tri et des prédicats - Implémenter des opérations CRUD via modelContext - Plans de migration entre versions de schéma - Données de prévisualisation et fixtures de test

Là où les agents ont besoin d’orientation : - Expressions #Predicate complexes (le DSL de prédicats de SwiftData a des limitations que l’agent ne connaît pas toujours — documentez les limitations connues dans CLAUDE.md) - Configuration de la synchronisation CloudKit (automatique via SwiftData, mais l’agent peut tenter d’implémenter une synchronisation manuelle)

Tests unitaires

Les tests unitaires écrits par l’agent sont systématiquement de haute qualité pour les projets iOS. L’agent comprend les motifs XCTest, les méthodes de test async et le cycle de vie 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)

L’agent produit des cas XCTest bien structurés avec setUp() et tearDown(), des assertions appropriées et une gestion asynchrone pour les tests basés sur des minuteurs.

Refactorisation et application de motifs

Les agents excellent dans la refactorisation mécanique : extraire des vues en composants, convertir ObservableObject en @Observable, migrer de NavigationView vers NavigationStack, et appliquer des motifs cohérents à travers plusieurs fichiers.

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.

L’agent traite méthodiquement chaque fichier, applique correctement la transformation et maintient la fonctionnalité existante. C’est un travail à fort effet de levier — une refactorisation qui prendrait une heure d’édition manuelle se termine en quelques minutes avec une précision quasi parfaite.

Diagnostic d’erreurs de build via MCP

Avec une sortie MCP structurée, les agents diagnostiquent les erreurs de build plus rapidement que la plupart des développeurs. L’agent lit le JSON d’erreur, identifie le fichier et la ligne exacts, comprend le message d’erreur et applique le correctif — souvent en un seul tour.

Erreurs que les agents corrigent de manière autonome : - Imports manquants - Incompatibilités de types - Lacunes de conformité aux protocoles - Utilisation d’API obsolètes (avec remplacement) - Paramètres d’initialiseur requis manquants - Violations de contrôle d’accès

Erreurs pour lesquelles les agents ont besoin d’aide : - Résolution de types ambiguë (plusieurs modules définissent le même type) - Échecs complexes de contraintes génériques - Erreurs d’expansion de macro (l’agent ne peut pas voir la sortie de macro développée)

Gestion du simulateur

Les agents gèrent bien le cycle de vie du simulateur via MCP :

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

L’agent appelle list_sims pour trouver les runtimes disponibles, boot_sim pour démarrer le simulateur, build_sim pour compiler et installer, et screenshot pour capturer — le tout via des appels MCP structurés.

Ce que les agents font mal sur iOS

Bilan honnête des domaines où les agents échouent. Connaître ces limites évite la frustration et le gaspillage de tokens.

Modifications du fichier .pbxproj — JAMAIS

C’est la règle la plus importante du développement iOS assisté par agent. Le fichier .pbxproj est la configuration de projet de Xcode — un fichier texte structuré contenant des références UUID, des listes de phases de build et l’appartenance aux cibles. Il est nominalement lisible par un humain, mais en pratique impossible à analyser pour les agents IA.

Pourquoi les agents échouent sur .pbxproj : - Le fichier utilise un format personnalisé (ni JSON, ni YAML, ni XML) avec une signification positionnelle - Chaque entrée est référencée par UUID — ajouter un fichier exige de mettre à jour 3 à 5 sections différentes de manière cohérente - Un seul caractère mal placé corrompt l’intégralité du fichier de projet - La résolution des conflits de fusion de Xcode pour .pbxproj est déjà fragile — les modifications d’un agent l’aggravent

Ce qui se passe quand un agent modifie .pbxproj : 1. La modification semble réussir (l’agent rapporte « fichier mis à jour ») 2. Xcode refuse d’ouvrir le projet (« Le fichier de projet est corrompu ») 3. Vous passez 15 à 60 minutes à récupérer depuis l’historique git 4. Vous apprenez à ajouter le hook PreToolUse (voir Hooks)

Le workflow : L’agent crée les fichiers Swift. Vous les ajoutez au projet Xcode manuellement (glisser-déposer dans Xcode, ou File > Add Files). Cela prend 5 secondes par fichier et évite des heures de récupération.

Pour les projets Swift Package Manager : Cette limitation est moins sévère. Package.swift est un fichier Swift standard que les agents peuvent modifier de façon fiable. Si votre projet utilise SPM exclusivement (sans .xcodeproj), l’agent peut gérer toute la structure du projet.

Modifications complexes Interface Builder / Storyboard

Si votre projet utilise Interface Builder (fichiers .xib) ou des Storyboards (fichiers .storyboard), les agents ne peuvent pas les modifier de manière utile. Ce sont des fichiers XML avec des UUID auto-générés, des références de contraintes et des connexions d’outlets conçus pour l’édition visuelle, pas pour l’édition textuelle.

La parade : Utilisez SwiftUI exclusivement pour les nouvelles vues. Si votre projet contient des fichiers Interface Builder hérités, laissez-les tranquilles et construisez la nouvelle UI en SwiftUI.

Optimisation des performances

Les agents écrivent du code correct, mais pas nécessairement performant. Ils ne peuvent pas profiler votre application, identifier les goulots d’étranglement ni mesurer les fréquences d’images. L’optimisation des performances exige :

  1. Le profilage avec Instruments (outil visuel, inaccessible aux agents)
  2. La compréhension des caractéristiques GPU/CPU spécifiques de l’appareil
  3. Des modifications itératives guidées par la mesure

Où cela se manifeste : - Optimisation des shaders Metal (l’agent écrit du Metal valide mais ne peut pas mesurer le temps d’image GPU) - Complexité du body des vues SwiftUI (l’agent crée des vues profondément imbriquées qui provoquent une surcharge de redessin) - Optimisation des fetchs Core Data / SwiftData (l’agent écrit des requêtes correctes qui peuvent être lentes sur de gros jeux de données)

La parade : Utilisez les agents pour l’implémentation, profilez manuellement avec Instruments, puis demandez à l’agent d’appliquer les optimisations spécifiques que vous avez identifiées.

Code Signing et Provisioning

Les agents ne peuvent pas déboguer les problèmes de signature de code au-delà de la lecture du message d’erreur. La gestion des profils de provisioning, la création de certificats, la configuration des entitlements et la soumission à l’App Store sont fondamentalement des workflows opérés par un humain qui impliquent l’Apple Developer portal, Keychain Access et l’interface de signature de Xcode.

Ce que voit l’agent : « Signing for ‘Return’ requires a development team. »

Ce que l’agent ne peut pas voir : Si votre certificat a expiré, si le profil de provisioning inclut l’appareil, si le bundle ID correspond à l’App ID, ou si votre fichier d’entitlements est correct.

La parade : Gérez toute la signature dans l’onglet Signing & Capabilities de Xcode. Ne demandez pas aux agents de déboguer les échecs de signature.

Débogage complexe de shaders Metal

Les agents écrivent du Metal Shading Language (MSL) syntaxiquement correct, mais ne peuvent pas vérifier la sortie visuelle ni déboguer les problèmes côté GPU. Les shaders Metal s’exécutent sur le GPU — l’agent n’a aucun mécanisme de retour pour savoir si le shader produit des résultats visuels corrects.

Ce que les agents peuvent faire avec Metal : - Écrire des vertex shaders et fragment shaders à partir de descriptions - Mettre en place le pipeline de rendu Metal en Swift - Créer des compute shaders pour des opérations data-parallèles - Corriger les erreurs de compilation dans les fichiers .metal

Ce que les agents ne peuvent pas faire avec Metal : - Vérifier la justesse visuelle de la sortie d’un shader - Déboguer les performances GPU (temps d’image, occupancy, bande passante mémoire) - Diagnostiquer les artefacts visuels (banding, problèmes de précision, espace colorimétrique incorrect) - Tester sur différentes architectures GPU (différences de comportement entre A-series et M-series)

La parade : Testez les shaders Metal sur des appareils physiques. L’implémentation Metal du Simulator n’est pas représentative du comportement GPU d’un appareil. Utilisez le GPU Frame Capture de Xcode pour le débogage visuel.

Vérification de la mise en page visuelle

Les agents ne peuvent pas voir l’UI de votre application. Ils écrivent du code de mise en page SwiftUI et peuvent vérifier qu’il compile, mais ils ne peuvent pas dire si l’écran résultant a l’air correct. Une vue qui s’affiche décalée de 10 pixels, utilise la mauvaise graisse de police ou présente des éléments qui se chevauchent ne produit aucune erreur de build et passe tous les tests logiques.

La parade : Inspectez visuellement les changements d’UI. Utilisez les SwiftUI Previews dans Xcode (ou RenderPreview via Apple MCP pour le rendu headless) pour vérifier la mise en page. Envisagez les tests par snapshot avec des bibliothèques comme swift-snapshot-testing pour une détection automatisée des régressions visuelles.

Hooks pour le développement iOS

Les hooks sont des commandes shell qui s’exécutent de manière déterministe à des points précis du workflow de l’agent. Ils constituent le mécanisme d’application — la différence entre « merci de ne pas modifier .pbxproj » (une suggestion que l’agent peut ignorer) et « vous ne pouvez pas modifier .pbxproj » (un blocage strict).

Pour une présentation du système de hooks, consultez le guide des hooks Claude Code. Cette section couvre les modèles de hooks spécifiques à iOS.

PreToolUse : bloquer les écritures dans .pbxproj

Le hook le plus important dans tout projet iOS. Il empêche l’agent d’écrire dans les fichiers .pbxproj, les répertoires .xcodeproj/ et autres fichiers gérés par 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'"
      }
    ]
  }
}

Placez cela dans .claude/settings.json à la racine du projet ou dans ~/.claude/settings.json pour une protection globale.

Fonctionnement : lorsque l’agent tente d’utiliser l’outil Edit ou Write sur un fichier correspondant au motif, le hook s’exécute, détecte le chemin du fichier, affiche un avertissement sur stderr et se termine avec le code 2 (ce qui bloque l’utilisation de l’outil). L’agent reçoit le message d’erreur et adapte son approche.

Ce qu’il intercepte : - Les modifications directes de .pbxproj - Tout fichier à l’intérieur des répertoires .xcodeproj/ ou .xcworkspace/ - Les fichiers Interface Builder (.xib, .storyboard)

PostToolUse : formatage automatique avec SwiftFormat

Formatez automatiquement les fichiers Swift chaque fois que l’agent les écrit ou les modifie :

{
  "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'"
      }
    ]
  }
}

Prérequis : SwiftFormat doit être installé (brew install swiftformat).

Pourquoi c’est important : les agents produisent du Swift syntaxiquement correct mais ne respectent pas systématiquement les conventions de formatage. SwiftFormat normalise l’indentation, le placement des accolades et l’ordre des imports. Le hook de formatage automatique garantit que chaque fichier Swift que l’agent touche est formaté avant que vous ne le voyiez.

Optionnel : ajoutez un fichier de configuration .swiftformat à la racine de votre projet pour personnaliser les règles de formatage :

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

PostToolUse : exécution automatique de SwiftLint

Si vous utilisez SwiftLint, exécutez-le après chaque modification de fichier 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'"
      }
    ]
  }
}

Le || true empêche les avertissements de lint de bloquer l’agent. Si vous souhaitez que les violations de lint bloquent, supprimez-le.

PostToolUse : build automatique après modification

Pour des boucles de feedback agressives, déclenchez un build après chaque modification de fichier 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'"
      }
    ]
  }
}

Avertissement : c’est coûteux. Chaque modification de fichier déclenche un build. Utilisez avec parcimonie — c’est surtout utile lors de sessions de débogage où vous voulez un retour de build immédiat. Pour le développement normal, laissez l’agent déclencher les builds manuellement via MCP lorsqu’il est prêt.

PreToolUse : bloquer les modifications d’entitlements

Protégez votre fichier d’entitlements des modifications accidentelles de l’agent :

{
  "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'"
      }
    ]
  }
}

Configuration combinée des hooks iOS

Voici le fichier .claude/settings.json complet que j’utilise sur tous mes projets iOS :

{
  "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'"
      }
    ]
  }
}

Cela vous offre deux garanties : 1. L’agent ne peut pas corrompre les fichiers de projet Xcode (blocage PreToolUse) 2. Chaque fichier Swift que l’agent touche est formaté automatiquement (formatage PostToolUse)

Architectures qui fonctionnent avec les agents

Toutes les architectures Swift ne sont pas aussi adaptées aux agents. Ces patterns produisent les meilleurs résultats parce qu’ils sont explicites, cohérents et bien représentés dans les données d’entraînement.

@Observable (jamais ObservableObject)

Les cibles iOS 26+ doivent utiliser exclusivement @Observable. Il s’agit à la fois du pattern moderne et du pattern adapté aux agents :

// 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()
}

Pourquoi @Observable est adapté aux agents : le pattern est plus simple (pas besoin d’annotations @Published), le modèle de propriété est plus clair (@State au lieu de @StateObject vs @ObservedObject), et les agents produisent moins de bugs avec lui parce qu’il y a moins d’éléments mobiles.

Documentez ceci dans CLAUDE.md : même avec iOS 26 comme cible, les agents reviennent occasionnellement aux patterns ObservableObject issus de leurs données d’entraînement. Une interdiction explicite empêche cela.

// 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 est disponible depuis iOS 16+ et constitue le seul pattern de navigation que vous devez utiliser pour le nouveau code. Le pattern navigationDestination(for:) typé empêche l’agent de créer des liens de navigation incorrects.

SwiftData pour la persistance

Les modèles SwiftData constituent le pattern de persistance le plus propre pour le développement assisté par agent :

@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
    }
}

Règles clés pour les agents travaillant avec SwiftData : 1. Les classes @Model sont automatiquement Observable — n’ajoutez pas @Observable 2. Utilisez @Bindable pour les bindings de formulaire : @Bindable var item: GroceryItem 3. Utilisez @Query dans les vues pour les données réactives : @Query var items: [GroceryItem] 4. Utilisez modelContext.fetch() dans le code hors vue 5. Les suppressions de relations nécessitent des règles explicites : .cascade, .nullify, .deny

Concurrence Swift 6.2

Visez la concurrence stricte Swift 6.2 pour les nouveaux projets :

// 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
}

Conseils aux agents pour la concurrence : - Marquez tous les view models @MainActor (évite les avertissements de data race) - Utilisez async/await pour tout travail asynchrone (pas de completion handlers) - Rendez les types valeur Sendable pour les transferts entre acteurs - Utilisez Task { } dans les vues pour l’initialisation asynchrone - Utilisez nonisolated uniquement lorsque vous avez mesuré un besoin de performance

Système de design Liquid Glass (iOS 26+)

iOS 26 a introduit le système de design Liquid Glass. Les agents le gèrent bien lorsqu’ils reçoivent des consignes explicites :

// 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()

À inclure dans CLAUDE.md : « Utilisez .glassEffect() sur les arrière-plans de sections et les conteneurs de cartes. Les barres de navigation adoptent automatiquement le matériau Liquid Glass dans iOS 26. Ne recréez pas manuellement les effets de verre avec des matériaux personnalisés — utilisez le modificateur système. »


Contexte spécifique aux frameworks

Chaque framework Apple a des considérations propres aux agents. Cette section couvre les frameworks utilisés dans les 8 applications.

HealthKit

Apps qui l’utilisent : Return, Water

HealthKit nécessite une gestion soignée des permissions et des garde-fous de plateforme :

// 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
        }
    }
}

Règles pour les agents avec HealthKit : - Protégez toujours avec HKHealthStore.isHealthDataAvailable() - Ne supposez jamais l’autorisation — vérifiez à chaque écriture - Utilisez #if canImport(HealthKit) pour le code multi-plateforme (HealthKit indisponible sur tvOS) - Ne stockez jamais les données de santé localement au-delà de ce que HealthKit fournit - Incluez à la fois NSHealthShareUsageDescription et NSHealthUpdateUsageDescription dans Info.plist

SpriteKit

Apps qui l’utilisent : TappyColor, Starfield Destroyer

Le modèle de scene graph de SpriteKit nécessite des consignes explicites pour les agents :

## 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)

Points forts des agents avec SpriteKit : - Création de séquences et de groupes SKAction - Configuration des corps physiques et de la détection de contact - Implémentation de machines à états de jeu - Construction de superpositions HUD

Points faibles des agents avec SpriteKit : - Boucles de jeu sensibles aux performances (l’agent ajoute du travail inutile à chaque frame) - Simulations physiques complexes (une physique personnalisée surpasse SKPhysicsBody en précision) - Réglage des effets de particules (visuel, nécessite des itérations)

Metal

Apps qui l’utilisent : amp97, Water, Starfield Destroyer

Metal est le framework où les agents peinent le plus. Le modèle de programmation GPU est fondamentalement différent du Swift côté CPU, et les agents ne peuvent pas vérifier la sortie visuelle.

## 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

Ce qu’il faut inclure dans CLAUDE.md pour les projets Metal : - La définition du struct Uniforms (partagé entre Swift et MSL) - Le pattern de configuration de l’état du pipeline de rendu - Les indices de buffer et leurs usages - Quels shaders existent et ce que chacun fait - Les problèmes de précision connus (half vs float)

Live Activities

Apps qui l’utilisent : Return

Les Live Activities nécessitent une configuration spécifique que les agents gèrent bien une fois documentée :

## 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

Apps qui l’utilisent : 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)

Modèles multi-plateformes

Return couvre iOS, watchOS et tvOS. Le développement multi-plateforme avec des agents nécessite une documentation explicite des frontières entre plateformes.

Organisation du code partagé

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

Règle pour les agents : « Si un fichier se trouve dans Shared/, les modifications affectent toutes les plateformes. Si un fichier se trouve dans un dossier spécifique à une plateforme, les modifications sont isolées. Vérifiez toujours dans quel dossier se trouve un fichier avant de le modifier. »

Garde-fous de disponibilité par plateforme

// 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

Conseils aux agents : « Utilisez toujours les garde-fous #if canImport() ou #if os() lorsque vous utilisez des frameworks spécifiques à une plateforme. Ne supposez pas qu’un framework est disponible sur toutes les cibles. »

Adaptation de l’UI par plateforme

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
    }
}

Workflows avancés

Boucles autonomes build-test-fix

Le modèle le plus puissant : donner à l’agent une spécification de fonctionnalité et le laisser itérer à travers des cycles build-test-fix de façon autonome.

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.

L’agent écrit du code, compile via MCP, lit les erreurs structurées, les corrige, et recommence. Une fonctionnalité qui exigerait 5 à 10 cycles humains de build-erreur-correction se termine en une seule boucle autonome.

Quand cela fonctionne : des fonctionnalités bien définies avec des critères d’acceptation clairs.

Quand cela échoue : des fonctionnalités ouvertes (« faites en sorte que ça soit beau »), du code sensible aux performances, ou tout ce qui nécessite une vérification visuelle.

Délégation à un sous-agent pour iOS

Le système de sous-agents de Claude Code fonctionne pour les projets 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.

Le sous-agent explore la documentation et les modèles de code dans une fenêtre de contexte distincte, retourne un résumé, et la session principale implémente la recommandation. Cela évite que la recherche ne consomme votre contexte principal.

Application de modèles entre applications

Lorsque vous maintenez plusieurs applications iOS avec des modèles cohérents, les agents peuvent appliquer les modèles d’une application à une autre :

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.

L’agent lit le modèle source, comprend la structure, et crée une implémentation cohérente dans le projet cible.

Revue à deux agents (Claude + Codex)

Pour les changements critiques, utilisez deux agents issus de familles de modèles différentes :

  1. Claude Code écrit l’implémentation
  2. Codex CLI la passe en revue dans une seconde passe
# 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."

Des familles de modèles différentes détectent des classes d’erreurs différentes. C’est particulièrement précieux pour les shaders Metal et les modèles de concurrence où les bugs subtils sont faciles à introduire.

Ce que la revue à deux agents détecte et qu’une revue unique manque :

Type de problème Force de Claude Force de Codex
Cycles de relations SwiftData Modérée Forte (GPT-4o)
Lacunes d’isolation @MainActor Forte Modérée
Alignement de buffer Metal Modérée Modérée
Détection de cycles de rétention Forte (Opus) Forte (o3)
Conscience des dépréciations API Forte (données d’entraînement plus récentes) Modérée
Conditions de course en concurrence Forte Forte (différents modèles détectés)

La revue à deux agents ne vise pas à trouver plus de bugs — elle vise à trouver des bugs différents. Chaque famille de modèles a des modes de défaillance différents dans sa reconnaissance de modèles.

Opérations par lots sur plusieurs applications

Lorsqu’un changement de framework ou de modèle affecte plusieurs applications :

# 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

À utiliser avec prudence. Le drapeau --dangerously-skip-permissions est requis pour le mode non interactif mais contourne tous les contrôles de sécurité. Assurez-vous que vos hooks PreToolUse sont en place pour protéger les fichiers .pbxproj.

Applications qui utilisent le LLM on-device d’Apple

Si votre application appelle le framework Foundation Models d’Apple (par exemple pour la synthèse hors ligne, la classification ou la génération de sortie structurée), les agents doivent connaître le budget de prompt. iOS 26.4 a ajouté deux APIs à SystemLanguageModel qui ont remplacé l’ancienne estimation de 4096 tokens : contextSize (nombre maximal de tokens que le modèle accepte dans une seule conversation) et tokenCount(for:) (async throws, retourne le nombre de tokens qu’un prompt donné coûte réellement).16 Les deux sont @backDeployed(before: iOS 26.4), donc disponibles sur toutes les versions d’OS prenant en charge FM sans nécessiter d’échelle #available.

Le modèle qu’un agent devrait suivre lorsqu’il génère du code de construction de prompt :

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
}

Ajoutez ce modèle à votre CLAUDE.md si l’application touche à SystemLanguageModel. Sans cela, les agents reviennent à l’ancienne valeur codée en dur de 4096 et tronquent silencieusement les prompts sur les appareils livrés avec des fenêtres de contexte plus grandes. La signature async throws sur tokenCount(for:) est essentielle — les agents qui collent une version synchrone échoueront à la compilation.


Études de cas concrètes

Les conseils abstraits sont faciles. Voici des scénarios spécifiques tirés des 8 applications qui illustrent le fonctionnement du développement iOS assisté par agents en pratique — y compris les échecs.

Étude de cas 1 : ajouter une application TV à Return (succès)

La tâche : ajouter une cible tvOS à Return, un minuteur de méditation qui disposait déjà de versions iOS et watchOS. L’application TV nécessitait une navigation à la Siri Remote, une interface adaptée aux grands écrans et la synchronisation des paramètres avec l’application iOS.

Ce que l’agent a bien réussi : - Lecture du TimerManager iOS existant et création d’un TVTimerManager qui omet les Live Activities et HealthKit (indisponibles sur tvOS) - Création de styles de boutons personnalisés pour la navigation au focus de la Siri Remote (TVCapsuleButtonStyle, TVCircleButtonStyle) - Construction d’un composant TVStepper qui remplace les sélecteurs à roulette (inutilisables avec la Siri Remote) par des boutons +/- - Mise en place de la synchronisation des paramètres via App Groups (group.com.941apps.Return) - Ajout de directives #if os(tvOS) dans tout le code partagé - Compilation et tests via MCP avec platform=tvOS Simulator,name=Apple TV

Ce que j’ai dû faire manuellement : - Créer la cible tvOS dans Xcode (File > New > Target > tvOS App) - Ajouter la nouvelle cible au projet Xcode (modifications du .pbxproj) - Configurer l’entitlement App Groups pour la cible TV - Ajouter la cible TV au schéma existant ou en créer un nouveau - Ajouter manuellement tous les fichiers Swift créés par l’agent à la cible TV - Tester la navigation à la Siri Remote à la main (l’agent ne peut pas évaluer le comportement du focus)

Résultat : 15 nouveaux fichiers Swift, une application TV pleinement fonctionnelle, en environ 3 heures de travail assisté par agent. Selon mon estimation, l’agent a pris en charge environ 80 % du travail d’implémentation ; je me suis chargé des parties qui exigeaient une interaction avec l’interface de Xcode (entitlements, configuration de la cible, capability flags) ainsi que des tests manuels du focus sur une vraie Apple TV. Un travail équivalent réalisé en solo dans cette base de code — d’après des fonctionnalités similaires que j’ai livrées sans agents — aurait représenté plusieurs jours d’effort.

Étude de cas 2 : débogage de shader Metal dans amp97 (échec partiel)

La tâche : ajouter un système d’intensité basé sur l’énergie au shader d’oscilloscope. La visualisation devait pulser avec l’énergie audio.

Ce qui s’est passé : 1. L’agent a écrit une modification valide du shader Metal en ajoutant un uniform uEnergy et un tonemapping HDR 2. Le code s’est compilé sans erreur 3. Sur l’appareil, la visualisation était entièrement blanche — le coefficient d’intensité était 10 fois trop élevé (3,5 au lieu de 0,30) 4. L’agent ne pouvait pas voir l’écran blanc, il n’avait donc aucun signal de retour 5. J’ai identifié le problème visuellement et demandé à l’agent de réduire le coefficient 6. L’agent l’a réduit, mais la machine d’état d’énergie globale était trop complexe et a cassé le visualiseur d’autres manières 7. Tout a été annulé — deux commits (67959ed et cda4830) annulés dans 869d914

La leçon : les shaders Metal constituent le domaine le plus difficile pour le développement assisté par agent, car la boucle de rétroaction est rompue. L’agent peut vérifier la syntaxe (cela compile) et la sémantique (types corrects), mais il ne peut pas vérifier la sortie (rendu correct). Toute modification de shader qui change le comportement visuel exige une vérification humaine sur l’appareil.

Ce que j’ai ajouté à CLAUDE.md après cela : « DO NOT attempt energy state modifications to the oscilloscope shader without extremely careful coefficient testing. Previous attempt broke the visualizer with coefficients 10x too high. »

Étude de cas 3 : migration SwiftData dans Banana List (succès)

La tâche : migrer le modèle de données de V1 à V2, en ajoutant un champ quantity à GroceryItem ainsi qu’un nouveau modèle Category avec des relations.

Ce qu’a fait l’agent : 1. Lecture des définitions de modèles V1 existantes 2. Création des définitions de modèles V2 avec les nouveaux champs et relations 3. Rédaction d’un GroceryMigrationPlan conforme au protocole SchemaMigrationPlan 4. Implémentation de l’étape de migration V1toV2 : ajout des valeurs par défaut quantity: 1 et category: nil 5. Mise à jour de toutes les vues pour prendre en charge les nouveaux champs 6. Mise à jour de SampleData.swift pour les previews 7. Compilation et exécution des tests via MCP — tous réussis 8. Création de tests unitaires spécifiques à la migration

La clé : l’agent a réussi parce que les migrations SwiftData suivent un schéma de protocole bien défini, largement représenté dans la documentation d’Apple et les données d’entraînement. Le CLAUDE.md documentait explicitement le modèle V1, ce qui permettait à l’agent de comprendre depuis quoi il migrait.

Étude de cas 4 : synchronisation de sessions iCloud dans Return (succès avec complexité)

La tâche : mettre en place la journalisation des sessions de méditation entre appareils. Les sessions terminées sur Apple TV ou Mac devaient se synchroniser vers l’iPhone pour être enregistrées dans HealthKit.

Ce que l’agent a produit :

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

L’agent : 1. A créé le modèle de données MeditationSession avec UUID, dates, durée, appareil source et statut de synchronisation HealthKit 2. A construit un singleton SessionStore gérant NSUbiquitousKeyValueStore pour la synchronisation iCloud 3. A implémenté la résolution des conflits de fusion (déduplication basée sur l’UUID) 4. A ajouté une SessionHistoryView avec des adaptations spécifiques à chaque plateforme (balayer pour supprimer sur iOS, basé sur le focus sur tvOS) 5. A câblé la synchronisation HealthKit côté iPhone pour les sessions provenant d’autres appareils

Ce qui a nécessité des itérations : l’implémentation initiale ne gérait pas le cas où l’application iPhone se lance en arrière-plan (aucune notification de premier plan pour la synchronisation). L’agent avait besoin d’une indication précise : « Utilise NSUbiquitousKeyValueStore.didChangeExternallyNotification pour déclencher la synchronisation lors des changements de KV en arrière-plan. » Après cet indice, l’implémentation était correcte.

La leçon : les agents gèrent bien les schémas architecturaux multiplateformes lorsque l’architecture est clairement décrite. Le schéma de synchronisation iCloud n’est pas trivial, mais il suit un schéma Apple documenté que l’agent a su comprendre. Le cas limite (synchronisation en arrière-plan) a exigé une connaissance humaine du domaine, car il n’est pas bien documenté.

Étude de cas 5 : intégration Game Center dans Starfield Destroyer (succès)

La tâche : ajouter des classements et des succès Game Center au shoot ‘em up spatial.

Ce que l’agent a bien réussi : - Mise en place de GKLocalPlayer.local.authenticateHandler dans le point d’entrée de l’application - Création d’un GameCenterManager avec des méthodes pour la soumission des scores et le signalement des succès - Ajout d’une vérification de l’état d’authentification avant toute opération Game Center - Gestion gracieuse du cas hors ligne (le jeu fonctionne sans Game Center, soumet à la reconnexion) - Création de définitions de succès correspondant au système de progression à 8 vaisseaux

Ce qui a nécessité un travail manuel : - Créer les classements et succès dans App Store Connect (portail web, non accessible à l’agent) - Configurer l’entitlement Game Center dans Xcode - Tester avec un compte Game Center sandbox (nécessite une connexion manuelle sur l’appareil)


Cycle de vie du projet avec les agents

Démarrer un nouveau projet iOS

Le flux de travail optimal pour démarrer un nouveau projet avec l’assistance d’un agent :

Phase 1 : Configuration humaine (15 à 30 minutes) 1. Créez le projet Xcode (File > New > Project) 2. Configurez la signature et les capacités 3. Définissez la cible de déploiement et les destinations prises en charge 4. Ajoutez les entitlements requis (HealthKit, Game Center, etc.) 5. Créez le fichier CLAUDE.md initial avec l’identité et les règles du projet

Phase 2 : Implémentation par l’agent (heures à jours) 1. L’agent crée le modèle de données (SwiftData, Core Data ou structs simples) 2. L’agent construit les vues en suivant vos modèles documentés 3. L’agent implémente la logique métier dans des classes manager/service 4. L’agent rédige les tests unitaires 5. Boucle build-test-fix via MCP (autonome)

Phase 3 : Intégration humaine (30 à 60 minutes) 1. Ajoutez les fichiers créés par l’agent aux cibles Xcode 2. Vérifiez la signature et les entitlements 3. Testez sur un appareil physique 4. Examinez la mise en page visuelle et l’UX 5. Soumettez à App Store Connect

Maintenir un projet existant

Pour le développement continu d’applications établies :

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]

L’efficacité de l’agent évolue en fonction de la qualité avec laquelle votre CLAUDE.md reflète l’état actuel du projet. Mettez à jour votre CLAUDE.md lorsque vous ajoutez de nouvelles fonctionnalités importantes, modifiez les modèles architecturaux ou introduisez de nouveaux frameworks.

Quand impliquer l’agent ou non

Tâche Agent ? Pourquoi
Nouvelle vue SwiftUI Oui Les agents excellent dans l’UI déclarative
Modifications du modèle SwiftData Oui Bien défini, testable
Tests unitaires Oui Mécanique, basé sur des modèles
Refactorisation Oui Systématique, multi-fichiers
Diagnostic des erreurs de build Oui (via MCP) Boucle de retour structurée
Nouvelle cible Xcode Non Nécessite l’UI Xcode, modifications du .pbxproj
Signature et provisioning Non Basé sur le portail, non accessible à l’agent
Finition visuelle Non Nécessite un jugement esthétique humain
Réglage des shaders Metal Non Nécessite des tests sur appareil GPU
Soumission à l’App Store Non Portail et Xcode Organizer
Profilage des performances Non Nécessite Instruments
Audit d’accessibilité Partiel L’agent peut ajouter des labels, l’humain vérifie VoiceOver

Configurer les définitions d’agent

Si vous utilisez le système de définition d’agent de Claude Code (.claude/agents/), créez un agent spécifique à 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

Référencez cet agent avec @ios-developer dans les sessions Claude Code.


Modèles de tests pour iOS assisté par agent

Les agents rédigent d’excellents tests unitaires lorsqu’ils reçoivent des directives claires. Voici les modèles qui produisent les meilleurs résultats.

Organisation des fichiers de test

# 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`

Formuler des prompts pour les tests

Prompt de test efficace :

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.

Pourquoi cela fonctionne : des critères d’acceptation numérotés fournissent à l’agent une checklist. Référencer un fichier de test existant établit le modèle. Spécifier l’utilisation de setUp() empêche l’agent de créer un état de test enchevêtré.

Prompt de test inefficace :

Write tests for TimerManager.

Cela produit des tests génériques et superficiels qui passent à côté des cas limites et risquent de ne pas suivre les modèles de votre projet.

Modèles de tests asynchrones

Pour tester le code basé sur des timers et asynchrone :

// 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)
    }
}

Modèles clés que les agents doivent qu’on leur rappelle : - @MainActor sur les méthodes de test qui testent des classes @MainActor - async throws pour les tests qui utilisent Task.sleep ou des opérations asynchrones - Tolérance dans les assertions basées sur le temps (1,1 seconde, pas exactement 1,0) - setUp() / tearDown() propres pour l’isolation des tests

Tests par capture d’écran

Pour la détection des régressions visuelles, envisagez d’ajouter 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.

Les agents configurent correctement les tests par capture d’écran mais ne peuvent pas examiner les images de référence. Vous examinez les captures initiales, puis les tests de l’agent détectent les régressions visuelles dans les modifications futures.


Gestion de la fenêtre de contexte pour les projets iOS

La fenêtre de contexte de 1M (Opus 4.6) est vaste mais pas infinie. Les projets iOS ont des considérations spécifiques en matière de gestion du contexte.

Coût en tokens des fichiers iOS

Type de fichier Taille typique Tokens approximatifs
Vue SwiftUI (simple) 50-100 lignes 500-1 000
Vue SwiftUI (complexe) 200-400 lignes 2 000-4 000
Modèle SwiftData 30-80 lignes 300-800
Classe manager/service 100-300 lignes 1 000-3 000
Shader Metal (.metal) 50-200 lignes 500-2 000
Fichier de tests unitaires 50-200 lignes 500-2 000
CLAUDE.md 100-300 lignes 1 000-3 000
Réponse MCP (build) variable 200-2 000
Réponse MCP (test) variable 500-5 000

Pour un projet de 50 fichiers : la lecture de tous les fichiers consomme environ 50 000 à 100 000 tokens — bien dans les limites de la fenêtre de 1M. L’agent peut conserver l’intégralité du projet en contexte.

Pour un projet de plus de 100 fichiers : une lecture sélective devient nécessaire. L’agent lit d’abord CLAUDE.md (pour les annotations sur la structure des fichiers), puis lit des fichiers spécifiques selon les besoins. C’est pourquoi les annotations de fichiers dans CLAUDE.md sont essentielles — elles guident l’agent vers les bons fichiers sans qu’il ait à tout lire.

Stratégies pour les grands projets

  1. Annotations détaillées des fichiers dans CLAUDE.md — l’agent lit la carte des fichiers et navigue directement vers les fichiers pertinents
  2. Délégation à des sous-agents — déléguez l’exploration et la recherche à des sous-agents (contexte propre, retourne des résumés)
  3. Prompts ciblés — « Modifier SettingsView.swift pour ajouter un nouveau toggle » est préférable à « mettre à jour les paramètres »
  4. Limites de session — démarrez de nouvelles sessions pour des fonctionnalités sans rapport plutôt que de prolonger une longue session
  5. Utilisez /compact — la commande de compaction de Claude Code résume la conversation et libère du contexte

Efficacité en tokens de MCP

L’un des arguments les plus solides en faveur de MCP : les réponses JSON structurées consomment beaucoup moins de tokens que la sortie brute de xcodebuild.

Scénario Tokens Bash bruts Tokens MCP Économies
Build réussi 3 000-10 000 200-500 85-95 %
Build échoué (1 erreur) 3 000-10 000 300-800 90-92 %
Résultats de tests (20 tests) 2 000-5 000 500-1 000 75-80 %
Liste des simulateurs 500-2 000 200-400 60-80 %

Sur une session de développement typique avec 10 à 20 cycles de build, MCP permet d’économiser 30 000 à 150 000 tokens par rapport à xcodebuild brut — des tokens qui restent disponibles pour le raisonnement sur le code lui-même.


Dépannage

« build_sim failed — scheme not found »

L’agent devine le nom du scheme. Correctif :

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

Ou ajoutez explicitement le nom du scheme à votre CLAUDE.md :

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

« xcrun mcpbridge — command not found »

Vous avez besoin de Xcode 26.3 ou une version ultérieure. Vérifiez avec xcodebuild -version. Si vous disposez de Xcode 26.3+ mais que la commande échoue toujours :

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

# Verify
xcrun mcpbridge --help

« Les outils MCP n’apparaissent pas dans Claude Code »

Les outils MCP enregistrés en cours de session peuvent ne pas apparaître avant un redémarrage. Quittez Claude Code et démarrez une nouvelle session :

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

Puis vérifiez :

You: List all available MCP tools from XcodeBuildMCP.

« L’agent continue d’utiliser xcodebuild via Bash au lieu de MCP »

L’agent ne découvre pas les outils MCP via Tool Search. Deux correctifs :

  1. Ajoutez des consignes explicites à CLAUDE.md (voir Apprendre à l’agent à utiliser MCP)
  2. Demandez directement : « Utilise l’outil MCP build_sim, pas xcodebuild via Bash »

« Le build réussit mais l’agent signale un échec »

XcodeBuildMCP analyse la sortie de xcodebuild. Si le build produit des avertissements qui ressemblent à des erreurs (fréquent avec les avertissements de dépréciation), l’agent peut mal interpréter le résultat. Vérifiez le champ status réel dans la réponse MCP.

« Le simulateur se bloque au démarrage »

Tuez tous les simulateurs et redémarrez :

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

Ou demandez à l’agent :

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

« L’agent a essayé de modifier .pbxproj malgré les règles de CLAUDE.md »

Les règles de CLAUDE.md sont des suggestions. Les hooks sont l’application stricte. Si vous n’avez pas de hook PreToolUse bloquant les écritures sur .pbxproj, l’agent finira par tenter cette opération. Installez le 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'"
      }
    ]
  }
}

Les règles disent « s’il vous plaît, ne le faites pas. » Les hooks disent « vous ne pouvez pas. »


FAQ

Par quel runtime d’agent commencer ?

Claude Code CLI avec XcodeBuildMCP. Il offre l’intégration MCP la plus profonde, le système de hooks le plus mature et la fenêtre de contexte de 1M (Opus 4.6) qui peut conserver des projets iOS entiers en mémoire de travail. Commencez par là, puis ajoutez Codex pour la revue et les agents natifs Xcode pour les modifications inline rapides à mesure que votre flux de travail évolue.

Ai-je besoin des deux serveurs MCP ?

Pour la plupart des développeurs, XcodeBuildMCP couvre à lui seul 90 % des besoins (builds, tests, simulateurs, débogage). Ajoutez le MCP Xcode d’Apple si vous souhaitez la recherche dans la documentation, la vérification via le REPL Swift, ou le rendu des previews SwiftUI. Vous pouvez toujours l’ajouter ultérieurement — les deux serveurs sont indépendants.

Les agents peuvent-ils créer un nouveau projet Xcode à partir de zéro ?

XcodeBuildMCP inclut un outil create_project qui génère de nouveaux projets Xcode. Toutefois, pour les apps en production, je recommande de créer le projet dans Xcode (afin d’obtenir une configuration correcte de la signature, des capacités et des cibles), puis d’utiliser les agents pour toute l’implémentation du code. Les 5 minutes passées dans l’assistant de nouveau projet de Xcode vous épargnent des heures de problèmes de configuration de projet générés par l’agent.

Comment les agents gèrent-ils les dépendances Swift Package Manager ?

Très bien. Package.swift est un fichier Swift standard que les agents peuvent lire et modifier de manière fiable. L’ajout de dépendances, la mise à jour des plages de versions et la configuration des cibles fonctionnent tous. La limite concerne la gestion des dépendances basée sur .xcodeproj (l’interface de résolution de packages de Xcode) — celle-ci est gérée par Xcode et ne devrait pas être modifiée par l’agent.

Les agents peuvent-ils soumettre à l’App Store ?

Non. La soumission à l’App Store implique l’Organizer de Xcode, les profils de provisionnement, les captures d’écran, les métadonnées et le portail App Store Connect. Aucun de ces éléments n’est accessible via MCP ou via des outils en ligne de commande d’une manière permettant aux agents d’agir de manière significative. Les agents s’occupent de tout jusqu’à l’archive — implémentation, tests, correction de bugs et documentation. Le dernier kilomètre de la soumission reste opéré par un humain.

Cependant, les agents peuvent aider avec les métadonnées App Store. Demandez à l’agent de rédiger la description de l’app, les mots-clés et le texte « Nouveautés » à partir des derniers changements. C’est du travail de génération de texte, un domaine où les agents excellent.

Comment gérer les secrets et les clés API dans le développement iOS assisté par agent ?

Ne committez jamais de secrets. Pour les apps iOS qui se connectent à des API backend :

  1. Utilisez des fichiers .xcconfig pour la configuration spécifique à l’environnement
  2. Ajoutez les fichiers .xcconfig à .gitignore
  3. Référencez les valeurs de configuration via les paramètres de build Info.plist
  4. Documentez les secrets requis dans CLAUDE.md sans inclure les valeurs réelles
## 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`.

L’agent sait que les clés existent et où elles sont utilisées, mais ne voit jamais les valeurs réelles.

Et les animations SwiftUI — les agents peuvent-ils les écrire ?

Les agents écrivent du code d’animation correct sur le plan syntaxique mais ne peuvent pas vérifier le résultat visuellement. Les animations simples (.animation(.spring()), .transition(.slide), withAnimation { }) produisent des résultats corrects. Les animations complexes en plusieurs étapes avec un timing précis nécessitent une itération visuelle que les agents ne peuvent pas effectuer.

Efficace : « Ajoute une animation spring lorsque le timer passe d’un état à un autre. »

Inefficace : « Fais en sorte que l’animation du timer soit satisfaisante. » (Subjectif, nécessite un ajustement visuel.)

Comment les agents gèrent-ils les patterns de gestion des erreurs ?

Très bien. Les agents comprennent les patterns Swift do/catch, Result et async throws :

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

Les agents produisent une gestion des erreurs structurée avec des messages destinés à l’utilisateur appropriés. Ils sur-gèrent parfois les erreurs (capturant des exceptions qui devraient se propager), donc relisez les blocs catch.

Puis-je utiliser des agents pour l’implémentation de l’accessibilité ?

Partiellement. Les agents ajoutent correctement les labels, hints et traits d’accessibilité :

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

Ce que les agents ne peuvent pas faire : vérifier que l’ordre de navigation VoiceOver est correct, tester la mise à l’échelle Dynamic Type, ou évaluer les ratios de contraste des couleurs. Utilisez l’Accessibility Inspector de Xcode pour la vérification.

Comment les agents gèrent-ils la migration Core Data (si vous n’utilisez pas SwiftData) ?

Les agents écrivent les mappings de migration Core Data et les versions de modèle, mais les étapes manuelles dans Xcode (création de nouvelles versions de modèle, sélection de la version actuelle) ne peuvent pas être automatisées. Si vous êtes encore sur Core Data plutôt que SwiftData, documentez l’historique des versions de modèle dans CLAUDE.md :

## Versions du modèle Core Data
- V1 : initiale (GroceryList, GroceryItem)
- V2 : ajout du modèle Category (actuelle)
- Migration : automatique légère pour V1→V2

Comment les agents gèrent-ils les previews SwiftUI ?

Deux méthodes : 1. L’outil RenderPreview d’Apple Xcode MCP affiche les previews sans interface et renvoie le résultat. L’agent peut vérifier qu’une preview se compile et s’affiche sans erreurs, mais il ne peut pas évaluer la justesse visuelle. 2. La vérification par build via build_sim confirme que les preview providers se compilent. Si une preview plante à l’exécution, le build réussit malgré tout — le plantage ne se manifeste que lorsque Xcode tente d’afficher la preview.

Pour la vérification visuelle des previews, vous devez toujours avoir Xcode ouvert.

Qu’en est-il de visionOS et de l’Apple Vision Pro ?

Les mêmes patterns s’appliquent. XcodeBuildMCP prend en charge les simulateurs visionOS, et les patterns architecturaux (@Observable, NavigationStack, SwiftData) sont identiques. Le code spécifique à RealityKit (contenu 3D, espaces immersifs, suivi des mains) suit les mêmes limitations que Metal — les agents peuvent écrire du code correct mais ne peuvent pas vérifier la sortie spatiale.

Quelle est la taille maximale d’un projet avant que les agents ne peinent ?

La taille de la fenêtre de contexte est le facteur limitant. Avec la fenêtre de 1M de tokens d’Opus 4.6, Claude Code peut conserver environ 50 à 70 fichiers Swift en mémoire de travail active simultanément. Pour les projets plus grands, l’agent utilise la recherche de fichiers et la lecture sélective pour travailler avec des sous-ensembles du codebase. Les projets de plus de 100 fichiers fonctionnent très bien — l’agent lit simplement les fichiers à la demande au lieu de tout garder en contexte.

La limite pratique n’est pas le nombre de fichiers mais la cohérence du codebase. Un projet de 200 fichiers bien documenté avec un CLAUDE.md détaillé produit de meilleurs résultats qu’un projet de 30 fichiers non documenté.

Dois-je connaître Swift pour utiliser des agents en développement iOS ?

Vous devez être capable d’examiner les sorties de l’agent et de prendre des décisions architecturales. Vous n’avez pas besoin d’écrire chaque ligne vous-même, mais vous devez maîtriser Swift suffisamment pour détecter quand l’agent fait des choix incorrects — en particulier autour de la concurrence, de la gestion mémoire et des patterns spécifiques aux frameworks. Un agent est un amplificateur 10x de votre compétence existante, pas un substitut.

Comment les agents gèrent-ils les conflits de fusion dans les fichiers Swift ?

Les agents résolvent les conflits de fusion dans les fichiers source Swift de manière fiable. Les marqueurs de conflit standard (<<<<<<<, =======, >>>>>>>) sont bien compris par tous les runtimes d’agents. Toutefois, les conflits de fusion dans les fichiers .pbxproj restent une tâche de résolution manuelle — ne demandez pas aux agents de résoudre les conflits .pbxproj.

Quel est le coût d’utilisation des agents pour le développement iOS ?

Avec le plan Max de Anthropic (Opus 4.6, contexte 1M), une session typique de développement iOS dure 30 à 120 minutes et traite 200K à 800K tokens. Les appels d’outils MCP ajoutent une charge minimale (les réponses JSON structurées sont efficaces en tokens par rapport à la sortie brute du build). Le coût est comparable à l’exécution de Claude Code pour tout autre codebase — le développement iOS n’est ni plus ni moins coûteux que le développement web de manière significative.

Puis-je utiliser des agents avec des projets UIKit ?

Oui, mais les agents sont plus efficaces avec SwiftUI. UIKit nécessite plus de code passe-partout, a une structure moins déclarative et implique souvent des fichiers Interface Builder que les agents ne peuvent pas modifier. Si vous avez un projet UIKit, envisagez d’utiliser des agents pour la couche modèle et la logique métier tout en gérant l’UI manuellement, ou de migrer progressivement les vues vers SwiftUI.

Comment les agents gèrent-ils la localisation ?

Les agents créent et modifient les fichiers .xcstrings (Xcode string catalog) efficacement. Ils peuvent ajouter de nouvelles clés de localisation, fournir des traductions et maintenir la cohérence entre les langues. Le format JSON structuré des fichiers .xcstrings est adapté aux agents. Pour les fichiers .strings (format hérité), les agents fonctionnent également bien — le format clé-valeur est simple.


Erreurs courantes des agents sous iOS (et comment les prévenir)

Voici les erreurs récurrentes que j’ai observées au fil de milliers d’interactions avec des agents sur 8 projets iOS. Chacune dispose d’une stratégie de prévention.

Erreur 1 : mélanger les patterns Observable

Ce qui se passe : l’agent utilise @Observable dans un fichier et ObservableObject dans un autre, ou ajoute @Observable à une classe @Model (qui est déjà Observable).

Prévention : des règles explicites dans 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

Erreur 2 : créer des cycles de rétention dans les closures

Ce qui se passe : l’agent crée des closures qui capturent self fortement, en particulier dans Timer.publish, NotificationCenter et les completion handlers.

Prévention : incluez un pattern de closure dans 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

Erreur 3 : ignorer les exigences @MainActor

Ce qui se passe : l’agent crée des classes @Observable sans isolation @MainActor, ce qui provoque des avertissements de concurrence Swift 6.2 ou des plantages à l’exécution lorsque les mises à jour de l’UI ont lieu hors du main thread.

Prévention :

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

Ce qui se passe : l’agent utilise le NavigationLink(destination:label:) déprécié au lieu du pattern type-safe NavigationLink(value:) + .navigationDestination(for:).

Prévention :

## 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)) { }`

Erreur 5 : coder en dur les noms de simulateurs

Ce qui se passe : l’agent écrit des commandes de build avec des noms de simulateurs spécifiques (« iPhone 16 Pro ») qui peuvent ne pas exister sur votre système.

Prévention : MCP s’en charge — list_sims découvre les simulateurs disponibles. Dans 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.

Erreur 6 : créer des fichiers dans les mauvais répertoires

Ce qui se passe : l’agent crée un nouveau fichier de vue à la racine du projet au lieu du sous-répertoire Views/, ou place un modèle dans le mauvais groupe.

Prévention : les annotations de structure de fichiers dans CLAUDE.md guident le placement. De plus :

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

Erreur 7 : ne pas gérer la disponibilité des plateformes

Ce qui se passe : l’agent utilise HealthKit dans du code partagé qui se compile pour tvOS (où HealthKit n’est pas disponible), ou utilise ActivityKit dans du code watchOS.

Prévention :

## 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)

Erreur 8 : sur-ingénierie de fonctionnalités simples

Ce qui se passe : l’agent crée un protocole, une extension de protocole, une implémentation concrète, une factory et un conteneur d’injection de dépendances pour ce qui devrait être une fonction utilitaire de 20 lignes.

Prévention : incluez un principe de simplicité :

## 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

L’évaluation honnête

Après avoir livré 8 applications iOS avec des agents IA, voici le résumé :

Ce que les agents ont transformé : la vitesse d’implémentation. Ce qui prenait des jours prend désormais des heures. Les vues SwiftUI, les modèles SwiftData, les tests unitaires, le refactoring — tout cela est désormais principalement produit par les agents et révisé par des humains.

Ce que les agents n’ont pas transformé : les décisions d’architecture, la conception visuelle, l’optimisation des performances ou la soumission à l’App Store. Ces aspects restent pilotés par l’humain.

Le multiplicateur est réel mais limité. Mon estimation subjective sur l’ensemble du portefeuille de 8 applications : amélioration de 3 à 5x du délai de mise en œuvre des fonctionnalités sur les projets bien documentés avec une configuration appropriée de MCP et des hooks. Cela n’est pas mesuré par rapport à un groupe témoin ; il s’agit d’une comparaison en temps réel entre des fonctionnalités assistées par agent et un travail solo équivalent dans les mêmes codebases. Les projets non documentés sans hooks bénéficient peut-être d’une amélioration de 1,5 à 2x — l’agent passe trop de temps à deviner au lieu de construire.18

L’investissement qui paie : le temps consacré à CLAUDE.md, aux hooks et à la configuration de MCP. Chaque heure de configuration économise de nombreuses heures de correction des erreurs de l’agent. La configuration est le produit — l’agent est le moteur d’exécution.

Ce qui m’a surpris : à quel point les serveurs MCP ont changé la dynamique. Avant MCP, les agents étaient des éditeurs de texte sophistiqués qui se trouvaient comprendre Swift. Après MCP, ils sont devenus des partenaires de développement qui écrivent, compilent, testent, déboguent et itèrent. La boucle de rétroaction structurée fait toute la différence entre un agent qui écrit du code et un agent qui livre du code.

Ce que je dirais à mon moi du passé : commencez par la plus petite application (Reps, 14 fichiers), réussissez la configuration de MCP et des hooks, rédigez un CLAUDE.md complet, puis transposez les modèles vers des projets plus volumineux. Ne commencez pas par l’application multiplateforme de 63 fichiers. L’investissement en infrastructure est le même quelle que soit la taille du projet — faites-le une fois sur un petit projet, puis copiez-le partout ailleurs.

L’avenir : l’intégration native des agents dans Xcode 26.3 est le début, pas la fin. Le fait qu’Apple intègre la prise en charge de MCP signifie que la chaîne d’outils évolue vers un développement axé sur les agents. Les développeurs qui investissent dès maintenant dans des structures de projet compatibles avec les agents — fichiers CLAUDE.md propres, architectures testables, hooks automatisés — verront cet investissement fructifier au fur et à mesure que les outils s’améliorent.


Carte de référence rapide

Installation (configuration unique)

# 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

Sections essentielles de 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 essentiels

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

Règles d’architecture

@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+)

Priorités des outils 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)

Changelog

Date Modifications
2026-04-28 Recommandation portée à Xcode 26.4+ pour les workflows d’agent (26.4.1, 2026-04-16, build 17E202 est la dernière version stable, correctifs de bugs uniquement). Citation des fonctionnalités de Xcode 26.4 (2026-03-24, build 17E192) utiles pour les tests écrits par agents et la localisation : pièces jointes d’images Swift Testing, sévérité sur Issue.record, avertissements de plantage des tests d’interface avec les journaux de plantage joints (spécifiquement pour les applications XCUIApplication(bundleIdentifier:) / XCUIApplication(url:)), améliorations de l’éditeur de catalogue de chaînes. Ajout de l’auto-installateur xcodebuildmcp init (v2.1.0+, 2026-02-23) comme alternative à la configuration manuelle de MCP.
2026-04-27 App Store Connect : les soumissions Xcode 26+ deviennent obligatoires à partir du 2026-04-28. Foundation Models a gagné les APIs SystemLanguageModel.contextSize et tokenCount(for:) (rétroportés vers iOS 26.4) — ajout d’un modèle pour le code de budget de prompt FM généré par agent. iOS 26.4.2 (22 avril) et iOS 26.5 beta 3 (20 avril) sont sortis sans modifications affectant la chaîne d’outils des agents.
2026-04-13 Publication initiale. 8 applications, 3 runtimes, configuration de MCP, modèles CLAUDE.md, hooks, études de cas.

Références


  1. XcodeBuildMCP inclut la télémétrie Sentry par défaut. La documentation sur la confidentialité du projet détaille ce qui est envoyé : messages d’erreur, traces de pile et, dans certains cas, chemins de fichiers. La variable d’environnement XCODEBUILDMCP_SENTRY_DISABLED=true permet de se désinscrire entièrement. 

  2. Anthropic, « Model Context Protocol Specification », modelcontextprotocol.io/specification. La spécification MCP définit le transport JSON-RPC, la découverte d’outils et le protocole de ressources que XcodeBuildMCP et le Xcode MCP d’Apple implémentent tous deux. 

  3. XcodeBuildMCP, github.com/getsentry/XcodeBuildMCP. Open source, maintenu par Sentry. 59 outils couvrant les workflows de simulateur, d’appareil, de débogage et d’automatisation d’interface utilisateur. Versionnage sémantique avec changelogs. 

  4. Apple a introduit le serveur Xcode MCP dans le cadre de l’initiative Xcode 26.3 sur les outils de développement intelligents, positionnant MCP comme la couche d’interface entre les assistants de codage IA et la chaîne d’outils Xcode. Consultez les Xcode Release Notes pour la documentation officielle. 

  5. Rudrank Riyam, « Exploring Xcode Using MCP Tools », rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients, 2026. Confirmation indépendante du nombre d’outils MCP d’Apple, de la dépendance XPC et des capacités de recherche dans la documentation. 

  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. Les agents disposant d’un accès structuré aux outils ont nettement surpassé les agents limités à des commandes shell non structurées. Ce résultat valide les interfaces MCP structurées pour l’efficacité des agents. 

  7. Documentation Claude Code CLI, code.claude.com. Système de hooks, configuration MCP, délégation aux sous-agents et définitions d’agents. 

  8. SwiftFormat, github.com/nicklockwood/SwiftFormat. L’outil de formatage Swift utilisé dans les hooks PostToolUse pour un style de code cohérent. 

  9. Site officiel de XcodeBuildMCP, xcodebuildmcp.com. Confirme les 59 outils MCP via un exemple de sortie CLI. Catégories d’outils : simulateur, appareil, débogage et automatisation d’interface utilisateur. Installation via Homebrew ou npx. 

  10. Swiftjective-C, « Agentic Coding in Xcode 26.3 with Claude Code and Codex », swiftjectivec.com, février 2026. Confirme que Xcode 26.3 est livré avec une prise en charge native de l’agent Claude et du runtime Codex via Settings > Intelligence. 20 outils MCP exposés via xcrun mcpbridge

  11. Blake Crosley, « Two MCP Servers Made Claude Code an iOS Build System », blakecrosley.com/blog/xcode-mcp-claude-code, février 2026. Guide d’installation pas à pas et résultats concrets issus du workflow de développement iOS du même auteur. 

  12. Apple Developer News, « Upcoming Requirements ». L’entrée du 2026-04-28 : « Apps uploaded to App Store Connect must be built with Xcode 26 or later using an SDK for iOS 26, iPadOS 26, tvOS 26, visionOS 26, or watchOS 26. » macOS ne figure pas dans l’ensemble de plateformes listées pour cette exigence. 

  13. Apple, « Xcode 26.4 Release Notes ». Xcode 26.4 (2026-03-24, build 17E192). Fonctionnalités citées d’après les release notes : Swift Testing prend désormais en charge les pièces jointes d’images via CGImage, NSImage, UIImage et CIImage ; Issue.record accepte des niveaux de gravité ; certains plantages d’applications lors des UI tests — précisément les applications avec lesquelles on interagit via XCUIApplication(bundleIdentifier:) ou XCUIApplication(url:) — sont signalés comme avertissements avec crashlogs joints plutôt que comme échecs du test ; l’éditeur de String Catalog ajoute le couper/copier/coller des entrées, la suppression de langue et le pré-remplissage des traductions à partir d’une langue existante, ainsi que le paramètre BUILD_ONLY_KNOWN_LOCALIZATIONS

  14. Apple Developer News, « Xcode 26.4.1 (Build 17E202) Now Available », 2026-04-16. Version mineure de correction de bugs uniquement — corrige un plantage MetricKit dû à des symboles manquants sur iOS / macOS / visionOS pré-26.4, ainsi qu’un bug d’allocation de pile asynchrone Swift (« freed pointer was not the last allocation » dans swift_asyncLet_finish). 

  15. getsentry/XcodeBuildMCP v2.1.0 release, 2026-02-23. Ajout de la commande CLI xcodebuildmcp init pour installer les compétences d’agent et la configuration MCP en une seule étape, remplaçant le script autonome install-skill.sh. Détecte automatiquement Claude Code, Cursor et Codex ; prend en charge --print (écrit la configuration sur stdout pour les clients non pris en charge) et --uninstall (suppression). 

  16. InfoQ, « Apple Adds Context Window Management to Foundation Models », mars 2026. Documente les nouvelles API SystemLanguageModel.contextSize et tokenCount(for:) et confirme les annotations @backDeployed(before: iOS 26.4). Remplace l’estimation communautaire précédente d’un codage en dur à 4096 tokens. 

  17. Comptages de fichiers obtenus via find . -name '*.swift' -not -path '*/Tests/*' | wc -l exécuté contre chacun des huit dépôts d’applications privées le 2026-04-27. Les fichiers de tests sont exclus. Le total est cohérent en interne avec la ventilation par application présentée dans le tableau de §The Portfolio. 

  18. Estimation subjective en temps réel, et non une mesure par rapport à un groupe témoin. Le chiffre de 3 à 5x correspond au souvenir de l’auteur des comparaisons de temps de mise en œuvre entre les fonctionnalités assistées par agent en 2026 et les fonctionnalités équivalentes livrées en solo dans les mêmes bases de code avant le workflow agentique. À considérer comme une heuristique de ce à quoi s’attendre après la mise en place de MCP et des hooks, et non comme un benchmark. 

NORMAL ios-agent-development.md EOF