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

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

# Créer des applications iOS avec des agents IA

words: 12324 read_time: 62m updated: 2026-04-14 23:53
$ less ios-agent-development.md

TL;DR : Trois environnements d’exécution d’agents produisent 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 le xcrun mcpbridge d’Apple avec 20 outils) offrent aux agents un accès structuré aux builds, tests, simulateurs et au débogage. Ce guide couvre de véritables configurations CLAUDE.md, des paramètres de hooks et des évaluations honnêtes de ce qui fonctionne et de ce qui échoue — issus de 8 applications iOS en production totalisant 293 fichiers Swift. Les agents excellent pour les vues SwiftUI, les modèles SwiftData, le refactoring et le diagnostic d’erreurs de build. Ils échouent sur les modifications de .pbxproj, la signature de code et le débogage visuel. Le fossé entre « l’agent écrit du Swift » et « l’agent livre une app iOS » se comble par la configuration, pas par le prompting.

Je développe 8 applications iOS avec des agents de programmation IA. Pas des prototypes — des applications disponibles sur l’App Store, avec des intégrations HealthKit, des shaders Metal, de la physique SpriteKit, 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 soit été écrite par un agent et revue par moi, soit écrite par moi et refactorisée par un agent. Selon mon estimation, le ratio est d’environ 85/15 en faveur de l’agent.

Ce guide est la référence que j’aurais voulu avoir en commençant. Il couvre l’ensemble de la pile : quel environnement d’exécution d’agent utiliser, comment configurer les serveurs MCP pour un accès structuré au build, quoi mettre dans votre CLAUDE.md, quels hooks empêchent l’agent de détruire votre projet Xcode et — point crucial — où les agents échouent et où vous devez reprendre la main.

Points clés

Pour les développeurs iOS découvrant les agents IA :

  • Commencez avec Claude Code CLI + XcodeBuildMCP. C’est l’environnement d’exécution le plus mature avec la couverture d’outils MCP la plus étendue. 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 vers .pbxproj et .xcodeproj/ vous épargnera des heures de récupération.
  • Votre CLAUDE.md est le document d’intégration de l’agent. Chaque heure investie dans CLAUDE.md en économise dix à corriger les erreurs de l’agent.

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

  • MCP transforme la boucle de build iOS. Avant MCP, les agents écrivaient du Swift sans pouvoir vérifier la compilation. 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 environnements d’exécution répondent à des besoins distincts. Claude Code CLI pour les sessions agentiques approfondies, Codex CLI pour le travail par lots headless, les agents natifs de Xcode 26.3 pour les corrections rapides en ligne sans quitter l’IDE.
  • L’infrastructure de hooks est transférable. Vos formateurs PostToolUse, bloqueurs PreToolUse et hooks d’exécution de tests existants fonctionnent de manière identique pour les projets iOS moyennant quelques ajustements de chemins.

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

  • L’efficacité des agents dépend de la documentation du projet, pas de sa taille. Une application de 63 fichiers avec un CLAUDE.md détaillé produit de meilleurs résultats qu’une application de 14 fichiers sans documentation.
  • La frontière .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 de fichiers aux cibles Xcode.
  • Évaluation ROI : les agents gèrent 70 à 80 % du travail d’implémentation. Les 20 à 30 % restants — finitions visuelles, signature, optimisation des performances, soumission à l’App Store — nécessitent un jugement humain.

Choisissez votre parcours

Ce dont vous avez besoin Direction
Configurer MCP pour la première fois Configuration MCP : le guide complet — installer les deux serveurs, vérifier, configurer les agents
Rédiger un CLAUDE.md pour votre projet iOS Modèles CLAUDE.md pour projets iOS — exemples réels tirés de 8 applications
Comparer les trois environnements d’exécution Trois environnements d’exécution d’agents pour iOS — Claude Code vs. Codex vs. Xcode natif
Comprendre ce que les agents peuvent et ne peuvent pas faire Ce que les agents font bien et Ce que les agents font mal
Configurer les hooks pour le développement iOS Hooks pour le développement iOS — formatage automatique, protection .pbxproj, exécuteurs de tests
Référence complète (cette page) Poursuivez la lecture — de la configuration aux modèles avancés

Comment utiliser ce guide

Ceci 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
Débutant iOS + agents PrérequisConfiguration MCPVotre première session d’agent Modèles CLAUDE.md, Ce qui fonctionne / ne fonctionne pas
Développeur iOS, débutant en agents Trois environnements d’exécutionConfiguration MCPCLAUDE.md Hooks, Modèles d’architecture
Utilisateur d’agents, débutant en iOS Modèles d’architectureCe que les agents font malCLAUDE.md Contexte par framework, Workflows avancés
Expérimenté dans les deux Workflows avancésHooksModèles multi-plateformes Matrice de comparaison des environnements, Le portfolio

Table des matières

  1. Le portfolio : 8 applications, 293 fichiers
  2. Prérequis
  3. Trois environnements d’exécution d’agents pour iOS
  4. Configuration MCP : le guide complet
  5. Modèles CLAUDE.md pour projets iOS
  6. Votre première session d’agent
  7. Ce que les agents font bien en iOS
  8. Ce que les agents font mal en iOS
  9. Hooks pour le développement iOS
  10. Modèles d’architecture compatibles avec les agents
  11. Contexte par framework
  12. Modèles multi-plateformes
  13. Workflows avancés
  14. Études de cas réelles
  15. Cycle de vie d’un projet avec agents
  16. Configuration des définitions d’agents
  17. Modèles de test pour iOS assisté par agents
  18. Gestion de la fenêtre de contexte pour les projets iOS
  19. Dépannage
  20. Erreurs courantes des agents en iOS
  21. L’évaluation honnête
  22. FAQ
  23. Carte de référence rapide
  24. Références

Ressources associées

Sujet Ressource
Configuration MCP pour Xcode (article de blog plus court) Deux serveurs MCP ont transformé Claude Code en système de build iOS
Référence complète de Claude Code CLI Claude Code CLI : le guide complet
Référence Codex CLI Codex CLI : le guide complet
Exploration approfondie du système de hooks Anatomie d’une griffe : 84 hooks comme couche d’orchestration
Modèles d’architecture d’agents Guide d’architecture d’agents

Le portfolio : 8 apps, 293 fichiers

Avant de plonger dans la configuration, voici la base sur laquelle repose ce guide. Il ne s’agit pas de projets jouets — ils couvrent cinq frameworks Apple, trois plateformes, et tout le spectre de complexité iOS, d’un tracker d’entraînement de 14 fichiers à un minuteur de méditation multi-plateforme de 63 fichiers.

App Stack Fichiers Complexité
Banana List SwiftUI + SwiftData + iCloud Drive sync + serveur MCP pour Claude Desktop 53 CRUD complet, synchronisation iCloud, serveur MCP personnalisé qui expose les données de l’app à Claude Desktop
Ace Citizenship App d’étude SwiftUI + backend FastAPI 26 Client-serveur, intégration REST API, moteur de quiz
TappyColor Jeu de correspondance 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, runtime étendu Watch, navigation focus TV, synchronisation de sessions iCloud
amp97 Shaders Metal + visualisation audio 41 Pipeline de rendu Metal personnalisé, analyse audio, calcul GPU en temps réel
Reps SwiftUI + SwiftData suivi d’entraînement 14 App minimale viable, patterns SwiftData propres
Water SwiftUI + SwiftData + Metal + HealthKit suivi d’hydratation 34 Simulation de fluide Metal, journalisation HealthKit de l’apport en eau, widget
Starfield Destroyer SpriteKit + Metal space shooter 32 99 niveaux, 8 vaisseaux, classements Game Center, post-traitement Metal

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


Prérequis

Avant de configurer un runtime d’agent pour le développement iOS :

Requis : - macOS 15+ (Sequoia) ou macOS Tahoe - Xcode 26.3+ installé et configuré (accord de licence accepté, plateformes téléchargées) - 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 le respect des conventions de style - Familiarité avec le terminal — les trois runtimes fonctionnent depuis ou s’intègrent avec la ligne de commande

Vérifiez votre installation Xcode :

# Check Xcode version
xcodebuild -version
# Expected: Xcode 26.3 or later

# 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 renvoie « 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 — il vous faut l’application Xcode.app complète.


Trois runtimes d’agents pour iOS

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

1. Claude Code CLI

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

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

Configuration :

# 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

Idéal pour : les sessions d’implémentation en profondeur — créer de nouvelles fonctionnalités, refactorer à travers plusieurs fichiers, déboguer des problèmes complexes, exécuter des boucles build-test-fix de manière autonome. La fenêtre de contexte d‘1M de tokens de Claude Code (avec Opus 4.6) signifie que l’agent peut garder en mémoire de travail la plupart des projets iOS de petite à moyenne taille — d’après mon expérience, jusqu’à environ 50 fichiers selon la taille des fichiers.

Session type :

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 ni de coller la sortie d’erreurs. La boucle build-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 les modèles OpenAI (GPT-4o, o3) et possède un modèle de permissions différent.

Intégration MCP : Codex prend en charge MCP via la commande codex mcp add. L’Xcode MCP 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 où vous souhaitez un second avis d’une famille de modèles différente. Le mode sandbox de Codex exécute le code dans des environnements isolés, ce qui est utile pour les opérations destructives comme les exécutions de suites de tests qui modifient l’état.

Différences clés avec Claude Code : - Utilise les modèles OpenAI au lieu des modèles Claude - Tailles de fenêtre de contexte et économie de tokens différentes - Modèle de permissions orienté sandbox (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 conditionnel if

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

Utilisez Codex quand vous voulez de la diversité de modèles — avoir un second agent qui révise le code écrit par le premier détecte des classes d’erreurs différentes. Le workflow collab (Claude construit, Codex révise) est efficace pour iOS car les patterns SwiftUI qui semblent corrects pour une famille de modèles peuvent présenter des problèmes subtils qu’une autre détecte. Les shaders Metal et les patterns de concurrence bénéficient particulièrement de la révision bi-modèle.

3. Agents natifs Xcode 26.3

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

Configuration :

  1. Ouvrez Xcode 26.3+
  2. Naviguez vers Settings > Intelligence
  3. Ajoutez un nouveau fournisseur :
  4. Pour Claude : sélectionnez « Claude Agent », entrez votre clé Anthropic API
  5. Pour Codex : sélectionnez « Codex », entrez votre clé OpenAI API
  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 projet d’Xcode — fichiers ouverts, cibles de build, configuration de schéma — sans pont MCP.

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

Quand utiliser les agents natifs Xcode :

Pour des modifications rapides et ciblées où basculer vers le terminal représente une surcharge. « Ajouter une propriété calculée à ce modèle. » « Écrire un test unitaire pour cette fonction. » « Refactorer cette vue pour utiliser @Observable. » Des tâches qui touchent un ou deux fichiers et ne nécessitent pas de cycle build-test.

Pour tout ce qui nécessite de compiler, tester, refactorer sur plusieurs fichiers ou corriger des erreurs de manière autonome, utilisez un agent CLI avec MCP.

Matrice de comparaison des runtimes

Capacité Claude Code CLI Codex CLI Xcode 26.3 natif
Support MCP Complet (79 outils) Complet (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
Build-test-fix autonome Oui (via MCP) Oui (via MCP) Partiel (en ligne uniquement)
Délégation de sous-agents Oui (jusqu’à 10 en parallèle) Non Non
Fenêtre de contexte 1M tokens (Opus 4.6) Variable selon le modèle Variable selon le fournisseur
Opérations multi-fichiers Accès complet à la codebase Accès complet à la codebase Fichier / sélection en cours
Protection .pbxproj Via hooks Manuelle N/A (utilise Xcode nativement)
Formatage à la sauvegarde Via hooks PostToolUse Outillage externe Paramètres Xcode
Fonctionnement hors ligne Non Non Non
Modèle de coût Utilisation Anthropic API Utilisation OpenAI API Utilisation 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 révision et les opérations batch. Les trois se complètent plutôt qu’ils ne se concurrencent.


Configuration MCP : le guide complet

MCP (Model Context Protocol) transforme un agent qui « écrit du Swift en espérant que vous le compilez » en un agent qui « écrit du Swift, le compile, lit les erreurs structurées et les corrige ». Cette section va plus loin que le billet de blog — elle couvre 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 headless

XcodeBuildMCP encapsule xcodebuild, xcrun simctl et LLDB en 59 outils MCP structurés. Il fonctionne sans qu’Xcode soit lancé — l’ensemble du cycle compilation-test-débogage 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

Le flag -s user rend le serveur disponible globalement dans tous vos projets. Omettez-le pour une installation limitée au projet (utile si vous ne souhaitez MCP que dans vos projets iOS, pas dans vos projets web).

La variable d’environnement -e XCODEBUILDMCP_SENTRY_DISABLED=true désactive la télémétrie de rapports de crash. XcodeBuildMCP inclut Sentry par défaut, qui envoie des données d’erreur comprenant 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 Fonctions
Découverte de projet discover_projs, list_schemes, list_targets Trouve les fichiers .xcodeproj/.xcworkspace, liste les schemes et targets 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 par méthode (réussite/échec)
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 UI snapshot_ui, screenshot, tap, swipe, type_text Interaction automatisée et capture visuelle
Scaffolding de projet create_project, add_file, add_package Crée des projets et ajoute des dépendances

Les outils les plus importants au quotidien :

  1. build_sim — Vous l’appellerez des centaines de fois. Il retourne des JSON avec les erreurs classées par fichier, ligne et sévérité. L’agent lit l’erreur, navigue vers le 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 simplement « les tests ont échoué ».

  3. list_sims + boot_sim — Gestion du simulateur sans mémoriser les flags de xcrun simctl. L’agent découvre les runtimes disponibles et choisit un appareil approprié.

  4. discover_projs + list_schemes — Introspection du projet. L’agent n’a pas besoin de deviner le nom de votre scheme 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 parcourir le code pas à pas sans que vous ouvriez 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 auquel aucun outil CLI ne peut accéder.

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 restera en attente. XcodeBuildMCP n’a pas cette limitation.

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

Catégorie Outils Fonctions
Opérations sur les fichiers XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep Lecture/écriture de fichiers dans le contexte du projet Xcode
Compilation et tests BuildProject, GetBuildLog, RunAllTests, RunSomeTests Compilation et tests avec le système de build interne d’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 exclusifs à Apple MCP (non disponibles dans XcodeBuildMCP) :

  1. DocumentationSearch — Recherche dans la documentation développeur d’Apple, y compris les sessions WWDC. Plus rapide et plus fiable qu’une recherche web pour les questions relatives aux API Apple. Demandez « HKQuantityType(.dietaryWater) est-il valide ? » et obtenez une réponse définitive à la source.

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

  3. RenderPreview — Effectue le rendu des aperçus SwiftUI en mode headless. L’agent peut vérifier qu’une vue s’affiche sans erreurs, bien qu’il ne puisse pas évaluer le rendu visuel (le résultat 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 des problèmes comme les variables inutilisées, les cycles de rétention potentiels et les avertissements de dépréciation que le système de build ne signale pas.

Pourquoi les deux serveurs

Ils se chevauchent sur la compilation 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 compilation-test-débogage. Il fonctionne sans qu’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 compilation principal.

Utilisez Apple Xcode MCP pour : la recherche dans la documentation, la vérification via Swift REPL, le rendu des aperçus SwiftUI et les diagnostics en temps réel. Gardez Xcode ouvert durant les sessions nécessitant ces fonctionnalité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 la compilation et les tests car il est plus rapide (pas de surcharge liée au processus Xcode) et plus fiable (pas de dépendance XPC).

Vérification

Après avoir installé les deux serveurs, vérifiez qu’ils sont bien 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 : vérifiez que Node.js est installé (node --version). La commande npx nécessite Node.js 18+.
  2. Apple Xcode MCP ne se connecte pas : vérifiez qu’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 cours 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 risque de revenir à l’exécution de xcodebuild via Bash (sortie non structurée, gaspillage de tokens de contexte) ou d’utiliser la 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 plutôt que les 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)
- **Débogage** : `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Documentation Apple** : `DocumentationSearch` (PAS WebSearch pour les API Apple)
- **Vérification Swift** : `ExecuteSnippet` (PAS `swift` via Bash)
- **Previews** : `RenderPreview` pour la vérification headless de SwiftUI

MCP renvoie des données JSON structurées. Bash renvoie du texte non structuré.
Des données structurées signifient moins de tokens consommés et un meilleur diagnostic des erreurs.

Cette directive garantit que l’agent utilise d’abord les outils MCP. Sans elle, vous observerez l’agent construire de longues commandes xcodebuild via Bash, consommant des milliers de tokens de contexte pour analyser la sortie, et parfois identifiant mal 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 un nouveau collaborateur qui a lu la documentation d’architecture et un autre qui avance à l’aveugle.

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

Les sections essentielles

Chaque CLAUDE.md iOS nécessite 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 with @Observable pattern, companion Watch and TV apps
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0

Pourquoi c’est important : 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 est essentiel pour les entitlements et la configuration HealthKit. La version de Swift détermine le modèle de concurrence (async/await vs. completion handlers, concurrence stricte vs. souple).

2. Structure des fichiers avec annotations de rôle

## File Structure

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


Les commentaires en ligne après chaque nom de fichier ne sont pas décoratifs. Ils constituent la documentation à plus fort effet de levier que vous puissiez rédiger. Lorsque l’agent doit décider où ajouter une nouvelle fonctionnalité, ces annotations le dirigent vers le bon fichier du premier coup, au lieu de devoir lire chaque fichier pour comprendre l’organisation du projet.

Anti-pattern : lister les fichiers sans annotations. TimerManager.swift n’indique rien à l’agent sur la gestion d’état, d’UI ou des deux. TimerManager.swift # Timer state, logic, and repeat handling lui dit exactement ce qui y a sa place et ce qui n’y appartient pas.

3. Commandes de build et de test

## Build & Test

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

Run tests:

xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test

Run tvOS tests:

xcodebuild -scheme ReturnTV -destination 'platform=tvOS Simulator,name=Apple TV' test

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

Incluez les commandes brutes même si l'agent devrait privilégier MCP. Ces commandes servent de documentation de secours et rendent explicites les noms de schemes et les destinations.

#### 4. Patterns clés et règles

```markdown

## Key Patterns

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

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

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

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

## Rules

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

Les interdictions explicites sont plus efficaces que les attentes implicites. L’agent respecte les contraintes négatives de manière plus fiable que les suggestions positives, car elles sont binaires (le faire / ne pas le faire) plutôt qu’heuristiques (préférer 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 applications HealthKit :

## HealthKit Configuration

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

Pour les applications SwiftData :

## SwiftData Models

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

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

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

Pour les applications SpriteKit :

## SpriteKit Scene Hierarchy

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

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

Pour les applications Metal :

## Metal Pipeline

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

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

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

CLAUDE.md réel : Banana List (SwiftUI + SwiftData + iCloud + serveur MCP)

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

# Banana List - Grocery List App

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

## Core Features

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

## 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` (nullification à la suppression)

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

Patterns de requêtes

  • 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 récupération (limitations des prédicats SwiftData)

Compilation et tests

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.

Patterns essentiels

Observable + SwiftData

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

Synchronisation iCloud

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

Architecture du serveur MCP

  • Fonctionne 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 des fichiers .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 les 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 (application SwiftData minimale — 14 fichiers)

Pour les petits projets, le CLAUDE.md peut rester concis. Voici le pattern utilisé pour Reps, un suivi d'entraînement de 14 fichiers. Remarquez comment même un CLAUDE.md court couvre les six sections essentielles :

```markdown
# 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. La rédaction prend 10 minutes et évite des heures de confusion à l'agent.

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

Les projets de jeux 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 :

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

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 changer 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
- Ajouter de nouveaux ennemis en créant une sous-classe de EnemyShip, jamais en le modifiant directement
- Pooling de projectiles : recycler via removeFromParent() + réajout, ne jamais allouer de nouveau
- Game Center : toujours vérifier isAuthenticated avant de soumettre les scores

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

Les projets Metal nécessitent le plus de contexte spécifique au framework, car les agents ne peuvent pas vérifier le rendu visuel :

# amp97 - Audio Visualizer

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

## Architecture

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

## File Structure

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

## Metal Pipeline

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

Render Pipeline

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

Buffer Management

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

Rules

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

Le niveau de détail approprié dépend du nombre de fichiers et de la complexité des frameworks :

| Taille du projet | Profondeur du CLAUDE.md | Exemple |
|-------------|----------------|---------|
| **Petit (< 20 fichiers)** | Identité + liste de fichiers + règles | Reps (14 fichiers) : patterns SwiftData de base, commandes de build, interdictions |
| **Moyen (20-40 fichiers)** | + Contexte framework + patterns clés | TappyColor (30 fichiers) : hiérarchie de scènes SpriteKit, catégories de physique, boucle de jeu |
| **Grand (40+ fichiers)** | + Diagrammes d'architecture + cartographie des relations + info multi-cibles | Return (63 fichiers) : architecture multi-plateforme, diagramme de synchronisation des sessions, différences par plateforme |
| **Spécialisé (Metal/GPU)** | + Diagrammes de pipeline + définitions de types partagés + organisation des buffers | amp97 (41 fichiers) : étapes du pipeline de rendu, struct des uniforms, gestion des buffers |

Le coût d'une documentation trop détaillée est quasi nul (l'agent ignore ce dont il n'a pas besoin). Le coût d'une documentation insuffisante est élevé (l'agent invente des patterns qui entrent en conflit avec votre base de code).

### Checklist du 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 de Swift et pattern d'architecture nommés
- [ ] Structure des fichiers avec annotations de rôle en ligne
- [ ] Commande de build avec le bon scheme et la bonne destination
- [ ] Commande de test avec le bon scheme et la bonne destination
- [ ] 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 de modifier .pbxproj
- [ ] Contexte spécifique au framework (permissions HealthKit, relations SwiftData, hiérarchie SpriteKit, pipeline Metal)
- [ ] Guards de disponibilité par plateforme documentés (#if canImport, #if os)
- [ ] Singletons clés et patterns partagés documentés
- [ ] Limitations connues ou pièges notés

---

## Votre première session avec un agent

Avec MCP configuré et un CLAUDE.md dans votre projet, voici le déroulement d'une première session efficace. L'exemple utilise Claude Code CLI, mais le workflow s'applique à tout environnement d'exécution.

### Étape 1 : Vérifier que l'agent peut voir votre projet

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

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

    This is Return, a zen meditation timer for iOS 26+, watchOS, and tvOS.
    Available schemes: Return, ReturnWatch, ReturnTV, ReturnTests.
    Primary scheme for iOS: Return.
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 répertoire que `.xcodeproj` ou `Package.swift`).

### Étape 2 : Lancer un build de vérification

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

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

    Build succeeded. 63 source files compiled.
    2 warnings:
    - HomeView.swift:132 — UIScreen.main deprecated in iOS 26.0
    - LogWaterIntent.swift:61 — Result of try? is unused
    0 errors.
### Étape 3 : Exécuter les tests

You: Run all tests and report pass/fail.

Claude: [calls test_sim]

    12 tests executed:
    ✓ TimerManagerTests (5/5 passed)
    ✓ SettingsTests (4/4 passed)
    ✓ ConstantsTests (3/3 passed)
    All tests passed.
### Étape 4 : Implémenter une fonctionnalité

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

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

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

    Note: You'll need to add rain_ambient.wav to the project
    and add the new Theme.swift changes to the Xcode target manually
    (I did not modify .pbxproj).
La note de l'agent concernant la non-modification de .pbxproj est le résultat direct des règles définies dans le 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 en iOS

Voici les tâches pour lesquelles les agents produisent systématiquement un résultat correct, prêt pour la production, avec un minimum de relecture humaine.

### Vues et modificateurs SwiftUI

Les agents possèdent une reconnaissance de motifs approfondie pour la syntaxe déclarative de SwiftUI. La composition de vues, les chaînes de modificateurs, les liaisons d'état et la mise en page  tout cela correspond bien aux données d'entraînement de l'agent, car la surface d'API de SwiftUI est bien documentée et les 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 les motifs de mise en page (VStack vers LazyVGrid, List vers ScrollView)
- Implémenter des liaisons de formulaire `@Bindable` vers des modèles SwiftData
- Créer 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. « Create a SettingsView that matches the existing pattern in 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 le 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`
- Planifier les migrations entre les versions de schéma
- Créer des données de prévisualisation et des fixtures de test

**Là où les agents ont besoin de guidance :**
- Les 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)
- La 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 les agents sont systématiquement de haute qualité pour les projets iOS. L'agent comprend les motifs XCTest, les méthodes de test asynchrones 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 de test XCTest bien structurés avec `setUp()` et `tearDown()`, des assertions appropriées et une gestion asynchrone pour les tests basés sur des minuteries.

### Refactoring et application de motifs

Les agents excellent dans le refactoring mécanique : extraction de vues en composants, conversion de `ObservableObject` vers `@Observable`, migration de `NavigationView` vers `NavigationStack`, et application de motifs cohérents sur 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 parcourt méthodiquement chaque fichier, applique la transformation correctement et préserve les fonctionnalités existantes. C'est un travail à fort levier  un refactoring qui prendrait une heure d'édition manuelle s'accomplit en quelques minutes avec une précision quasi parfaite.

### Diagnostic des erreurs de build via MCP

Avec la sortie structurée de MCP, les agents diagnostiquent les erreurs de build plus rapidement que la plupart des développeurs. L'agent lit le JSON d'erreurs, 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 macros (l'agent ne peut pas voir la sortie des macros étendues)

### 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 structurés MCP.

---

## Ce que les agents font mal en iOS

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

### Modifications de fichiers .pbxproj — JAMAIS

C'est la règle la plus importante du développement iOS avec agents. Le fichier `.pbxproj` est la configuration de projet Xcode  un fichier texte structuré avec des références UUID, des listes de phases de build et des appartenances 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 propriétaire (ni JSON, ni YAML, ni XML) avec une signification positionnelle
- Chaque entrée est référencée croisée par UUID  ajouter un fichier nécessite la mise à jour cohérente de 3 à 5 sections différentes
- Un seul caractère mal placé corrompt l'intégralité du fichier projet
- La résolution de conflits de merge par Xcode pour .pbxproj est déjà fragile — les modifications par un agent aggravent la situation

**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 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](#hooks-for-ios-development))

**Le workflow :** L'agent crée les fichiers Swift. Vous les ajoutez manuellement au projet Xcode (glisser dans Xcode, ou Fichier > Ajouter des fichiers). Cela prend 5 secondes par fichier et évite des heures de récupération.

**Pour les projets Swift Package Manager :** Cette limitation est moins contraignante. `Package.swift` est un fichier Swift standard que les agents peuvent modifier de manière fiable. Si votre projet utilise exclusivement SPM (pas de .xcodeproj), l'agent peut gérer l'intégralité de la structure du projet.

### Modifications complexes d'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 pertinente. Ce sont des fichiers XML avec des UUID générés automatiquement, des références de contraintes et des connexions d'outlets conçus pour l'édition visuelle, pas pour l'édition textuelle.

**La solution :** Utilisez exclusivement SwiftUI pour les nouvelles vues. Si votre projet contient des fichiers Interface Builder hérités, laissez-les en l'état et construisez les nouvelles interfaces en SwiftUI.

### Optimisation des performances

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

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

** cela se manifeste :**
- Optimisation des shaders Metal (l'agent écrit du Metal valide mais ne peut pas mesurer le temps de frame GPU)
- Complexité du body des vues SwiftUI (l'agent crée des vues profondément imbriquées qui causent un surcoût de redessin)
- Optimisation des requêtes Core Data / SwiftData (l'agent écrit des requêtes correctes qui peuvent être lentes sur de grands jeux de données)

**La solution :** 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.

### Signature de code 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 sur l'App Store sont fondamentalement des workflows opérés par l'humain, impliquant le portail Apple Developer, Trousseau d'accès et l'interface de signature d'Xcode.

**Ce que l'agent voit :** « 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 l'identifiant de bundle correspond à l'App ID, ou si votre fichier d'entitlements est correct.

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

### Débogage complexe des shaders Metal

Les agents écrivent du Metal Shading Language (MSL) syntaxiquement correct mais ne peuvent pas vérifier le rendu visuel 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 et fragment shaders à partir de descriptions
- Configurer le pipeline de rendu Metal en Swift
- Créer des compute shaders pour des opérations parallèles sur les données
- Corriger les erreurs de compilation dans les fichiers `.metal`

**Ce que les agents ne peuvent pas faire avec Metal :**
- Vérifier la justesse visuelle du rendu des shaders
- Déboguer les performances GPU (temps de frame, occupation, bande passante mémoire)
- Diagnostiquer des artefacts visuels (banding, problèmes de précision, espace colorimétrique incorrect)
- Tester sur différentes architectures GPU (différences de comportement entre séries A et séries M)

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

### Vérification visuelle de la mise en page

Les agents ne peuvent pas voir l'interface de votre application. Ils écrivent le code de mise en page SwiftUI et peuvent vérifier qu'il compile, mais ils ne peuvent pas déterminer si l'écran résultant est visuellement correct. Une vue décalée de 10 pixels, utilisant la mauvaise graisse de police ou présentant des éléments qui se chevauchent ne produit aucune erreur de build et passe tous les tests logiques.

**La solution :** Vérifiez visuellement les modifications d'interface. Utilisez les SwiftUI Previews dans Xcode (ou `RenderPreview` via Apple MCP pour le rendu headless) pour valider la mise en page. Envisagez les tests de snapshot avec des bibliothèques comme swift-snapshot-testing pour la détection automatisée de 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 flux de travail de l'agent. Ils constituent le mécanisme d'application  la différence entre « veuillez ne pas modifier .pbxproj » (une suggestion que l'agent peut ignorer) et « vous ne pouvez pas modifier .pbxproj » (un blocage strict).

Pour en savoir plus sur le système de hooks, consultez le [guide des hooks Claude Code](/blog/claude-code-hooks-tutorial). Cette section couvre les patterns de hooks spécifiques à iOS.

### PreToolUse : bloquer les écritures dans .pbxproj

Le hook le plus important de tout projet iOS. Il empêche l'agent d'écrire dans les fichiers `.pbxproj`, les répertoires `.xcodeproj/` et les autres fichiers gérés par Xcode :

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

Placez ceci 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 pattern, 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 touché par l’agent 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 d’un 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 du linter de bloquer l’agent. Si vous souhaitez que les violations de lint bloquent l’exécution, supprimez-le.

PostToolUse : build automatique après les modifications

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

Attention : cette approche est coûteuse. Chaque modification de fichier déclenche un build. Utilisez-la avec parcimonie — elle s’avère surtout utile lors des sessions de débogage où vous souhaitez un retour de build immédiat. Pour le développement courant, laissez l’agent déclencher les builds manuellement via MCP lorsqu’il est prêt.

PreToolUse : bloquer les modifications des entitlements

Protégez votre fichier d’entitlements contre les 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 .claude/settings.json complet que j’utilise dans 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 touché par l’agent est automatiquement formaté (formatage PostToolUse)


Patrons d’architecture compatibles avec les agents

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

@Observable (jamais ObservableObject)

Les projets ciblant iOS 26+ doivent utiliser exclusivement @Observable. C’est à la fois le patron moderne et celui qui convient le mieux 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 convient aux agents : Le patron 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 bogues avec lui car il comporte moins d’éléments mobiles.

Documentez-le dans CLAUDE.md : Même avec iOS 26 comme cible, les agents reviennent parfois aux patrons ObservableObject issus de leurs données d’entraînement. Une interdiction explicite empêche ce comportement.

// 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 patron de navigation à utiliser pour du nouveau code. Le patron typé navigationDestination(for:) empêche l’agent de créer des liens de navigation incorrects.

SwiftData pour la persistance

Les modèles SwiftData représentent le patron 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 liaisons de formulaires : @Bindable var item: GroceryItem 3. Utilisez @Query dans les vues pour des 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

Ciblez la concurrence stricte de 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 pour les agents en matière de concurrence : - Marquez tous les modèles de vue @MainActor (évite les avertissements de course de données) - Utilisez async/await pour tout travail asynchrone (pas de gestionnaires de rappel) - Rendez les types valeur Sendable pour les transferts inter-acteurs - Utilisez Task { } dans les vues pour l’initialisation asynchrone - N’utilisez nonisolated que lorsqu’un besoin de performance a été mesuré

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 indications 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 section et les conteneurs de cartes. Les barres de navigation adoptent automatiquement le matériau glass sous iOS 26. Ne recréez pas manuellement les effets glass avec des matériaux personnalisés — utilisez le modificateur système. »


Contexte spécifique aux frameworks

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

HealthKit

Applications concernées : Return, Water

HealthKit nécessite une gestion rigoureuse des permissions et des vérifications 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 : - Vérifiez toujours avec HKHealthStore.isHealthDataAvailable() - Ne présumez jamais de l’autorisation — vérifiez à chaque écriture - Utilisez #if canImport(HealthKit) pour le code multi-plateforme (HealthKit indisponible sur tvOS) - Ne stockez jamais de données de santé localement au-delà de ce que HealthKit fournit - Incluez NSHealthShareUsageDescription et NSHealthUpdateUsageDescription dans Info.plist

SpriteKit

Applications concernées : TappyColor, Starfield Destroyer

Le modèle de graphe de scène de SpriteKit nécessite des indications 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 groupes SKAction - Mise en place de corps physiques et détection de contact - Implémentation de machines à états de jeu - Construction de surcouches d’interface (HUD)

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

Metal

Applications concernées : amp97, Water, Starfield Destroyer

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

## 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 de la structure Uniforms (partagée entre Swift et MSL) - Le patron de configuration du pipeline de rendu - Les indices de buffers et leurs fonctions - Les shaders existants et le rôle de chacun - Les problèmes de précision connus (half vs. float)

Live Activities

Applications concernées : 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

Applications concernées : 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 répertoire spécifique à une plateforme, les modifications sont isolées. Vérifiez toujours dans quel répertoire se trouve un fichier avant de le modifier. »

Gardes 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

Consigne pour les agents : « Utilisez toujours les gardes #if canImport() ou #if os() lorsque vous faites appel à des frameworks spécifiques à une plateforme. Ne présumez jamais qu’un framework est disponible sur toutes les cibles. »

Adaptation de l’interface 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-correction

Le modèle le plus puissant : fournir à l’agent une spécification de fonctionnalité et le laisser itérer à travers des cycles build-test-correction de manière 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 le code, lance le build via MCP, lit les erreurs structurées, les corrige, puis recommence. Une fonctionnalité qui nécessiterait 5 à 10 cycles humains de build-erreur-correction se réalise en une seule boucle autonome.

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

Quand cela échoue : Fonctionnalités ouvertes (« rendez ça joli »), code sensible aux performances, ou tout ce qui nécessite une vérification visuelle.

Délégation par sous-agents 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 séparée, renvoie 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 à double agent (Claude + Codex)

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

  1. Claude Code écrit l’implémentation
  2. Codex CLI la révise dans une passe séparée
# 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 catégories 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 à double agent détecte que la revue simple 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 des buffers Metal Modérée Modérée
Détection de cycles de rétention Forte (Opus) Forte (o3)
Connaissance des dépréciations API Forte (données d’entraînement plus récentes) Modérée
Conditions de concurrence Forte Forte (différents modèles détectés)

La revue à double agent ne vise pas à trouver plus de bugs — elle vise à trouver des bugs différents. Chaque famille de modèles possède 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 flag --dangerously-skip-permissions est nécessaire pour le mode non interactif mais contourne toutes les vérifications de sécurité. Assurez-vous que vos hooks PreToolUse sont en place pour protéger les fichiers .pbxproj.


Études de cas concrets

Les conseils abstraits sont faciles à donner. Voici des scénarios spécifiques issus des 8 applications qui illustrent comment le développement iOS assisté par agents fonctionne en pratique — échecs compris.

Étude de cas 1 : Ajout d’une application TV à Return (Succès)

La tâche : Ajouter une cible tvOS à Return, un minuteur de méditation disposant déjà de versions iOS et watchOS. L’application TV devait gérer la navigation avec la Siri Remote, une interface grand écran et la synchronisation des paramètres avec l’application iOS.

Ce que l’agent a bien fait : - A lu le TimerManager iOS existant et créé un TVTimerManager omettant Live Activities et HealthKit (indisponibles sur tvOS) - A créé des styles de boutons personnalisés pour la navigation au focus avec la Siri Remote (TVCapsuleButtonStyle, TVCircleButtonStyle) - A construit un composant TVStepper remplaçant les sélecteurs rotatifs (inutilisables avec la Siri Remote) par des boutons +/- - A implémenté la synchronisation des paramètres via App Groups (group.com.941apps.Return) - A ajouté des gardes #if os(tvOS) dans tout le code partagé - A compilé et testé 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 scheme existant ou en créer un nouveau - Ajouter manuellement tous les fichiers Swift créés par l’agent à la cible TV - Tester la navigation 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, implémentée en environ 3 heures de travail assisté par agent. L’implémentation manuelle équivalente aurait pris 1 à 2 jours. L’agent a géré environ 80 % du code, je me suis occupé des 20 % nécessitant des interactions avec l’interface Xcode et des tests manuels.

É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 de l’oscilloscope. La visualisation devait pulser en fonction de l’énergie audio.

Ce qui s’est passé : 1. L’agent a écrit une modification valide du shader Metal ajoutant un uniform uEnergy et du tonemapping HDR 2. Le code a compilé sans erreurs 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 et 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’états d’énergie globale était trop complexe et cassait le visualiseur de différentes manières 7. Réversion complète — 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 (compilation réussie) et la sémantique (types corrects), mais ne peut pas vérifier le résultat visuel (rendu correct). Toute modification de shader affectant le comportement visuel nécessite une vérification humaine sur l’appareil.

Ce que j’ai ajouté au CLAUDE.md après cela : « NE PAS tenter de modifications de la machine d’états d’énergie sur le shader de l’oscilloscope sans des tests de coefficients extrêmement minutieux. Une tentative précédente a cassé le visualiseur avec des coefficients 10 fois trop élevés. »

Étude de cas 3 : Migration SwiftData dans Banana List (Succès)

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

Ce que l’agent a fait : 1. A lu les définitions du modèle V1 existant 2. A créé les définitions du modèle V2 avec les nouveaux champs et relations 3. A écrit un GroceryMigrationPlan conforme au protocole SchemaMigrationPlan 4. A implémenté l’étape de migration V1toV2 : ajout de quantity: 1 par défaut et category: nil 5. A mis à jour toutes les vues pour prendre en charge les nouveaux champs 6. A mis à jour SampleData.swift pour les previews 7. A compilé et exécuté les tests via MCP — tous passés 8. A créé des tests unitaires spécifiques à la migration

L’élément clé : L’agent a réussi parce que les migrations SwiftData suivent un modèle de protocole bien défini, largement représenté dans la documentation Apple et les données d’entraînement. Le CLAUDE.md documentait explicitement le modèle V1, ce qui a permis à l’agent de comprendre le point de départ de la migration.

Étude de cas 4 : Synchronisation iCloud des sessions dans Return (Succès avec complexité)

La tâche : Implémenter la journalisation des sessions de méditation entre appareils. Les sessions terminées sur Apple TV ou Mac devaient se synchroniser avec l’iPhone pour l’enregistrement 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 de conflits de fusion (déduplication par UUID) 4. A ajouté SessionHistoryView avec des adaptations spécifiques à chaque plateforme (glisser pour supprimer sur iOS, navigation au focus sur tvOS) 5. A connecté 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 (pas de notification de premier plan pour la synchronisation). L’agent a eu besoin d’une indication précise : « Utiliser NSUbiquitousKeyValueStore.didChangeExternallyNotification pour déclencher la synchronisation lors des changements KV en arrière-plan. » Après cette indication, l’implémentation était correcte.

La leçon : Les agents gèrent bien les architectures multi-plateformes lorsque l’architecture est clairement décrite. Le modèle de synchronisation iCloud n’est pas trivial, mais il suit un pattern documenté par Apple que l’agent a compris. Le cas limite (synchronisation en arrière-plan) a nécessité une connaissance métier humaine car il est peu 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 jeu de tir spatial.

Ce que l’agent a bien fait : - A implémenté GKLocalPlayer.local.authenticateHandler au point d’entrée de l’application - A créé un GameCenterManager avec des méthodes pour la soumission des scores et le signalement des succès - A ajouté la vérification de l’état d’authentification avant toutes les opérations Game Center - A géré élégamment le cas hors ligne (le jeu fonctionne sans Game Center, soumet les données à la reconnexion) - A créé les 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, inaccessible à 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 d’un projet avec les agents

Démarrer un nouveau projet iOS

Le workflow optimal pour démarrer un nouveau projet avec l’assistance d’un agent :

Phase 1 : Configuration humaine (15-30 minutes) 1. Créer le projet Xcode (File > New > Project) 2. Configurer la signature et les capabilities 3. Définir la cible de déploiement et les destinations prises en charge 4. Ajouter les entitlements nécessaires (HealthKit, Game Center, etc.) 5. Créer le 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 patterns documentés 3. L’agent implémente la logique métier dans des classes manager/service 4. L’agent écrit les tests unitaires 5. Boucle compilation-test-correction via MCP (autonome)

Phase 3 : Intégration humaine (30-60 minutes) 1. Ajouter les fichiers créés par l’agent aux cibles Xcode 2. Vérifier la signature et les entitlements 3. Tester sur un appareil physique 4. Examiner la mise en page et l’expérience utilisateur 5. Soumettre sur App Store Connect

Maintenir un projet existant

Pour le développement continu sur des 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 croît proportionnellement à la fidélité de votre CLAUDE.md par rapport à l’état actuel du projet. Mettez à jour votre CLAUDE.md lorsque vous ajoutez des fonctionnalités significatives, modifiez des patterns architecturaux ou introduisez de nouveaux frameworks.

Quand impliquer l’agent et quand s’en passer

Tâche Agent ? Pourquoi
Nouvelle vue SwiftUI Oui Les agents excellent en UI déclarative
Modifications de modèle SwiftData Oui Bien défini, testable
Tests unitaires Oui Mécanique, basé sur des patterns
Refactoring Oui Systématique, multi-fichiers
Diagnostic d’erreurs de compilation Oui (via MCP) Boucle de rétroaction structurée
Nouvelle cible Xcode Non Nécessite l’interface Xcode, modifications du .pbxproj
Signature et provisioning Non Portail web, inaccessible à l’agent
Finitions visuelles Non Nécessite un jugement esthétique humain
Ajustement de shaders Metal Non Nécessite des tests GPU sur appareil
Soumission App Store Non Portail et Xcode Organizer
Profilage de performances Non Nécessite Instruments
Audit d’accessibilité Partiel L’agent peut ajouter des labels, l’humain vérifie VoiceOver

Configuration des définitions d’agents

Si vous utilisez le système de définition d’agents 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.


Patterns de test pour le développement iOS assisté par agents

Les agents rédigent d’excellents tests unitaires lorsqu’ils reçoivent des consignes claires. Voici les patterns 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`

Rédiger 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 pattern à suivre. 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.

Ce type de prompt produit des tests génériques et superficiels qui manquent les cas limites et ne suivent pas nécessairement les patterns de votre projet.

Patterns de tests asynchrones

Pour tester du code basé sur des timers et du code 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)
    }
}

Points clés à rappeler aux agents : - @MainActor sur les méthodes de test qui testent des classes @MainActor - async throws pour les tests utilisant Task.sleep ou des opérations asynchrones - Une tolérance dans les assertions temporelles (1,1 seconde, pas exactement 1,0) - Des méthodes setUp() / tearDown() propres pour l’isolation des tests

Tests par snapshots

Pour la détection de 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 snapshots, mais ne peuvent pas examiner les images de référence. Vous vérifiez les snapshots initiaux, puis les tests de l’agent détectent les régressions visuelles lors des modifications ultérieures.


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 présentent 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 — largement 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 de structure de fichiers), puis consulte les fichiers spécifiques au besoin. C’est pourquoi les annotations de fichiers dans CLAUDE.md sont essentielles : elles guident l’agent vers les bons fichiers sans tout lire.

Stratégies pour les grands projets

  1. Annotations de fichiers détaillées dans CLAUDE.md — L’agent lit la carte des fichiers et navigue directement vers les fichiers pertinents
  2. Délégation aux sous-agents — Déléguez l’exploration et la recherche aux 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 les fonctionnalités sans rapport plutôt que d’étendre 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 convaincants en faveur de MCP : les réponses structurées en JSON consomment bien moins de tokens que la sortie brute de xcodebuild.

Scénario Tokens Bash brut Tokens MCP Économie
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 économise entre 30 000 et 150 000 tokens par rapport à xcodebuild brut — des tokens qui restent disponibles pour le raisonnement sur le code.


Dépannage

« build_sim failed — scheme not found »

L’agent devine le nom du scheme. Solution :

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

Vous pouvez aussi ajouter explicitement le nom du scheme dans votre CLAUDE.md :

## Build
Schéma principal : `Return` (iOS)
Schéma Watch : `ReturnWatch` (watchOS)
Schéma TV : `ReturnTV` (tvOS)

« xcrun mcpbridge — command not found »

Xcode 26.3 ou version ultérieure est requis. 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 utilise xcodebuild via Bash au lieu de MCP »

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

  1. Ajoutez des directives explicites dans CLAUDE.md (voir Apprendre à l’agent à utiliser MCP)
  2. Formulez 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 ressemblant à des erreurs (fréquent avec les avertissements de dépréciation), l’agent peut mal interpréter le résultat. Vérifiez le champ de statut réel dans la réponse MCP.

« Le simulateur se bloque au démarrage »

Arrêtez 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 tenté de modifier .pbxproj malgré les règles de CLAUDE.md »

Les règles de CLAUDE.md sont des suggestions. Les hooks sont des mécanismes d’application. Sans le hook PreToolUse bloquant les écritures sur .pbxproj, l’agent finira par tenter la modification. 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 faites pas ça ». Les hooks disent « vous ne pouvez pas ».


FAQ

Quel runtime d’agent choisir pour commencer ?

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

Ai-je besoin des deux serveurs MCP ?

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

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

XcodeBuildMCP inclut un outil create_project qui génère la structure de nouveaux projets Xcode. Toutefois, pour les applications en production, je recommande de créer le projet dans Xcode (pour configurer correctement la signature, les capacités et les cibles) puis d’utiliser les agents pour toute l’implémentation du code. Les 5 minutes passées dans l’assistant de création de projet Xcode vous épargnent des heures de problèmes de configuration générée 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 correctement. La limitation concerne la gestion des dépendances via .xcodeproj (l’interface de résolution de paquets de Xcode) — celle-ci est gérée par Xcode et ne devrait pas être modifiée par un agent.

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

Non. La soumission sur 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 des outils en ligne de commande d’une manière exploitable par les agents. Les agents gèrent tout jusqu’à l’archive — implémentation, tests, correction de bugs et documentation. Le dernier kilomètre de la soumission reste une opération humaine.

En revanche, les agents peuvent aider avec les métadonnées App Store. Demandez à l’agent de rédiger la description de l’application, les mots-clés et le texte « Nouveautés » en se basant sur les dernières modifications. C’est un travail de génération de texte où les agents excellent.

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

Ne commitez jamais de secrets. Pour les applications iOS connectées à des API backend :

  1. Utilisez des fichiers .xcconfig pour la configuration spécifique à chaque environnement
  2. Ajoutez les fichiers .xcconfig au .gitignore
  3. Référencez les valeurs de configuration via les paramètres de build de 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.

Qu’en est-il des animations SwiftUI — les agents peuvent-ils les écrire ?

Les agents écrivent du code d’animation syntaxiquement correct 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 lors de la transition entre les états du minuteur. »

Inefficace : « Rends l’animation du minuteur agréable. » (Subjectif, nécessite un ajustement visuel.)

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

Très bien. Les agents maîtrisent les patterns do/catch, Result et async throws de Swift :

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 d’erreurs structurée avec des messages utilisateur appropriés. Ils ont parfois tendance à sur-gérer les erreurs (capturer des exceptions qui devraient se propager) ; examinez donc les blocs catch.

Puis-je utiliser les 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 le dimensionnement 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 (sans SwiftData) ?

Les agents écrivent les mappings de migration Core Data et les versions de modèles, mais les étapes manuelles dans Xcode (création de nouvelles versions de modèle, sélection de la version courante) ne peuvent pas être automatisées. Si vous utilisez encore Core Data plutôt que SwiftData, documentez l’historique des versions du 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 ?

De deux manières : 1. L’outil RenderPreview d’Apple Xcode MCP effectue le rendu des previews sans interface graphique et renvoie le résultat. L’agent peut vérifier qu’une preview compile et s’affiche sans erreurs, mais il ne peut pas évaluer la justesse visuelle. 2. La vérification par compilation via build_sim confirme que les fournisseurs de previews compilent. Si une preview plante à l’exécution, la compilation réussit quand même — le plantage ne se manifeste que lorsque Xcode tente d’effectuer le rendu de la preview.

Pour la vérification visuelle des previews, Xcode doit être 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) obéit aux mêmes limitations que Metal — les agents peuvent écrire du code correct mais ne peuvent pas vérifier la sortie spatiale.

Quelle taille un projet peut-il atteindre avant que les agents ne rencontrent des difficultés ?

La taille de la fenêtre de contexte est le facteur limitant. Avec la fenêtre de 1M tokens d’Opus 4.6, Claude Code peut maintenir environ 50 à 70 fichiers Swift simultanément en mémoire de travail active. Pour les projets plus importants, l’agent utilise la recherche de fichiers et la lecture sélective pour travailler sur des sous-ensembles du code source. Les projets de plus de 100 fichiers fonctionnent parfaitement — 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 code source. Un projet bien documenté de 200 fichiers avec un CLAUDE.md détaillé produit de meilleurs résultats qu’un projet non documenté de 30 fichiers.

Faut-il connaître Swift pour utiliser des agents dans le développement iOS ?

Vous devez être capable d’examiner la production 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 comprendre Swift suffisamment bien 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 ×10 de vos compétences existantes, 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 environnements d’exécution 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’exécution des agents pour le développement iOS ?

Avec le plan Max de Anthropic (Opus 4.6, contexte de 1M), une session de développement iOS typique dure 30 à 120 minutes et traite 200K à 800K tokens. Les appels d’outils MCP ajoutent une surcharge minimale (les réponses JSON structurées sont économes en tokens comparées à la sortie brute de compilation). Le coût est comparable à l’utilisation de Claude Code pour n’importe quel autre code source — le développement iOS n’est pas significativement plus ou moins coûteux que le développement web.

Peut-on utiliser des agents avec des projets UIKit ?

Oui, mais les agents sont plus efficaces avec SwiftUI. UIKit nécessite davantage de code boilerplate, possède 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 les agents pour la couche modèle et la logique métier tout en gérant l’interface manuellement, ou de migrer progressivement les vues vers SwiftUI.

Comment les agents gèrent-ils la localisation ?

Les agents créent et modifient efficacement les fichiers .xcstrings (catalogues de chaînes Xcode). 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 en 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 a sa stratégie de prévention.

Erreur 1 : mélange de 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éation de cycles de rétention dans les closures

Ce qui se passe : l’agent crée des closures qui capturent self fortement, notamment dans Timer.publish, NotificationCenter et les gestionnaires de complétion.

Prévention : inclure 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 de @MainActor

Ce qui se passe : l’agent crée des classes @Observable sans isolation @MainActor, provoquant des avertissements de concurrence Swift 6.2 ou des plantages à l’exécution lorsque les mises à jour de l’interface se produisent hors du thread principal.

Prévention :

## Concurrency Rule
ALL @Observable classes MUST be @MainActor:
```swift
@Observable
@MainActor
final class SomeManager { }
### Erreur 4 : utiliser NavigationLink avec une closure de destination

**Ce qui se passe :** l'agent utilise le `NavigationLink(destination:label:)` déprécié au lieu du pattern typé `NavigationLink(value:)` + `.navigationDestination(for:)`.

**Prévention :**
```markdown

## 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 compilation avec des noms de simulateurs spécifiques (« iPhone 16 Pro ») qui peuvent ne pas exister sur votre système.

**Prévention :** MCP gère cela — `list_sims` découvre les simulateurs disponibles. Dans CLAUDE.md :
```markdown

## 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. Par ailleurs :

## 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é par plateforme

Ce qui se passe : l’agent utilise HealthKit dans du code partagé qui 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 : inclure 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

Le bilan honnête

Après avoir publié 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 maintenant principalement produit par les agents et révisé par l’humain.

Ce que les agents n’ont pas transformé : les décisions architecturales, le design visuel, l’optimisation des performances ou la soumission sur l’App Store. Ces aspects restent pilotés par l’humain.

Le multiplicateur est réel mais borné. J’estime un gain de productivité de 3 à 5× pour les projets bien documentés avec une configuration appropriée de MCP et des hooks. Les projets non documentés sans hooks connaissent peut-être une amélioration de 1,5 à 2× — l’agent passe trop de temps à deviner au lieu de construire.

L’investissement qui rapporte : 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 comprenaient Swift. Après MCP, ce sont des partenaires de développement qui écrivent, compilent, testent, déboguent et itèrent. La boucle de retour structurée fait 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), mettez en place correctement MCP et les hooks, rédigez un CLAUDE.md approfondi, puis étendez les patterns aux projets plus importants. Ne commencez pas par l’application multi-plateforme 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 vers tout le reste.

L’avenir : l’intégration native d’agents dans Xcode 26.3 n’est que le commencement. 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 — des fichiers CLAUDE.md soignés, des architectures testables, des hooks automatisés — capitaliseront sur cet investissement à mesure que les outils s’amélioreront.


Carte de référence rapide

Installation (configuration initiale)

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

Journal des modifications

Date Modifications
13 avril 2026 Publication initiale. 8 applications, 3 environnements d’exécution, configuration MCP, patterns CLAUDE.md, hooks, études de cas.

Références


  1. XcodeBuildMCP inclut la télémétrie Sentry par défaut. La documentation relative à la confidentialité du projet détaille les données transmises : messages d’erreur, traces de pile et, dans certains cas, chemins de fichiers. La variable d’environnement XCODEBUILDMCP_SENTRY_DISABLED=true désactive entièrement cette collecte. 

  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 implémentés par XcodeBuildMCP et l’Xcode MCP d’Apple. 

  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. Versionnage sémantique avec journaux de modifications. 

  4. Apple a introduit le serveur Xcode MCP dans le cadre de l’initiative d’outils de développement intelligents d’Xcode 26.3, positionnant MCP comme couche d’interface entre les assistants de codage IA et la chaîne d’outils Xcode. Consultez les notes de version d’Xcode 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 documentaire. 

  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é ceux 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 garantir un style de code cohérent. 

  9. Site officiel de XcodeBuildMCP, xcodebuildmcp.com. Confirme 59 outils MCP via un exemple de sortie CLI. Catégories d’outils : simulateur, appareil, débogage et automatisation d’interface. 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 qu’Xcode 26.3 intègre nativement le support de Claude Agent et du runtime Codex via Réglages > 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 de configuration et résultats concrets issus du workflow de développement iOS du même auteur. 

NORMAL ios-agent-development.md EOF