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

Desarrollo de apps iOS con agentes de IA: la guía del profesional

# Desarrollo de apps iOS con agentes de IA

words: 11924 read_time: 55m updated: 2026-04-14 23:54
$ less ios-agent-development.md

TL;DR: Tres entornos de ejecución de agentes ahora generan código para iOS: Claude Code CLI con MCP, Codex CLI con MCP, y los agentes nativos de Intelligence en Xcode 26.3. Dos servidores MCP (XcodeBuildMCP con 59 herramientas y xcrun mcpbridge de Apple con 20 herramientas) dan a los agentes acceso estructurado a compilaciones, pruebas, simuladores y depuración. Esta guía cubre patrones reales de CLAUDE.md, configuraciones de hooks y evaluaciones honestas de qué funciona y qué falla — extraídas de 8 apps iOS en producción con un total de 293 archivos Swift. Los agentes sobresalen en vistas SwiftUI, modelos SwiftData, refactorización y diagnóstico de errores de compilación. Fallan en modificaciones de .pbxproj, firma de código y depuración visual. La brecha entre “el agente escribe Swift” y “el agente publica una app iOS” se cierra con configuración, no con prompting.

Construyo 8 apps iOS con agentes de codificación IA. No prototipos — apps en el App Store, con integraciones de HealthKit, shaders Metal, física de SpriteKit, sincronización con iCloud, Live Activities, tablas de clasificación de Game Center y targets multiplataforma que abarcan iOS, watchOS y tvOS. Cada línea de Swift en estas apps fue escrita por un agente y revisada por mí, o escrita por mí y refactorizada por un agente. Según mi estimación, la proporción es aproximadamente 85/15 a favor del agente.

Esta guía es la referencia que me hubiera gustado tener cuando empecé. Cubre toda la pila: qué entorno de ejecución de agentes usar, cómo configurar servidores MCP para acceso estructurado a compilaciones, qué incluir en tu CLAUDE.md, qué hooks evitan que el agente destruya tu proyecto de Xcode y — lo más importante — dónde fallan los agentes y necesitas tomar el control.

Puntos Clave

Para desarrolladores iOS nuevos en agentes IA:

  • Comienza con Claude Code CLI + XcodeBuildMCP. Es el entorno de ejecución más maduro con la cobertura de herramientas MCP más amplia. Instala dos comandos, agrega un CLAUDE.md a tu proyecto, y el agente puede compilar, probar y depurar sin que copies mensajes de error.
  • Nunca permitas que un agente modifique .pbxproj. Esta es la regla más importante. Un hook PreToolUse que bloquee escrituras en .pbxproj y .xcodeproj/ te ahorrará horas de recuperación.
  • Tu CLAUDE.md es el documento de incorporación del agente. Cada hora invertida en CLAUDE.md ahorra diez horas de corrección de errores del agente.

Para usuarios experimentados de agentes que agregan iOS a su flujo de trabajo:

  • MCP transforma el ciclo de compilación iOS. Antes de MCP, los agentes escribían Swift pero no podían verificar que compilara. Con XcodeBuildMCP, el agente escribe código, lo compila, lee errores estructurados, los corrige y ejecuta pruebas — de forma autónoma.
  • Tres entornos de ejecución cubren diferentes necesidades. Claude Code CLI para sesiones agénticas profundas, Codex CLI para trabajo por lotes sin interfaz, agentes nativos de Xcode 26.3 para correcciones rápidas en línea sin salir del IDE.
  • La infraestructura de hooks se transfiere directamente. Tus formateadores PostToolUse existentes, bloqueadores PreToolUse y hooks de ejecución de pruebas funcionan de manera idéntica para proyectos iOS con ajustes menores de rutas.

Para líderes técnicos evaluando desarrollo iOS asistido por IA:

  • La efectividad del agente escala con la documentación del proyecto, no con su tamaño. Una app de 63 archivos con un CLAUDE.md detallado produce mejor resultado del agente que una app de 14 archivos sin ninguno.
  • El límite de .pbxproj es innegociable. Los agentes no pueden editar archivos de proyecto de Xcode de forma confiable. Tu flujo de trabajo debe contemplar la adición manual de archivos a los targets de Xcode.
  • ROI honesta: los agentes manejan el 70-80% del trabajo de implementación. El 20-30% restante — pulido visual, firma, ajuste de rendimiento, envío al App Store — requiere juicio humano.

Elige Tu Camino

Lo que necesitas Ve aquí
Configurar MCP por primera vez Configuración de MCP: La Guía Completa — instala ambos servidores, verifica, configura agentes
Escribir un CLAUDE.md para tu proyecto iOS Patrones de CLAUDE.md para Proyectos iOS — ejemplos reales de 8 apps
Comparar los tres entornos de ejecución de agentes Tres Entornos de Ejecución de Agentes para iOS — Claude Code vs. Codex vs. Xcode nativo
Entender qué pueden y no pueden hacer los agentes Lo Que los Agentes Hacen Bien y Lo Que los Agentes Hacen Mal
Configurar hooks para desarrollo iOS Hooks para Desarrollo iOS — formato al guardar, protección de .pbxproj, ejecutores de pruebas
Referencia completa (esta página) Sigue leyendo — todo, desde la configuración hasta patrones avanzados

Cómo Usar Esta Guía

Esta es una referencia de más de 3.000 líneas. Comienza donde se ajuste tu nivel de experiencia:

Experiencia Comienza Aquí Luego Explora
Nuevo en iOS + agentes Requisitos PreviosConfiguración de MCPTu Primera Sesión con un Agente Patrones de CLAUDE.md, Qué Funciona/No Funciona
Desarrollador iOS, nuevo en agentes Tres Entornos de EjecuciónConfiguración de MCPCLAUDE.md Hooks, Patrones de Arquitectura
Usuario de agentes, nuevo en iOS Patrones de ArquitecturaLo Que los Agentes Hacen MalCLAUDE.md Contexto Específico de Frameworks, Flujos de Trabajo Avanzados
Experimentado con ambos Flujos de Trabajo AvanzadosHooksPatrones Multiplataforma Matriz de Comparación de Entornos, El Portafolio

Tabla de Contenidos

  1. El Portafolio: 8 Apps, 293 Archivos
  2. Requisitos Previos
  3. Tres Entornos de Ejecución de Agentes para iOS
  4. Configuración de MCP: La Guía Completa
  5. Patrones de CLAUDE.md para Proyectos iOS
  6. Tu Primera Sesión con un Agente
  7. Lo Que los Agentes Hacen Bien en iOS
  8. Lo Que los Agentes Hacen Mal en iOS
  9. Hooks para Desarrollo iOS
  10. Patrones de Arquitectura Que Funcionan con Agentes
  11. Contexto Específico de Frameworks
  12. Patrones Multiplataforma
  13. Flujos de Trabajo Avanzados
  14. Casos de Estudio Reales
  15. Ciclo de Vida de un Proyecto con Agentes
  16. Configuración de Definiciones de Agentes
  17. Patrones de Pruebas para iOS Asistido por Agentes
  18. Gestión de la Ventana de Contexto para Proyectos iOS
  19. Solución de Problemas
  20. Errores Comunes de Agentes en iOS y Cómo Prevenirlos
  21. La Evaluación Honesta
  22. Preguntas Frecuentes
  23. Tarjeta de Referencia Rápida
  24. Referencias

Recursos Relacionados

Tema Recurso
Configuración de MCP para Xcode (artículo de blog más breve) Dos Servidores MCP Convirtieron a Claude Code en un Sistema de Compilación iOS
Referencia completa de Claude Code CLI Claude Code CLI: La Guía Completa
Referencia de Codex CLI Codex CLI: La Guía Completa
Inmersión profunda en el sistema de hooks Anatomía de una Garra: 84 Hooks como Capa de Orquestación
Patrones de arquitectura de agentes Guía de Arquitectura de Agentes

El portafolio: 8 apps, 293 archivos

Antes de entrar en la configuración, esto es lo que respalda esta guía. No son proyectos de juguete — abarcan cinco frameworks de Apple, tres plataformas y el rango completo de complejidad iOS, desde un rastreador de entrenamientos de 14 archivos hasta un temporizador de meditación multiplataforma de 63 archivos.

App Stack Archivos Complejidad
Banana List SwiftUI + SwiftData + sincronización iCloud Drive + servidor MCP para Claude Desktop 53 CRUD completo, sincronización iCloud, servidor MCP personalizado que expone los datos de la app a Claude Desktop
Ace Citizenship App de estudio SwiftUI + backend FastAPI 26 Cliente-servidor, integración REST API, motor de cuestionarios
TappyColor Juego de combinación de colores con SpriteKit 30 Game loop, física, manejo de toques, efectos de partículas
Return Temporizador de meditación zen — iOS 26+, watchOS, tvOS 63 HealthKit, Live Activities, runtime extendido de Watch, navegación por foco en TV, sincronización de sesiones por iCloud
amp97 Shaders Metal + visualización de audio 41 Pipeline de renderizado Metal personalizado, análisis de audio, cómputo GPU en tiempo real
Reps SwiftUI + SwiftData rastreo de entrenamientos 14 App mínima viable, patrones limpios de SwiftData
Water SwiftUI + SwiftData + Metal + HealthKit rastreo de hidratación 34 Simulación de fluidos en Metal, registro de consumo de agua con HealthKit, widget
Starfield Destroyer SpriteKit + Metal shooter espacial 32 99 niveles, 8 naves, tablas de clasificación de Game Center, post-procesamiento Metal

Por qué importa el conteo de archivos: La efectividad del agente se correlaciona con la legibilidad del proyecto, no con su tamaño. Return (63 archivos) produce mejor salida del agente que amp97 (41 archivos) porque Return tiene un CLAUDE.md detallado con anotaciones de archivos, diagramas de arquitectura y patrones explícitos. Los shaders Metal de amp97 son inherentemente más difíciles de razonar para los agentes, independientemente de la calidad de la documentación.


Prerrequisitos

Antes de configurar cualquier runtime de agente para desarrollo iOS:

Requerido: - macOS 15+ (Sequoia) o macOS Tahoe - Xcode 26.3+ instalado y configurado (acuerdo de licencia aceptado, plataformas descargadas) - Al menos un runtime de iOS Simulator instalado - Una cuenta Anthropic API (para Claude Code) o cuenta OpenAI (para Codex)

Recomendado: - SwiftFormat instalado (brew install swiftformat) — utilizado por los hooks de formato al guardar - SwiftLint instalado (brew install swiftlint) — opcional pero útil para aplicar reglas de estilo - Familiaridad con la terminal — los tres runtimes operan desde o se integran con la línea de comandos

Verifica tu instalación de 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 devuelve “command not found”, necesitas Xcode 26.3 o posterior. Instala o actualiza Xcode a través de la App Store o developer.apple.com. Nota: xcode-select --install solo instala las Command Line Tools, que no incluyen mcpbridge — necesitas la aplicación completa Xcode.app.


Tres runtimes de agentes para iOS

Tres runtimes distintos pueden escribir, compilar y probar código iOS. No son intercambiables — cada uno tiene diferentes fortalezas, diferentes patrones de integración con MCP y diferentes casos de uso ideales.

1. Claude Code CLI

Qué es: El asistente de programación agéntico de Anthropic basado en terminal. Lee tu codebase, ejecuta comandos, modifica archivos y se conecta a herramientas externas vía MCP.

Integración con MCP: Soporte completo tanto para XcodeBuildMCP como para el MCP de Xcode de Apple. El agente descubre herramientas vía el protocolo MCP y las invoca con parámetros estructurados. 59 + 20 herramientas entre ambos servidores.

Configuración:

# 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

Ideal para: Sesiones de implementación profunda — construir funciones nuevas, refactorizar a través de múltiples archivos, depurar problemas complejos, ejecutar ciclos autónomos de compilación-prueba-corrección. La ventana de contexto de 1M tokens de Claude Code (con Opus 4.6) permite que el agente mantenga en memoria de trabajo la mayoría de los proyectos iOS pequeños a medianos — en mi experiencia, aproximadamente hasta 50 archivos dependiendo del tamaño de cada uno.

Sesión típica:

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 diferencia clave respecto al flujo de trabajo previo a MCP: el agente nunca te pide que compiles manualmente ni que pegues la salida de errores. El ciclo compilar-error-corregir es autónomo.

2. Codex CLI

Qué es: El agente de programación basado en terminal de OpenAI. Similar en concepto a Claude Code, pero usa modelos de OpenAI (GPT-4o, o3) y tiene un modelo de permisos diferente.

Integración con MCP: Codex soporta MCP mediante el comando codex mcp add. El MCP de Xcode de Apple funciona directamente:

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

XcodeBuildMCP también funciona con Codex mediante el mismo comando npx:

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

Ideal para: Operaciones por lotes headless, integración CI/CD y tareas donde quieres una segunda opinión de una familia de modelos diferente. El modo sandbox de Codex ejecuta código en entornos aislados, lo cual es útil para operaciones destructivas como ejecuciones de suites de pruebas que modifican estado.

Diferencias clave con Claude Code: - Usa modelos de OpenAI en lugar de modelos Claude - Diferentes tamaños de ventana de contexto y economía de tokens - Modelo de permisos sandbox-first (más restrictivo por defecto) - Ecosistema MCP más reducido (menos servidores comunitarios probados) - Sistema de hooks disponible (v0.119.0+) pero menos maduro que el de Claude Code — menos tipos de eventos y sin campo condicional if

Cuándo usar Codex en lugar de Claude Code para iOS:

Usa Codex cuando quieras diversidad de modelos — tener un segundo agente revisando código escrito por el primero detecta diferentes clases de errores. El flujo de trabajo collab (Claude construye, Codex revisa) es efectivo para iOS porque los patrones de SwiftUI que parecen correctos para una familia de modelos pueden tener problemas sutiles que otra detecta. Los shaders Metal y los patrones de concurrencia se benefician especialmente de la revisión con dos modelos.

3. Agentes nativos de Xcode 26.3

Qué es: Apple integró agentes de programación con IA directamente en el panel Intelligence de Xcode. A partir de Xcode 26.3, puedes configurar Claude Agent y Codex como proveedores de inteligencia en Xcode Settings > Intelligence.

Configuración:

  1. Abre Xcode 26.3+
  2. Navega a Settings > Intelligence
  3. Agrega un nuevo proveedor:
  4. Para Claude: Selecciona “Claude Agent”, ingresa tu clave Anthropic API
  5. Para Codex: Selecciona “Codex”, ingresa tu clave API de OpenAI
  6. El agente aparece en la barra lateral de Intelligence y puede invocarse en línea

Ideal para: Ediciones rápidas en línea, autocompletado de código con razonamiento a nivel de agente, y desarrolladores que prefieren no salir de Xcode. La integración nativa significa que el agente tiene acceso directo al contexto del proyecto en Xcode — archivos abiertos, targets de compilación, configuración de schemes — sin necesidad de un puente MCP.

Limitaciones en comparación con agentes CLI: - Sin sistema de hooks — no puedes aplicar formato al guardar ni bloquear escrituras en .pbxproj - Sin carga de CLAUDE.md — el agente no lee tus archivos de configuración a nivel de proyecto - Autonomía limitada — el agente opera sobre el archivo actual o la selección, no a través de todo el proyecto - Sin delegación a subagentes — las tareas complejas de múltiples pasos no pueden paralelizarse - Sin configuración de servidor MCP — el agente solo usa las herramientas integradas de Xcode

Cuándo usar agentes nativos de Xcode:

Para ediciones rápidas y acotadas donde cambiar a la terminal es sobrecarga innecesaria. “Agrega una propiedad computada a este modelo.” “Escribe una prueba unitaria para esta función.” “Refactoriza esta vista para usar @Observable.” Tareas que tocan uno o dos archivos y no requieren un ciclo de compilación-prueba.

Para cualquier cosa que requiera compilar, probar, refactorizar múltiples archivos o corrección autónoma de errores, usa un agente CLI con MCP.

Matriz comparativa de runtimes

Capacidad Claude Code CLI Codex CLI Xcode 26.3 Nativo
Soporte MCP Completo (79 herramientas) Completo (79 herramientas) Solo herramientas integradas de Xcode
Sistema de hooks Sí (maduro) Sí (básico, v0.119.0+) No
CLAUDE.md / config de proyecto Equivalente codex.md No
Ciclo autónomo compilar-probar-corregir Sí (vía MCP) Sí (vía MCP) Parcial (solo en línea)
Delegación a subagentes Sí (hasta 10 en paralelo) No No
Ventana de contexto 1M tokens (Opus 4.6) Varía según modelo Varía según proveedor
Operaciones multi-archivo Acceso completo al codebase Acceso completo al codebase Archivo actual / selección
Protección de .pbxproj Vía hooks Manual N/A (usa Xcode nativamente)
Formato al guardar Vía hooks PostToolUse Herramientas externas Configuración de Xcode
Capacidad offline No No No
Modelo de costos Uso de API Anthropic Uso de API OpenAI Uso de API del proveedor

La recomendación: Usa Claude Code CLI como tu runtime principal. Usa los agentes nativos de Xcode 26.3 para ediciones rápidas en línea. Usa Codex CLI para pasadas de revisión y operaciones por lotes. Los tres se complementan en lugar de competir.


Configuración de MCP: La guía completa

MCP (Model Context Protocol) es lo que transforma a un agente de “escribe Swift y espera que tú lo compiles” a “escribe Swift, lo compila, lee los errores estructurados y los corrige.” Esta sección profundiza más que el artículo del blog — cubriendo ambos servidores, todos los métodos de instalación, la verificación, y la configuración del agente que asegura que las herramientas realmente se utilicen.

XcodeBuildMCP: 59 herramientas para desarrollo iOS headless

XcodeBuildMCP envuelve xcodebuild, xcrun simctl y LLDB en 59 herramientas MCP estructuradas. Funciona sin que Xcode esté en ejecución — todo el ciclo de compilación, pruebas y depuración opera de forma headless mediante las herramientas de línea de comandos de Apple.

Opciones de instalación:

# 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

La bandera -s user hace que el servidor esté disponible globalmente en todos los proyectos. Omítela para una instalación con alcance de proyecto (útil si solo quieres MCP en proyectos iOS, no en proyectos web).

La variable de entorno -e XCODEBUILDMCP_SENTRY_DISABLED=true desactiva la telemetría de reportes de errores. XcodeBuildMCP incluye Sentry por defecto, que envía datos de errores incluyendo rutas de archivos. Desactívalo a menos que quieras contribuir diagnósticos al proyecto.1

Inventario completo de herramientas (59 herramientas en 8 categorías):

Categoría Herramientas Qué hacen
Descubrimiento de proyectos discover_projs, list_schemes, list_targets Encuentra archivos .xcodeproj/.xcworkspace, lista los schemes y targets disponibles
Compilación build_sim, build_device, build_mac Compila con salida estructurada de errores/advertencias JSON por archivo y línea
Pruebas test_sim, test_device Ejecuta pruebas con resultados de aprobado/fallido por método
Ciclo de vida del simulador list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults Crea, inicia, gestiona y configura simuladores
Gestión de dispositivos list_devices, install_device, launch_device Despliegue y gestión de dispositivos reales
Depuración debug_attach_sim, debug_attach_device, debug_breakpoint, debug_stack, debug_variables, debug_eval, debug_continue, debug_step, debug_detach Integración completa con LLDB incluyendo breakpoints e inspección de variables
Automatización de UI snapshot_ui, screenshot, tap, swipe, type_text Interacción automatizada y captura visual
Scaffolding de proyectos create_project, add_file, add_package Crea proyectos y agrega dependencias

Las herramientas más importantes para el trabajo diario:

  1. build_sim — La usarás cientos de veces. Devuelve JSON con errores categorizados por archivo, línea y severidad. El agente lee el error, navega al archivo y lo corrige sin que tengas que tocar nada.

  2. test_sim — Devuelve resultados por método de prueba. El agente sabe exactamente qué prueba falló y por qué, no solo “las pruebas fallaron.”

  3. list_sims + boot_sim — Gestión de simuladores sin memorizar las banderas de xcrun simctl. El agente descubre los runtimes disponibles y elige un dispositivo apropiado.

  4. discover_projs + list_schemes — Introspección del proyecto. El agente no necesita adivinar el nombre de tu scheme o la estructura del workspace.

  5. debug_attach_sim + debug_stack + debug_variables — Depuración remota con LLDB. El agente puede establecer breakpoints, inspeccionar variables y recorrer el código paso a paso sin que abras el depurador.

Apple Xcode MCP: 20 herramientas que conectan con Xcode

El servidor MCP de Apple viene incluido con Xcode 26.3 mediante xcrun mcpbridge. Se comunica con un proceso de Xcode en ejecución a través de XPC (el framework de comunicación entre procesos de Apple), exponiendo estado interno al que ninguna herramienta CLI puede acceder.

Instalación:

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

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

Requiere Xcode 26.3+ y un proceso de Xcode en ejecución. Si Xcode no está abierto, cada llamada MCP a través de este servidor fallará o se quedará colgada. XcodeBuildMCP no tiene esta limitación.

Inventario de herramientas (20 herramientas en 5 categorías):

Categoría Herramientas Qué hacen
Operaciones de archivos XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep Lectura/escritura de archivos dentro del contexto del proyecto Xcode
Compilación y pruebas BuildProject, GetBuildLog, RunAllTests, RunSomeTests Compila y ejecuta pruebas con el sistema de compilación interno de Xcode
Diagnósticos XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile Diagnósticos de código en tiempo real (no solo errores de compilación)
Código y documentación ExecuteSnippet, DocumentationSearch Ejecución de Swift REPL y búsqueda en la documentación de Apple
Previsualizaciones RenderPreview Renderizado headless de previsualizaciones SwiftUI

Herramientas exclusivas de Apple MCP (no disponibles en XcodeBuildMCP):

  1. DocumentationSearch — Busca en la documentación de desarrolladores de Apple, incluyendo sesiones de WWDC. Más rápido y confiable que la búsqueda web para preguntas sobre API de Apple. Pregunta “¿es válido HKQuantityType(.dietaryWater)?” y obtén una respuesta definitiva desde la fuente.

  2. ExecuteSnippet — Ejecución de Swift REPL dentro del contexto del proyecto. El agente puede verificar comportamientos de API, probar conversiones de tipos y validar expresiones sin compilar la aplicación completa.

  3. RenderPreview — Renderiza previsualizaciones de SwiftUI de forma headless. El agente puede comprobar si una vista se renderiza sin errores, aunque no puede evaluar la corrección visual (el render se devuelve como datos, no se inspecciona visualmente).

  4. XcodeListNavigatorIssues — Devuelve diagnósticos en tiempo real del analizador de Xcode, no solo errores de compilación. Detecta problemas como variables no utilizadas, posibles ciclos de retención y advertencias de deprecación que el sistema de compilación no muestra.

Por qué ambos servidores

Se superponen en compilación y pruebas, pero difieren fundamentalmente:

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

Usa XcodeBuildMCP para: El ciclo de compilación, pruebas y depuración. Funciona sin Xcode abierto, consume menos memoria del sistema y ofrece una gestión más completa de simuladores y dispositivos. Esta es tu herramienta de compilación principal.

Usa Apple Xcode MCP para: Consultas de documentación, verificación con Swift REPL, renderizado de previsualizaciones SwiftUI y diagnósticos en tiempo real. Mantén Xcode abierto durante las sesiones que necesiten estas capacidades.

En la práctica: Uso XcodeBuildMCP para aproximadamente el 90% de las llamadas MCP y Apple Xcode MCP para documentación y verificación con REPL. El agente usa XcodeBuildMCP por defecto para compilaciones y pruebas porque es más rápido (sin la sobrecarga del proceso de Xcode) y más confiable (sin dependencia de XPC).

Verificación

Después de instalar ambos servidores, verifica que estén conectados:

# List all configured MCP servers
claude mcp list

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

Si un servidor aparece como “Disconnected” o no se muestra:

  1. XcodeBuildMCP no conecta: Asegúrate de que Node.js esté instalado (node --version). El comando npx requiere Node.js 18+.
  2. Apple Xcode MCP no conecta: Asegúrate de tener Xcode 26.3+ instalado y que el comando xcrun mcpbridge funcione en tu terminal. Abre Xcode al menos una vez para aceptar el acuerdo de licencia.
  3. Ninguno aparece: Reinicia Claude Code (claude en una nueva terminal). Los servidores MCP registrados durante una sesión pueden no aparecer hasta el reinicio.

Enseñar al agente a usar MCP

Instalar los servidores MCP es necesario pero no suficiente. Sin orientación explícita, el agente puede recurrir a ejecutar xcodebuild vía Bash (salida no estructurada, tokens de contexto desperdiciados) o usar búsqueda web para la documentación de Apple (más lento, menos confiable).

Agrega esto a tu CLAUDE.md o definición del agente:

## Build & Test — Siempre usa MCP

Prefiere las herramientas de MCP sobre los comandos de shell directos para TODAS las operaciones de compilación:

- **Build**: `build_sim` / `build_device` (NO `xcodebuild` vía Bash)
- **Test**: `test_sim` / `test_device` (NO `xcodebuild test` vía Bash)
- **Simuladores**: `list_sims`, `boot_sim`, `open_sim` (NO `xcrun simctl` vía Bash)
- **Depuración**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Documentación de Apple**: `DocumentationSearch` (NO WebSearch para APIs de Apple)
- **Verificación de Swift**: `ExecuteSnippet` (NO `swift` vía Bash)
- **Previews**: `RenderPreview` para verificación headless de SwiftUI

MCP devuelve JSON estructurado. Bash devuelve texto sin estructura.
Datos estructurados significan menos tokens consumidos y mejor diagnóstico de errores.

Esta guía asegura que el agente recurra primero a las herramientas de MCP. Sin ella, observarás al agente construyendo largos comandos de xcodebuild vía Bash, consumiendo miles de tokens de contexto al analizar la salida y, en ocasiones, identificando erróneamente el error real.


Patrones de CLAUDE.md para proyectos iOS

Tu CLAUDE.md es el archivo más importante del proyecto para el desarrollo asistido por agentes. Es el documento de onboarding del agente — la diferencia entre un nuevo integrante que leyó la documentación de arquitectura y uno que está adivinando.

Cada proyecto iOS que mantengo tiene un CLAUDE.md. Estos son los patrones que funcionan, extraídos de las 8 aplicaciones.

Las secciones esenciales

Todo CLAUDE.md para iOS necesita estas seis secciones. Todo lo demás es opcional.

1. Identidad del proyecto

# 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

Por qué importa: el agente necesita conocer el target de deployment antes de escribir cualquier código. Un agente apuntando a iOS 17 usará NavigationView y @ObservedObject. Un agente apuntando a iOS 26 usará NavigationStack y @Observable. El bundle ID importa para entitlements y la configuración de HealthKit. La versión de Swift determina el modelo de concurrencia (async/await vs. completion handlers, concurrencia estricta vs. permisiva).

2. Estructura de archivos con anotaciones de propósito

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


Los comentarios en línea después de cada nombre de archivo no son decoración. Son la documentación con mayor impacto que puedes escribir. Cuando el agente está decidiendo dónde agregar una nueva función, estas anotaciones lo guían al archivo correcto en el primer intento, en lugar de tener que leer cada archivo para entender la estructura del proyecto.

Anti-patrón: Listar archivos sin anotaciones. TimerManager.swift no le dice nada al agente sobre si maneja estado, UI o ambos. TimerManager.swift # Timer state, logic, and repeat handling le indica exactamente qué pertenece ahí y qué no.

3. Comandos de build y 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.

Incluye los comandos directos aunque el agente debería preferir MCP. Los comandos directos sirven como documentación de respaldo y hacen explícitos los nombres de scheme y los destinos.

#### 4. Patrones clave y reglas

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

Estos patrones evitan que el agente introduzca inconsistencias. Sin documentación explícita de patrones, el agente a veces usará ObservableObject en un archivo y @Observable en otro, o creará un nuevo mecanismo de configuración en lugar de usar el singleton Settings.shared existente.

5. Lo que el agente nunca debe hacer

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

Las prohibiciones explícitas son más efectivas que las expectativas implícitas. El agente sigue restricciones negativas de manera más confiable que las sugerencias positivas, porque son binarias (hacerlo / no hacerlo) en lugar de heurísticas (preferir esto / a veces usar aquello).

6. Contexto específico del framework

Esta sección varía según la aplicación. Inclúyela para cualquier framework que tenga configuración no obvia:

Para apps con 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)`

Para apps con 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

Para apps con 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

Para apps con 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 real: Banana List (SwiftUI + SwiftData + iCloud + servidor MCP)

Este es un ejemplo anotado que muestra cómo las seis secciones funcionan juntas para una app moderadamente compleja. Este es el patrón de CLAUDE.md que uso para Banana List, una app de lista de compras con 53 archivos, sincronización con iCloud y un servidor MCP personalizado que expone los datos de la app a 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

## Estructura de Archivos

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

## Modelos SwiftData

### Relaciones
- `GroceryList` tiene muchos `GroceryItem` (eliminación en cascada)
- `GroceryItem` pertenece a un `GroceryList` (obligatorio)
- `GroceryItem` tiene un `Category` opcional
- `Category` tiene muchos `GroceryItem` (nullify al eliminar)

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

Patrones de Consulta

  • Listas: @Query(sort: \GroceryList.name) var lists: [GroceryList]
  • Elementos activos: @Query(filter: #Predicate { !$0.isCompleted })
  • Por categoría: filtrar en memoria después de la consulta (limitaciones de predicados en SwiftData)

Compilación y Pruebas

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

Es preferible usar las herramientas de MCP (build_sim, test_sim) en lugar de comandos directos.

Patrones Clave

Observable + SwiftData

  • Las clases @Model de SwiftData son automáticamente Observable
  • NO agregues @Observable a clases @Model (es redundante y genera advertencias)
  • Usa @Bindable para bindings bidireccionales con propiedades del modelo en formularios
  • Usa @Query en vistas, modelContext.fetch() en código fuera de vistas

Sincronización con iCloud

  • Automática mediante la integración de SwiftData con CloudKit
  • Resolución de conflictos: última escritura gana (comportamiento predeterminado de CloudKit)
  • El estado de sincronización se expone a través de CloudSyncManager.shared.syncState
  • Para probar la sincronización, ejecuta en dos simuladores con la misma cuenta de iCloud

Arquitectura del Servidor MCP

  • Se ejecuta como un servidor WebSocket local en el puerto 8765
  • Expone 6 herramientas: listAll, getList, createList, addItem, completeItem, deleteItem
  • Claude Desktop se conecta mediante la configuración de MCP en ~/.config/claude-desktop/config.json

Reglas

  • NUNCA modifiques el contenido de .pbxproj o .xcodeproj
  • NUNCA cambies el esquema del modelo sin actualizar SampleData.swift
  • NUNCA uses ObservableObject — los modelos de SwiftData ya son Observable
  • NUNCA uses @StateObject — usa @State con clases @Observable
  • NUNCA uses NavigationView — siempre NavigationStack
  • NUNCA agregues el macro @Observable a clases @Model
  • SIEMPRE usa @Bindable para bindings de formularios con propiedades del modelo
  • SIEMPRE prueba los cambios de sincronización con iCloud en dos instancias de simulador
### CLAUDE.md Real: Reps (App Mínima con SwiftData — 14 Archivos)

Para proyectos pequeños, el CLAUDE.md puede ser conciso. Este es el patrón para Reps, un rastreador de entrenamientos de 14 archivos. Observa cómo incluso un CLAUDE.md breve cubre las seis secciones esenciales:

```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
Eso son 40 líneas de CLAUDE.md para un proyecto de 14 archivos. Toma 10 minutos escribirlo y ahorra horas de confusión del agente.

### CLAUDE.md Real: Starfield Destroyer (SpriteKit + Metal — 32 Archivos)

Los proyectos de juegos requieren más contexto específico del framework. El agente necesita comprender el grafo de escenas, las categorías de física y la máquina de estados del juego:

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

## Reglas

- NUNCA modifiques .pbxproj
- NUNCA modifiques las bitmasks de PhysicsCategory (rompe toda la detección de colisiones)
- NUNCA cambies el orden z de la jerarquía de escena sin entender el orden de renderizado
- NUNCA modifiques ShaderTypes.h sin actualizar tanto las referencias de Swift como de Metal
- Agrega nuevos enemigos creando subclases de EnemyShip, no modificándolo
- Agrupación de balas (pooling): recicla mediante removeFromParent() + re-agregar, nunca asignes nuevas
- Game Center: siempre verifica isAuthenticated antes de enviar puntuaciones

CLAUDE.md real: amp97 (Metal + Visualización de Audio — 41 archivos)

Los proyectos de Metal necesitan el mayor contexto específico de framework porque los agentes no pueden verificar la salida visual:

# 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
### Escalando CLAUDE.md según el tamaño del proyecto

El nivel adecuado de detalle depende de la cantidad de archivos y la complejidad del framework:

| Tamaño del proyecto | Profundidad del CLAUDE.md | Ejemplo |
|-------------|----------------|---------|
| **Pequeño (< 20 archivos)** | Identidad + lista de archivos + reglas | Reps (14 archivos): patrones básicos de SwiftData, comandos de compilación, prohibiciones |
| **Mediano (20-40 archivos)** | + Contexto del framework + patrones clave | TappyColor (30 archivos): jerarquía de escena de SpriteKit, categorías de física, bucle del juego |
| **Grande (40+ archivos)** | + Diagramas de arquitectura + mapas de relaciones + información multi-target | Return (63 archivos): arquitectura multiplataforma, diagrama de sincronización de sesiones, diferencias por plataforma |
| **Especializado (Metal/GPU)** | + Diagramas de pipeline + definiciones de tipos compartidos + layouts de buffers | amp97 (41 archivos): etapas del pipeline de renderizado, struct de uniforms, gestión de buffers |

El costo de documentar en exceso es prácticamente nulo (el agente omite lo que no necesita). El costo de documentar insuficientemente es alto (el agente inventa patrones que entran en conflicto con tu código base).

### Lista de verificación de CLAUDE.md

Usa esta lista al crear o auditar un CLAUDE.md para un proyecto iOS:

- [ ] Bundle ID y deployment target especificados
- [ ] Versión de Swift y patrón de arquitectura nombrados
- [ ] Estructura de archivos con anotaciones de propósito en línea
- [ ] Comando de compilación con scheme y destino correctos
- [ ] Comando de pruebas con scheme y destino correctos
- [ ] Preferencia de MCP documentada ("preferir build_sim sobre xcodebuild")
- [ ] Regla de @Observable (nunca ObservableObject)
- [ ] Regla de NavigationStack (nunca NavigationView)
- [ ] Prohibición de .pbxproj
- [ ] Contexto específico del framework (permisos de HealthKit, relaciones de SwiftData, jerarquía de SpriteKit, pipeline de Metal)
- [ ] Guards de disponibilidad por plataforma documentados (#if canImport, #if os)
- [ ] Singletons clave y patrones compartidos documentados
- [ ] Limitaciones conocidas o trampas documentadas

---

## Tu primera sesión con un agente

Con MCP configurado y un CLAUDE.md en tu proyecto, aquí tienes un recorrido de una primera sesión efectiva. Este ejemplo usa Claude Code CLI, pero el flujo de trabajo aplica para cualquier runtime.

### Paso 1: Verifica que el agente puede ver tu proyecto

Tú: Resume este proyecto. ¿Con qué scheme debo compilar?

Claude: [lee CLAUDE.md] [llama a discover_projs vía MCP] [llama a list_schemes vía MCP]

    Este es Return, un temporizador de meditación zen para iOS 26+, watchOS y tvOS.
    Schemes disponibles: Return, ReturnWatch, ReturnTV, ReturnTests.
    Scheme principal para iOS: Return.
Si el agente no hace referencia al contenido de tu CLAUDE.md, verifica que el archivo esté en la raíz del proyecto (el mismo directorio que `.xcodeproj` o `Package.swift`).

### Paso 2: Ejecuta una compilación de verificación

Tú: Compila el scheme Return para el simulador iOS y reporta los resultados.

Claude: [llama a list_sims — encuentra iPhone 16 Pro en iOS 26.2] [llama a boot_sim — inicia el simulador] [llama a build_sim — compila el proyecto]

    Compilación exitosa. 63 archivos fuente compilados.
    2 advertencias:
    - HomeView.swift:132 — UIScreen.main deprecado en iOS 26.0
    - LogWaterIntent.swift:61 — Resultado de try? no utilizado
    0 errores.
### Paso 3: Ejecuta las pruebas

Tú: Ejecuta todas las pruebas y reporta aprobadas/fallidas.

Claude: [llama a test_sim]

    12 pruebas ejecutadas:
    ✓ TimerManagerTests (5/5 aprobadas)
    ✓ SettingsTests (4/4 aprobadas)
    ✓ ConstantsTests (3/3 aprobadas)
    Todas las pruebas aprobadas.
### Paso 4: Implementa una función

Tú: Agrega un nuevo tema “Rain” al sistema de temas. Sigue el patrón existente en Theme.swift y ThemeManager.swift. Incluye un sonido ambiental de lluvia. Compila y ejecuta las pruebas después de la implementación.

Claude: [lee Theme.swift — entiende el patrón del struct Theme] [lee ThemeManager.swift — entiende el registro de temas] [lee las definiciones de temas existentes] [agrega el tema Rain a Theme.swift siguiendo el patrón existente] [registra el tema Rain en ThemeManager.swift] [llama a build_sim — compilación exitosa] [llama a test_sim — todas las pruebas pasan]

    Tema Rain agregado:
    - Theme.swift: nuevo `static let rain` con video, portada, ambiente
    - ThemeManager.swift: agregado al array `allThemes`
    - Compilación: exitosa (0 errores, 2 advertencias existentes)
    - Pruebas: 12/12 aprobadas

    Nota: Necesitarás agregar rain_ambient.wav al proyecto
    y agregar los cambios de Theme.swift al target de Xcode manualmente
    (no modifiqué .pbxproj).
La nota del agente sobre no modificar .pbxproj es el resultado de las reglas en CLAUDE.md. Sin esa regla, el agente intentaría modificar el archivo del proyecto y probablemente lo corrompería.

---

## Qué hacen bien los agentes en iOS

Estas son las tareas donde los agentes producen consistentemente resultados correctos y listos para producción, con mínima revisión humana.

### Vistas y modificadores de SwiftUI

Los agentes poseen un profundo reconocimiento de patrones para la sintaxis declarativa de SwiftUI. Composición de vistas, cadenas de modificadores, enlaces de estado y diseño de interfaz  todo esto se alinea bien con los datos de entrenamiento del agente porque la superficie de API de SwiftUI está bien documentada y los patrones son altamente consistentes.

**Donde los agentes sobresalen:**
- Construir nuevas vistas a partir de una descripción ("crea una hoja de configuración con toggles para X, Y, Z")
- Aplicar cadenas de modificadores (`.glassEffect()`, `.sensoryFeedback()`, `.navigationTitle()`)
- Convertir entre patrones de diseño (VStack a LazyVGrid, List a ScrollView)
- Implementar enlaces de formulario con `@Bindable` hacia modelos SwiftData
- Crear proveedores de vista previa con datos de ejemplo

**Ejemplo de prompt que produce resultados excelentes:**

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 especificidad importa. "Crea una vista de configuración" produce resultados genéricos. "Crea un SettingsView que coincida con el patrón existente en SettingsSheet.swift" produce resultados consistentes con tu código base.

### Modelos y consultas de SwiftData

Los agentes manejan de forma confiable el macro `@Model` de SwiftData, las relaciones y los patrones de `@Query`. La naturaleza declarativa del framework (similar a Django ORM o SQLAlchemy) se alinea bien con patrones que el agente ha visto en múltiples códigos base.

**Donde los agentes sobresalen:**
- Definir clases `@Model` con relaciones
- Escribir `@Query` con descriptores de ordenamiento y predicados
- Implementar operaciones CRUD mediante `modelContext`
- Planes de migración entre versiones de esquema
- Datos de vista previa y fixtures de prueba

**Donde los agentes necesitan orientación:**
- Expresiones complejas de `#Predicate` (el DSL de predicados de SwiftData tiene limitaciones que el agente no siempre conoce  documenta las limitaciones conocidas en CLAUDE.md)
- Configuración de sincronización con CloudKit (automática vía SwiftData, pero el agente podría intentar implementar sincronización manual)

### Pruebas unitarias

Las pruebas unitarias escritas por agentes son consistentemente de alta calidad para proyectos iOS. El agente comprende los patrones de XCTest, los métodos de prueba asíncronos y el ciclo de vida de 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)

El agente produce casos XCTest bien estructurados con `setUp()` y `tearDown()`, aserciones apropiadas y manejo asíncrono para pruebas basadas en temporizadores.

### Refactorización y aplicación de patrones

Los agentes sobresalen en refactorizaciones mecánicas: extraer vistas en componentes, convertir `ObservableObject` a `@Observable`, migrar de `NavigationView` a `NavigationStack` y aplicar patrones consistentes a través de múltiples archivos.

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.

El agente trabaja metódicamente a través de cada archivo, aplica la transformación correctamente y mantiene la funcionalidad existente. Este es trabajo de alto impacto: una refactorización que tomaría una hora de edición manual se completa en minutos con una precisión casi perfecta.

### Diagnóstico de errores de compilación vía MCP

Con la salida estructurada de MCP, los agentes diagnostican errores de compilación más rápido que la mayoría de los desarrolladores. El agente lee el JSON de errores, identifica el archivo y línea exactos, comprende el mensaje de error y aplica la corrección — frecuentemente en un solo turno.

**Errores que los agentes corrigen de forma autónoma:**
- Imports faltantes
- Incompatibilidad de tipos
- Brechas en la conformidad de protocolos
- Uso de API obsoletas (con reemplazo)
- Parámetros de inicializador requeridos faltantes
- Violaciones de control de acceso

**Errores donde los agentes necesitan ayuda:**
- Resolución ambigua de tipos (múltiples módulos definen el mismo tipo)
- Fallos complejos en restricciones genéricas
- Errores de expansión de macros (el agente no puede ver la salida expandida del macro)

### Gestión del simulador

Los agentes manejan bien el ciclo de vida del simulador mediante MCP:

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

El agente llama a `list_sims` para encontrar runtimes disponibles, `boot_sim` para iniciar el simulador, `build_sim` para compilar e instalar, y `screenshot` para capturar  todo a través de llamadas estructuradas a MCP.

---

## Lo que los agentes hacen mal en iOS

Un balance honesto de dónde fallan los agentes. Conocer estos límites evita frustración y tokens desperdiciados.

### Modificaciones a archivos .pbxproj — NUNCA

Esta es la regla más importante en el desarrollo iOS con agentes. El archivo `.pbxproj` es la configuración del proyecto de Xcode  un archivo de texto estructurado con referencias UUID, listados de fases de compilación y pertenencia a targets. Es nominalmente legible para humanos, pero prácticamente imposible de analizar para agentes de IA.

**Por qué los agentes fallan con .pbxproj:**
- El archivo usa un formato personalizado (no JSON, no YAML, no XML) con significado posicional
- Cada entrada está referenciada cruzadamente por UUID  agregar un archivo requiere actualizar consistentemente entre 3 y 5 secciones distintas
- Un solo carácter fuera de lugar corrompe todo el archivo del proyecto
- La resolución de conflictos de merge de Xcode para .pbxproj ya es frágil  las ediciones de agentes lo empeoran

**Qué sucede cuando un agente edita .pbxproj:**
1. La edición parece exitosa (el agente reporta "archivo actualizado")
2. Xcode se rehúsa a abrir el proyecto ("The project file is corrupted")
3. Pasas entre 15 y 60 minutos recuperándote del historial de git
4. Aprendes a agregar el hook PreToolUse (consulta [Hooks](#hooks-for-ios-development))

**El flujo de trabajo:** El agente crea archivos Swift.  los agregas al proyecto de Xcode manualmente (arrastrar a Xcode, o File > Add Files). Esto toma 5 segundos por archivo y previene horas de recuperación.

**Para proyectos con Swift Package Manager:** Esta limitación es menos severa. `Package.swift` es un archivo Swift estándar que los agentes pueden editar de forma confiable. Si tu proyecto usa SPM exclusivamente (sin .xcodeproj), el agente puede gestionar la estructura completa del proyecto.

### Ediciones complejas de Interface Builder / Storyboard

Si tu proyecto usa Interface Builder (archivos `.xib`) o Storyboards (archivos `.storyboard`), los agentes no pueden editarlos de manera significativa. Son archivos XML con UUIDs autogenerados, referencias a constraints y conexiones de outlets diseñados para edición visual, no para edición de texto.

**La solución:** Usa SwiftUI exclusivamente para vistas nuevas. Si tu proyecto tiene archivos legacy de Interface Builder, déjalos como están y construye la nueva UI en SwiftUI.

### Optimización de rendimiento

Los agentes escriben código correcto, pero no necesariamente código eficiente. No pueden perfilar tu app, identificar cuellos de botella ni medir tasas de cuadros. La optimización de rendimiento requiere:

1. Perfilado con Instruments (herramienta visual, no accesible para agentes)
2. Comprensión de las características de GPU/CPU del dispositivo específico
3. Cambios iterativos basados en mediciones

**Dónde se manifiesta esto:**
- Optimización de shaders Metal (el agente escribe Metal válido pero no puede medir el tiempo de cuadro de la GPU)
- Complejidad del body de vistas SwiftUI (el agente crea vistas profundamente anidadas que causan sobrecarga en el redibujado)
- Optimización de consultas en Core Data / SwiftData (el agente escribe consultas correctas que pueden ser lentas en conjuntos de datos grandes)

**La solución:** Usa agentes para la implementación, perfila manualmente con Instruments y luego pide al agente que aplique optimizaciones específicas que hayas identificado.

### Code signing y provisioning

Los agentes no pueden depurar problemas de code signing más allá de leer el mensaje de error. La gestión de provisioning profiles, la creación de certificados, la configuración de entitlements y el envío al App Store son flujos de trabajo fundamentalmente operados por humanos que involucran el portal de Apple Developer, Keychain Access y la interfaz de signing de Xcode.

**Lo que el agente ve:** "Signing for 'Return' requires a development team."

**Lo que el agente no puede ver:** Si tu certificado expiró, si el provisioning profile incluye el dispositivo, si el bundle ID coincide con el App ID, o si tu archivo de entitlements es correcto.

**La solución:** Maneja todo el signing en la pestaña Signing & Capabilities de Xcode. No pidas a los agentes que depuren fallos de signing.

### Depuración compleja de shaders Metal

Los agentes escriben Metal Shading Language (MSL) sintácticamente correcto, pero no pueden verificar la salida visual ni depurar problemas del lado de la GPU. Los shaders Metal se ejecutan en la GPU  el agente no tiene mecanismo de retroalimentación para saber si el shader produce resultados visuales correctos.

**Lo que los agentes pueden hacer con Metal:**
- Escribir vertex y fragment shaders a partir de descripciones
- Configurar el pipeline de renderizado Metal en Swift
- Crear compute shaders para operaciones de datos en paralelo
- Corregir errores de compilación en archivos `.metal`

**Lo que los agentes no pueden hacer con Metal:**
- Verificar la corrección visual de la salida del shader
- Depurar rendimiento de la GPU (tiempo de cuadro, ocupación, ancho de banda de memoria)
- Diagnosticar artefactos visuales (banding, problemas de precisión, espacio de color incorrecto)
- Probar en diferentes arquitecturas de GPU (diferencias de comportamiento entre serie A y serie M)

**La solución:** Prueba los shaders Metal en dispositivos físicos. La implementación Metal del Simulator no es representativa del comportamiento de la GPU del dispositivo. Usa GPU Frame Capture de Xcode para depuración visual.

### Verificación visual del layout

Los agentes no pueden ver la UI de tu app. Escriben código de layout en SwiftUI y pueden verificar que compila, pero no pueden determinar si la pantalla resultante se ve correcta. Una vista que se renderiza 10 píxeles descentrada, usa el peso de fuente incorrecto o tiene elementos superpuestos no produce ningún error de compilación y pasa todas las pruebas lógicas.

**La solución:** Revisa los cambios de UI visualmente. Usa SwiftUI Previews en Xcode (o `RenderPreview` a través de Apple MCP para renderizado headless) para verificar el layout. Considera pruebas de snapshot con bibliotecas como swift-snapshot-testing para detección automatizada de regresiones visuales.

---

## Hooks para desarrollo iOS

Los hooks son comandos de shell que se ejecutan de forma determinista en puntos específicos del flujo de trabajo del agente. Son el mecanismo de aplicación  la diferencia entre "por favor no edites .pbxproj" (una sugerencia que el agente puede ignorar) y "no puedes editar .pbxproj" (un bloqueo absoluto).

Para conocer el contexto del sistema de hooks, consulta la [guía de hooks de Claude Code](/blog/claude-code-hooks-tutorial). Esta sección cubre patrones de hooks específicos para iOS.

### PreToolUse: Bloquear escrituras en .pbxproj

El hook más importante en cualquier proyecto iOS. Bloquea al agente para que no escriba en archivos `.pbxproj`, directorios `.xcodeproj/` y otros archivos gestionados por 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'"
      }
    ]
  }
}

Coloca esto en .claude/settings.json en la raíz del proyecto o en ~/.claude/settings.json para protección global.

Cómo funciona: Cuando el agente intenta usar la herramienta Edit o Write en cualquier archivo que coincida con el patrón, el hook se ejecuta, detecta la ruta del archivo, imprime una advertencia en stderr y sale con código 2 (lo que bloquea el uso de la herramienta). El agente recibe el mensaje de error y ajusta su enfoque.

Qué detecta: - Ediciones directas a .pbxproj - Cualquier archivo dentro de directorios .xcodeproj/ o .xcworkspace/ - Archivos de Interface Builder (.xib, .storyboard)

PostToolUse: Formateo automático con SwiftFormat

Formatea automáticamente los archivos Swift cada vez que el agente los escribe o edita:

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

Requisitos: SwiftFormat debe estar instalado (brew install swiftformat).

Por qué es importante: Los agentes producen Swift sintácticamente correcto, pero no siguen las convenciones de formato de manera consistente. SwiftFormat normaliza la indentación, la ubicación de llaves y el orden de los imports. El hook de formateo automático garantiza que cada archivo Swift que el agente toca quede formateado antes de que lo veas.

Opcional: Agrega un archivo de configuración .swiftformat en la raíz de tu proyecto para personalizar las reglas de formato:

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

PostToolUse: Ejecutar SwiftLint automáticamente

Si usas SwiftLint, ejecútalo después de cada edición de archivos 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'"
      }
    ]
  }
}

El || true evita que las advertencias del linter bloqueen al agente. Si quieres que las violaciones del linter sí bloqueen, elimínalo.

PostToolUse: Compilación automática tras cambios

Para ciclos de retroalimentación agresivos, activa una compilación después de cada cambio en archivos 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'"
      }
    ]
  }
}

Advertencia: Esto es costoso. Cada edición de archivo activa una compilación. Úsalo con moderación — es más útil durante sesiones de depuración donde necesitas retroalimentación inmediata de la compilación. Para desarrollo normal, deja que el agente active las compilaciones manualmente vía MCP cuando esté listo.

PreToolUse: Bloquear modificaciones de entitlements

Protege tu archivo de entitlements contra modificaciones accidentales del agente:

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

Configuración combinada de hooks para iOS

Aquí está el .claude/settings.json completo que uso en todos mis proyectos 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'"
      }
    ]
  }
}

Esto te da dos garantías: 1. El agente no puede corromper los archivos de proyecto de Xcode (bloqueo PreToolUse) 2. Cada archivo Swift que el agente toca se formatea automáticamente (formateo PostToolUse)


Patrones de arquitectura que funcionan con agentes

No todas las arquitecturas de Swift son igualmente amigables para los agentes. Estos patrones producen los mejores resultados porque son explícitos, consistentes y están bien representados en los datos de entrenamiento.

@Observable (nunca ObservableObject)

Los proyectos que apuntan a iOS 26+ deben usar @Observable exclusivamente. Este es tanto el patrón moderno como el patrón amigable para agentes:

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

Por qué @Observable es amigable para agentes: El patrón es más simple (no se necesitan anotaciones @Published), el modelo de propiedad es más claro (@State en lugar de @StateObject vs. @ObservedObject), y los agentes producen menos errores con él porque tiene menos partes móviles.

Documéntalo en CLAUDE.md: Incluso con iOS 26 como objetivo, los agentes ocasionalmente revierten a patrones de ObservableObject de sus datos de entrenamiento. La prohibición explícita previene esto.

// 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 es iOS 16+ y el único patrón de navegación que deberías usar para código nuevo. El patrón de navigationDestination(for:) con seguridad de tipos evita que el agente cree enlaces de navegación incorrectos.

SwiftData para persistencia

Los modelos de SwiftData son el patrón de persistencia más limpio para el desarrollo asistido por agentes:

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

Reglas clave para agentes que trabajan con SwiftData: 1. Las clases @Model son automáticamente Observable — no agregues @Observable 2. Usa @Bindable para bindings de formularios: @Bindable var item: GroceryItem 3. Usa @Query en las vistas para datos reactivos: @Query var items: [GroceryItem] 4. Usa modelContext.fetch() en código fuera de las vistas 5. Las eliminaciones de relaciones necesitan reglas explícitas: .cascade, .nullify, .deny

Concurrencia en Swift 6.2

Apunta a la concurrencia estricta de Swift 6.2 para proyectos nuevos:

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

Guía para agentes sobre concurrencia: - Marca todos los view models como @MainActor (previene advertencias de data race) - Usa async/await para todo el trabajo asíncrono (sin completion handlers) - Haz que los tipos de valor sean Sendable para transferencias entre actores - Usa Task { } en las vistas para inicialización asíncrona - Usa nonisolated solo cuando hayas medido una necesidad de rendimiento

Sistema de diseño Liquid Glass (iOS 26+)

iOS 26 introdujo el sistema de diseño Liquid Glass. Los agentes lo manejan bien cuando se les da guía explícita:

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

Incluye en CLAUDE.md: “Usa .glassEffect() en fondos de secciones y contenedores tipo tarjeta. Las barras de navegación adoptan automáticamente el material glass en iOS 26. No recrees manualmente efectos glass con materiales personalizados — usa el modificador del sistema.”


Contexto específico por framework

Cada framework de Apple tiene consideraciones específicas para agentes. Esta sección cubre los frameworks utilizados en las 8 apps.

HealthKit

Apps que lo usan: Return, Water

HealthKit requiere un manejo cuidadoso de permisos y guardas de plataforma:

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

Reglas para agentes con HealthKit: - Siempre verifica con HKHealthStore.isHealthDataAvailable() - Nunca asumas la autorización — verifica en cada escritura - Usa #if canImport(HealthKit) para código multiplataforma (HealthKit no está disponible en tvOS) - Nunca almacenes datos de salud localmente más allá de lo que HealthKit proporciona - Incluye tanto NSHealthShareUsageDescription como NSHealthUpdateUsageDescription en Info.plist

SpriteKit

Apps que lo usan: TappyColor, Starfield Destroyer

El modelo de grafo de escena de SpriteKit requiere guía explícita para agentes:

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

Fortalezas de los agentes con SpriteKit: - Crear secuencias y grupos de SKAction - Configurar cuerpos físicos y detección de contacto - Implementar máquinas de estado del juego - Construir overlays de HUD

Debilidades de los agentes con SpriteKit: - Bucles de juego sensibles al rendimiento (el agente agrega trabajo innecesario por frame) - Simulaciones físicas complejas (la física personalizada supera a SKPhysicsBody en precisión) - Ajuste de efectos de partículas (es visual, requiere iteración)

Metal

Apps que lo usan: amp97, Water, Starfield Destroyer

Metal es el framework donde los agentes más dificultades tienen. El modelo de programación GPU es fundamentalmente diferente del Swift del lado de la CPU, y los agentes no pueden verificar la salida visual.

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

Qué incluir en CLAUDE.md para proyectos con Metal: - La definición del struct Uniforms (compartido entre Swift y MSL) - El patrón de configuración del render pipeline state - Los índices de buffer y sus propósitos - Qué shaders existen y qué hace cada uno - Problemas de precisión conocidos (half vs. float)

Live Activities

Apps que lo usan: Return

Las Live Activities requieren configuración específica que los agentes manejan bien una vez documentada:

## Live Activities

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

Game Center

Apps que lo usan: 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)

Patrones Multiplataforma

Return abarca iOS, watchOS y tvOS. El desarrollo multiplataforma con agentes requiere documentación explícita de los límites entre plataformas.

Organización de Código Compartido

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

Regla para agentes: “Si un archivo está en Shared/, los cambios afectan a todas las plataformas. Si un archivo está en un directorio de plataforma, los cambios están aislados. Siempre verifica en qué directorio se encuentra un archivo antes de modificarlo.”

Guardas de Disponibilidad por Plataforma

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

Orientación para agentes: “Siempre usa guardas #if canImport() o #if os() cuando utilices frameworks específicos de una plataforma. No asumas que un framework está disponible en todos los targets.”

Adaptación de UI por Plataforma

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

Flujos de Trabajo Avanzados

Ciclos Autónomos de Compilación-Prueba-Corrección

El patrón más poderoso: darle al agente una especificación de funcionalidad y dejarlo iterar a través de ciclos de compilación-prueba-corrección de forma autónoma.

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.

El agente escribe código, compila mediante MCP, lee errores estructurados, los corrige y repite. Una funcionalidad que requeriría entre 5 y 10 ciclos humanos de compilar-error-corregir se completa en un solo ciclo autónomo.

Cuándo funciona: Funcionalidades bien definidas con criterios de aceptación claros.

Cuándo falla: Funcionalidades abiertas (“haz que se vea bien”), código sensible al rendimiento o cualquier cosa que requiera verificación visual.

Delegación a Subagentes para iOS

El sistema de subagentes de Claude Code funciona para proyectos 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.

El subagente explora documentación y patrones de código en una ventana de contexto separada, devuelve un resumen y la sesión principal implementa la recomendación. Esto evita que la investigación consuma tu contexto principal.

Aplicación de Patrones Entre Aplicaciones

Cuando mantienes múltiples aplicaciones iOS con patrones consistentes, los agentes pueden aplicar patrones de una aplicación a otra:

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.

El agente lee el patrón fuente, comprende la estructura y crea una implementación consistente en el proyecto destino.

Revisión con Agente Dual (Claude + Codex)

Para cambios críticos, usa dos agentes de familias de modelos diferentes:

  1. Claude Code escribe la implementación
  2. Codex CLI la revisa en una pasada separada
# 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."

Diferentes familias de modelos detectan diferentes clases de errores. Esto es especialmente valioso para shaders de Metal y patrones de concurrencia donde es fácil introducir errores sutiles.

Qué detecta la revisión dual que la revisión simple no:

Tipo de problema Fortaleza de Claude Fortaleza de Codex
Ciclos en relaciones de SwiftData Moderada Fuerte (GPT-4o)
Brechas de aislamiento con @MainActor Fuerte Moderada
Alineación de buffers en Metal Moderada Moderada
Detección de ciclos de retención Fuerte (Opus) Fuerte (o3)
Detección de deprecaciones en API Fuerte (datos de entrenamiento más recientes) Moderada
Condiciones de carrera en concurrencia Fuerte Fuerte (detecta patrones diferentes)

La revisión dual no se trata de encontrar más errores, sino de encontrar errores diferentes. Cada familia de modelos tiene modos de fallo distintos en su reconocimiento de patrones.

Operaciones en Lote Sobre Múltiples Aplicaciones

Cuando un cambio de framework o patrón afecta a múltiples aplicaciones:

# 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

Usa con precaución. La flag --dangerously-skip-permissions es necesaria para el modo no interactivo, pero omite todas las verificaciones de seguridad. Asegúrate de que tus hooks PreToolUse estén configurados para proteger los archivos .pbxproj.


Casos de Estudio Reales

Los consejos abstractos son fáciles. Aquí tienes escenarios específicos de las 8 apps que ilustran cómo funciona el desarrollo iOS asistido por agentes en la práctica — incluyendo los fracasos.

Caso de Estudio 1: Agregar una App de TV a Return (Éxito)

La tarea: Agregar un target de tvOS a Return, un temporizador de meditación que ya tenía versiones para iOS y watchOS. La app de TV necesitaba navegación con Siri Remote, interfaz para pantalla grande y sincronización de configuración con la app de iOS.

Lo que el agente hizo bien: - Leyó el TimerManager existente de iOS y creó un TVTimerManager que omitía Live Activities y HealthKit (no disponibles en tvOS) - Creó estilos de botón personalizados para la navegación por foco del Siri Remote (TVCapsuleButtonStyle, TVCircleButtonStyle) - Construyó un componente TVStepper que reemplaza los selectores de rueda (no utilizables con Siri Remote) por botones +/- - Implementó sincronización de configuración vía App Groups (group.com.941apps.Return) - Agregó guardas #if os(tvOS) a lo largo del código compartido - Compiló y probó mediante MCP con platform=tvOS Simulator,name=Apple TV

Lo que tuve que hacer manualmente: - Crear el target de tvOS en Xcode (File > New > Target > tvOS App) - Agregar el nuevo target al proyecto de Xcode (cambios en .pbxproj) - Configurar el entitlement de App Groups para el target de TV - Agregar el target de TV al scheme existente o crear uno nuevo - Agregar manualmente todos los archivos Swift creados por el agente al target de TV - Probar la navegación del Siri Remote a mano (el agente no puede evaluar el comportamiento de foco)

Resultado: 15 nuevos archivos Swift, app de TV completamente funcional, implementada en aproximadamente 3 horas de trabajo asistido por agente. La implementación manual equivalente habría tomado 1-2 días. El agente manejó aproximadamente el 80% del código; yo me encargué del 20% que requería interacción con la interfaz de Xcode y pruebas manuales.

Caso de Estudio 2: Depuración de Metal Shader en amp97 (Fracaso Parcial)

La tarea: Agregar un sistema de intensidad basado en energía al shader del osciloscopio. La visualización debía pulsar con la energía del audio.

Lo que sucedió: 1. El agente escribió una modificación válida del Metal shader agregando un uniform uEnergy y tonemapping HDR 2. El código compiló sin errores 3. En el dispositivo, la visualización era completamente blanca — el coeficiente de intensidad era 10 veces demasiado alto (3.5 en lugar de 0.30) 4. El agente no podía ver la pantalla blanca, así que no tenía señal de retroalimentación 5. Identifiqué el problema visualmente y le pedí al agente que redujera el coeficiente 6. El agente lo redujo, pero la máquina de estados de energía en general era demasiado compleja y rompió el visualizador de otras formas 7. Se revirtió por completo — dos commits (67959ed y cda4830) revertidos en 869d914

La lección: Los Metal shaders son el dominio más difícil para el desarrollo asistido por agentes porque el ciclo de retroalimentación está roto. El agente puede verificar la sintaxis (compila) y la semántica (tipos correctos), pero no puede verificar la salida (se ve bien). Cualquier modificación de shader que cambie el comportamiento visual requiere verificación humana en el dispositivo.

Lo que agregué a CLAUDE.md después de esto: “DO NOT attempt energy state modifications to the oscilloscope shader without extremely careful coefficient testing. Previous attempt broke the visualizer with coefficients 10x too high.”

Caso de Estudio 3: Migración de SwiftData en Banana List (Éxito)

La tarea: Migrar el modelo de datos de V1 a V2, agregando un campo quantity a GroceryItem y un nuevo modelo Category con relaciones.

Lo que hizo el agente: 1. Leyó las definiciones del modelo V1 existente 2. Creó las definiciones del modelo V2 con los nuevos campos y relaciones 3. Escribió un GroceryMigrationPlan con conformidad al protocolo SchemaMigrationPlan 4. Implementó la etapa de migración V1toV2: agregó valores por defecto quantity: 1 y category: nil 5. Actualizó todas las vistas para soportar los nuevos campos 6. Actualizó SampleData.swift para las previews 7. Compiló y ejecutó las pruebas mediante MCP — todas pasaron 8. Creó pruebas unitarias específicas para la migración

La clave: El agente tuvo éxito porque las migraciones de SwiftData siguen un patrón de protocolo bien definido que está ampliamente representado en la documentación de Apple y en los datos de entrenamiento. El CLAUDE.md documentaba explícitamente el modelo V1, así que el agente entendía desde qué punto estaba migrando.

Caso de Estudio 4: Sincronización de Sesiones vía iCloud en Return (Éxito con Complejidad)

La tarea: Implementar registro de sesiones de meditación entre dispositivos. Las sesiones completadas en Apple TV o Mac debían sincronizarse con iPhone para el registro en HealthKit.

Lo que produjo el agente:

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

El agente: 1. Creó el modelo de datos MeditationSession con UUID, fechas, duración, dispositivo de origen y estado de sincronización con HealthKit 2. Construyó el singleton SessionStore que gestiona NSUbiquitousKeyValueStore para la sincronización con iCloud 3. Implementó resolución de conflictos de fusión (deduplicación basada en UUID) 4. Agregó SessionHistoryView con adaptaciones específicas por plataforma (deslizar para eliminar en iOS, basado en foco en tvOS) 5. Conectó la sincronización con HealthKit en el lado de iPhone para sesiones provenientes de otros dispositivos

Lo que requirió iteración: La implementación inicial no manejaba el caso donde la app de iPhone se abre en segundo plano (sin notificación de primer plano para la sincronización). El agente necesitó orientación específica: “Usa NSUbiquitousKeyValueStore.didChangeExternallyNotification para activar la sincronización ante cambios de KV en segundo plano.” Después de esa pista, la implementación fue correcta.

La lección: Los agentes manejan bien los patrones arquitectónicos multiplataforma cuando la arquitectura está claramente descrita. El patrón de sincronización con iCloud no es trivial, pero sigue un patrón documentado de Apple que el agente comprendió. El caso límite (sincronización en segundo plano) requirió conocimiento de dominio humano porque no está bien documentado.

Caso de Estudio 5: Integración con Game Center en Starfield Destroyer (Éxito)

La tarea: Agregar leaderboards y logros de Game Center al juego de naves espaciales.

Lo que el agente hizo bien: - Implementó GKLocalPlayer.local.authenticateHandler en el punto de entrada de la app - Creó un GameCenterManager con métodos para envío de puntuaciones y reporte de logros - Agregó verificación del estado de autenticación antes de todas las operaciones de Game Center - Manejó el caso sin conexión de forma elegante (el juego funciona sin Game Center, envía los datos cuando se reconecta) - Creó definiciones de logros que coinciden con el sistema de progresión de 8 naves

Lo que requirió trabajo manual: - Crear los leaderboards y logros en App Store Connect (portal web, no accesible por el agente) - Configurar el entitlement de Game Center en Xcode - Probar con una cuenta sandbox de Game Center (requiere inicio de sesión manual en el dispositivo)


Ciclo de Vida del Proyecto con Agentes

Iniciar un Nuevo Proyecto iOS

El flujo de trabajo óptimo para iniciar un nuevo proyecto con asistencia de agentes:

Fase 1: Configuración Humana (15-30 minutos) 1. Crear el proyecto en Xcode (File > New > Project) 2. Configurar la firma y las capacidades 3. Establecer el deployment target y los destinos soportados 4. Agregar los entitlements necesarios (HealthKit, Game Center, etc.) 5. Crear el CLAUDE.md inicial con la identidad y las reglas del proyecto

Fase 2: Implementación por el Agente (horas a días) 1. El agente crea el modelo de datos (SwiftData, Core Data o structs simples) 2. El agente construye las vistas siguiendo los patrones documentados 3. El agente implementa la lógica de negocio en clases manager/service 4. El agente escribe pruebas unitarias 5. Ciclo de compilar-probar-corregir mediante MCP (autónomo)

Fase 3: Integración Humana (30-60 minutos) 1. Agregar los archivos creados por el agente a los targets de Xcode 2. Verificar firma y entitlements 3. Probar en dispositivo físico 4. Revisar el diseño visual y la experiencia de usuario 5. Enviar a App Store Connect

Mantener un Proyecto Existente

Para el desarrollo continuo en apps establecidas:

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]

La efectividad del agente escala con qué tan bien tu CLAUDE.md refleja el estado actual del proyecto. Actualiza tu CLAUDE.md cuando agregues funciones significativas, cambies patrones arquitectónicos o introduzcas nuevos frameworks.

Cuándo Involucrar al Agente y Cuándo No

Tarea ¿Agente? Por qué
Nueva vista en SwiftUI Los agentes destacan en UI declarativa
Cambios en modelos SwiftData Bien definidos, comprobables
Pruebas unitarias Mecánicas, basadas en patrones
Refactorización Sistemática, multi-archivo
Diagnóstico de errores de compilación Sí (vía MCP) Ciclo de retroalimentación estructurado
Nuevo target de Xcode No Requiere la interfaz de Xcode, cambios en .pbxproj
Firma y aprovisionamiento No Basado en portal, no accesible por el agente
Pulido visual No Requiere juicio estético humano
Ajuste de Metal shaders No Requiere pruebas GPU en dispositivo
Envío al App Store No Portal y Xcode Organizer
Perfilado de rendimiento No Requiere Instruments
Auditoría de accesibilidad Parcial El agente puede agregar etiquetas, el humano verifica VoiceOver

Configuración de definiciones de agentes

Si usas el sistema de definición de agentes de Claude Code (.claude/agents/), crea un agente específico para 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

Haz referencia a este agente con @ios-developer en las sesiones de Claude Code.


Patrones de testing para iOS asistido por agentes

Los agentes escriben pruebas unitarias excelentes cuando reciben instrucciones claras. Estos son los patrones que producen los mejores resultados.

Organización de archivos de prueba

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

Prompts efectivos para pruebas

Prompt de prueba efectivo:

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.

¿Por qué funciona? Los criterios de aceptación numerados le dan al agente una lista de verificación. Hacer referencia a un archivo de prueba existente establece el patrón. Especificar el uso de setUp() evita que el agente cree estados de prueba entrelazados.

Prompt de prueba ineficaz:

Write tests for TimerManager.

Esto produce pruebas genéricas y superficiales que omiten casos límite y pueden no seguir los patrones de tu proyecto.

Patrones de pruebas asíncronas

Para probar código basado en temporizadores y código asíncrono:

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

Patrones clave que los agentes necesitan que les recuerdes: - @MainActor en métodos de prueba que evalúan clases @MainActor - async throws para pruebas que usan Task.sleep u operaciones asíncronas - Tolerancia en aserciones basadas en tiempo (1,1 segundos, no exactamente 1,0) - setUp() / tearDown() limpios para aislamiento de pruebas

Pruebas de snapshot

Para detectar regresiones visuales, considera agregar 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.

Los agentes configuran correctamente las pruebas de snapshot, pero no pueden revisar las imágenes de referencia. Tú revisas los snapshots iniciales y luego las pruebas del agente detectan regresiones visuales en cambios futuros.


Gestión de la ventana de contexto para proyectos iOS

La ventana de contexto de 1M (Opus 4.6) es grande, pero no infinita. Los proyectos iOS tienen consideraciones específicas para la gestión del contexto.

Costo en tokens de archivos iOS

Tipo de archivo Tamaño típico Tokens aproximados
Vista SwiftUI (simple) 50-100 líneas 500-1.000
Vista SwiftUI (compleja) 200-400 líneas 2.000-4.000
Modelo SwiftData 30-80 líneas 300-800
Clase manager/servicio 100-300 líneas 1.000-3.000
Shader Metal (.metal) 50-200 líneas 500-2.000
Archivo de pruebas unitarias 50-200 líneas 500-2.000
CLAUDE.md 100-300 líneas 1.000-3.000
Respuesta MCP (build) varía 200-2.000
Respuesta MCP (pruebas) varía 500-5.000

Para un proyecto de 50 archivos: Leer todos los archivos consume aproximadamente 50.000-100.000 tokens, bien dentro de la ventana de 1M. El agente puede mantener todo el proyecto en contexto.

Para un proyecto de más de 100 archivos: Se hace necesaria la lectura selectiva. El agente lee primero CLAUDE.md (para las anotaciones de estructura de archivos) y luego lee archivos específicos según sea necesario. Por eso las anotaciones de archivos en CLAUDE.md son fundamentales: guían al agente hacia los archivos correctos sin necesidad de leerlo todo.

Estrategias para proyectos grandes

  1. Anotaciones detalladas de archivos en CLAUDE.md — El agente lee el mapa de archivos y navega directamente a los archivos relevantes
  2. Delegación a subagentes — Enruta la exploración e investigación a subagentes (contexto limpio, devuelven resúmenes)
  3. Prompts enfocados — “Modifica SettingsView.swift para agregar un nuevo toggle” es mejor que “actualiza la configuración”
  4. Límites de sesión — Inicia nuevas sesiones para funcionalidades no relacionadas en lugar de extender una sesión larga
  5. Usa /compact — El comando de compactación de Claude Code resume la conversación y libera contexto

Eficiencia de tokens con MCP

Uno de los argumentos más sólidos a favor de MCP: las respuestas estructuradas en JSON consumen muchos menos tokens que la salida cruda de xcodebuild.

Escenario Tokens Bash crudo Tokens MCP Ahorro
Build exitoso 3.000-10.000 200-500 85-95%
Build fallido (1 error) 3.000-10.000 300-800 90-92%
Resultados de pruebas (20 pruebas) 2.000-5.000 500-1.000 75-80%
Lista de simuladores 500-2.000 200-400 60-80%

En una sesión de desarrollo típica con 10-20 ciclos de build, MCP ahorra entre 30.000 y 150.000 tokens en comparación con xcodebuild crudo — tokens que permanecen disponibles para el razonamiento real sobre código.


Solución de problemas

“build_sim failed — scheme not found”

El agente está adivinando el nombre del scheme. Solución:

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

O agrega el nombre del scheme explícitamente en tu CLAUDE.md:

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

“xcrun mcpbridge — command not found”

Necesitas Xcode 26.3 o posterior. Verifica con xcodebuild -version. Si tienes Xcode 26.3+ pero el comando sigue fallando:

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

# Verify
xcrun mcpbridge --help

“Las herramientas de MCP no aparecen en Claude Code”

Las herramientas de MCP registradas durante una sesión activa pueden no aparecer hasta reiniciar. Sal de Claude Code e inicia una sesión nueva:

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

Luego verifica:

You: List all available MCP tools from XcodeBuildMCP.

“El agente sigue usando xcodebuild a través de Bash en lugar de MCP”

El agente no está descubriendo las herramientas de MCP mediante Tool Search. Dos soluciones:

  1. Agrega indicaciones explícitas en CLAUDE.md (consulta Enseñar al agente a usar MCP)
  2. Indica directamente: “Usa la herramienta build_sim de MCP, no xcodebuild a través de Bash”

“La compilación tiene éxito pero el agente reporta un fallo”

XcodeBuildMCP analiza la salida de xcodebuild. Si la compilación produce advertencias que parecen errores (común con advertencias de deprecación), el agente puede malinterpretar el resultado. Verifica el campo de estado real en la respuesta de MCP.

“El simulador se congela durante el arranque”

Cierra todos los simuladores y reinicia:

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

O pídele al agente:

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

“El agente intentó modificar .pbxproj a pesar de las reglas en CLAUDE.md”

Las reglas en CLAUDE.md son sugerencias. Los hooks son mecanismos de cumplimiento. Si no tienes el hook PreToolUse bloqueando escrituras en .pbxproj, el agente eventualmente lo intentará. Instala el 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'"
      }
    ]
  }
}

Las reglas dicen “por favor, no lo hagas”. Los hooks dicen “no puedes”.


Preguntas frecuentes

¿Con qué entorno de agentes debería empezar?

Claude Code CLI con XcodeBuildMCP. Tiene la integración de MCP más profunda, el sistema de hooks más maduro y la ventana de contexto de 1M (Opus 4.6) que puede mantener proyectos iOS completos en memoria de trabajo. Empieza aquí, luego agrega Codex para revisión y los agentes nativos de Xcode para ediciones rápidas en línea a medida que tu flujo de trabajo madure.

¿Necesito ambos servidores MCP?

Para la mayoría de los desarrolladores, XcodeBuildMCP solo cubre el 90% de las necesidades (compilaciones, pruebas, simuladores, depuración). Agrega el MCP de Apple para Xcode si quieres búsqueda en documentación, verificación con Swift REPL o renderizado de previsualizaciones de SwiftUI. Siempre puedes agregarlo después — los dos servidores son independientes.

¿Pueden los agentes crear un proyecto de Xcode desde cero?

XcodeBuildMCP incluye una herramienta create_project que genera la estructura de nuevos proyectos de Xcode. Sin embargo, para apps en producción, recomiendo crear el proyecto en Xcode (para configurar correctamente la firma, las capacidades y los targets) y luego usar agentes para toda la implementación del código. Los 5 minutos que inviertes en el asistente de nuevo proyecto de Xcode ahorran horas de problemas de configuración generados por agentes.

¿Cómo manejan los agentes las dependencias de Swift Package Manager?

Bien. Package.swift es un archivo Swift estándar que los agentes pueden leer y editar de forma confiable. Agregar dependencias, actualizar rangos de versiones y configurar targets funciona correctamente. La limitación está en la gestión de dependencias basada en .xcodeproj (la interfaz de resolución de paquetes de Xcode) — eso lo administra Xcode y no debería ser editado por agentes.

¿Pueden los agentes enviar a la App Store?

No. El envío a la App Store involucra el Organizer de Xcode, perfiles de aprovisionamiento, capturas de pantalla, metadatos y el portal de App Store Connect. Nada de esto es accesible a través de MCP o herramientas de línea de comandos de una manera que los agentes puedan operar de forma significativa. Los agentes manejan todo hasta el archivo — implementación, pruebas, corrección de errores y documentación. El último tramo del envío sigue siendo operado por humanos.

No obstante, los agentes pueden ayudar con los metadatos de la App Store. Pídele al agente que escriba la descripción de la app, las palabras clave y el texto de novedades basándose en los cambios más recientes. Este es trabajo de generación de texto donde los agentes sobresalen.

¿Cómo manejo secretos y claves de API en el desarrollo iOS asistido por agentes?

Nunca hagas commit de secretos. Para apps iOS que se conectan a APIs de backend:

  1. Usa archivos .xcconfig para configuración específica por entorno
  2. Agrega los archivos .xcconfig a .gitignore
  3. Referencia los valores de configuración mediante ajustes de compilación en Info.plist
  4. Documenta los secretos requeridos en CLAUDE.md sin incluir los valores reales
## 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`.

El agente sabe que las claves existen y dónde se usan, pero nunca ve los valores reales.

¿Qué hay de las animaciones en SwiftUI — pueden los agentes escribirlas?

Los agentes escriben código de animación sintácticamente correcto, pero no pueden verificar el resultado visualmente. Las animaciones simples (.animation(.spring()), .transition(.slide), withAnimation { }) producen resultados correctos. Las animaciones complejas de múltiples pasos con temporización precisa requieren iteración visual que los agentes no pueden realizar.

Efectivo: “Agrega una animación de resorte cuando el temporizador transiciona entre estados.”

Inefectivo: “Haz que la animación del temporizador se sienta satisfactoria.” (Subjetivo, requiere ajuste visual.)

¿Cómo manejan los agentes los patrones de manejo de errores?

Muy bien. Los agentes entienden los patrones do/catch, Result y 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

Los agentes producen manejo de errores estructurado con mensajes apropiados para el usuario. A veces manejan errores en exceso (capturando excepciones que deberían propagarse), así que revisa los bloques catch.

¿Puedo usar agentes para la implementación de accesibilidad?

Parcialmente. Los agentes agregan etiquetas, sugerencias y traits de accesibilidad correctamente:

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

Lo que los agentes no pueden hacer: verificar que el orden de navegación de VoiceOver sea correcto, probar el escalado de Dynamic Type o evaluar las relaciones de contraste de color. Usa el Accessibility Inspector de Xcode para la verificación.

¿Cómo manejan los agentes la migración de Core Data (si no usas SwiftData)?

Los agentes escriben mapeos de migración y versiones de modelo de Core Data, pero los pasos manuales en Xcode (crear nuevas versiones del modelo, seleccionar la versión actual) no se pueden automatizar. Si todavía usas Core Data en lugar de SwiftData, documenta el historial de versiones del modelo en CLAUDE.md:

## Versiones del modelo de datos de Core Data
- V1: Inicial (GroceryList, GroceryItem)
- V2: Se añadió el modelo Category (actual)
- Migración: Ligera y automática para V1→V2

¿Cómo manejan los agentes las previews de SwiftUI?

De dos formas: 1. La herramienta RenderPreview de Apple Xcode MCP renderiza previews sin interfaz gráfica y devuelve el resultado. El agente puede verificar que una preview compila y se renderiza sin errores, pero no puede evaluar la corrección visual. 2. Verificación basada en compilación mediante build_sim confirma que los providers de preview compilan. Si una preview falla en tiempo de ejecución, la compilación sigue siendo exitosa — el fallo solo se manifiesta cuando Xcode intenta renderizar la preview.

Para la verificación visual de previews, aún necesitas tener Xcode abierto.

¿Qué hay de visionOS y Apple Vision Pro?

Los mismos patrones aplican. XcodeBuildMCP soporta simuladores de visionOS, y los patrones arquitectónicos (@Observable, NavigationStack, SwiftData) son idénticos. El código específico de RealityKit (contenido 3D, espacios inmersivos, seguimiento de manos) tiene las mismas limitaciones que Metal — los agentes pueden escribir código correcto pero no pueden verificar la salida espacial.

¿Qué tan grande puede ser un proyecto antes de que los agentes tengan dificultades?

El tamaño de la ventana de contexto es el factor limitante. Con la ventana de 1M tokens de Opus 4.6, Claude Code puede mantener aproximadamente 50-70 archivos Swift en memoria de trabajo activa simultáneamente. Para proyectos más grandes, el agente utiliza búsqueda de archivos y lectura selectiva para trabajar con subconjuntos del código. Proyectos con más de 100 archivos funcionan bien — el agente simplemente lee archivos bajo demanda en lugar de mantener todo en contexto.

El límite práctico no es la cantidad de archivos sino la coherencia del código. Un proyecto bien documentado de 200 archivos con un CLAUDE.md detallado produce mejores resultados que un proyecto sin documentar de 30 archivos.

¿Necesito saber Swift para usar agentes en el desarrollo iOS?

Necesitas ser capaz de revisar la salida del agente y tomar decisiones arquitectónicas. No necesitas escribir cada línea tú mismo, pero sí necesitas entender Swift lo suficiente como para detectar cuando el agente toma decisiones incorrectas — especialmente en concurrencia, gestión de memoria y patrones específicos de frameworks. Un agente es un amplificador 10x de tu habilidad existente, no un reemplazo.

¿Cómo manejan los agentes los conflictos de merge en archivos Swift?

Los agentes resuelven conflictos de merge en archivos fuente Swift de manera confiable. Los marcadores estándar de conflicto (<<<<<<<, =======, >>>>>>>) son bien comprendidos por todos los runtimes de agentes. Sin embargo, los conflictos de merge en archivos .pbxproj siguen siendo una tarea de resolución manual — no le pidas a los agentes resolver conflictos en .pbxproj.

¿Cuál es el costo de ejecutar agentes para desarrollo iOS?

Con el plan Max de Anthropic (Opus 4.6, contexto de 1M), una sesión típica de desarrollo iOS dura entre 30 y 120 minutos y procesa entre 200K y 800K tokens. Las llamadas a herramientas de MCP añaden una sobrecarga mínima (las respuestas estructuradas en JSON son eficientes en tokens comparadas con la salida cruda de compilación). El costo es comparable a ejecutar Claude Code en cualquier otro código — el desarrollo iOS no es significativamente más ni menos costoso que el desarrollo web.

¿Puedo usar agentes con proyectos UIKit?

Sí, pero los agentes son más efectivos con SwiftUI. UIKit requiere más código repetitivo, tiene una estructura menos declarativa y a menudo involucra archivos de Interface Builder que los agentes no pueden editar. Si tienes un proyecto UIKit, considera usar agentes para la capa de modelos y la lógica de negocio mientras manejas la UI manualmente, o migra vistas incrementalmente a SwiftUI.

¿Cómo manejan los agentes la localización?

Los agentes crean y editan archivos .xcstrings (catálogos de cadenas de Xcode) de manera efectiva. Pueden añadir nuevas claves de localización, proporcionar traducciones y mantener la consistencia entre idiomas. El formato estructurado JSON de los archivos .xcstrings es amigable para agentes. Para archivos .strings (formato legacy), los agentes también funcionan bien — el formato clave-valor es sencillo.


Errores comunes de agentes en iOS (y cómo prevenirlos)

Estos son los errores recurrentes que he observado a lo largo de miles de interacciones con agentes en 8 proyectos iOS. Cada uno tiene una estrategia de prevención.

Error 1: Mezclar patrones Observable

Qué sucede: El agente usa @Observable en un archivo y ObservableObject en otro, o añade @Observable a una clase @Model (que ya es Observable).

Prevención: Reglas explícitas en 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

Error 2: Crear ciclos de retención en closures

Qué sucede: El agente crea closures que capturan self de forma fuerte, especialmente en Timer.publish, NotificationCenter y completion handlers.

Prevención: Incluye un patrón de closures en 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

Error 3: Ignorar los requisitos de @MainActor

Qué sucede: El agente crea clases @Observable sin aislamiento @MainActor, causando advertencias de concurrencia en Swift 6.2 o fallos en tiempo de ejecución cuando las actualizaciones de UI ocurren fuera del hilo principal.

Prevención:

## Concurrency Rule
ALL @Observable classes MUST be @MainActor:
```swift
@Observable
@MainActor
final class SomeManager { }
### Error 4: Usar NavigationLink con closure de destino

**Qué sucede:** El agente usa el `NavigationLink(destination:label:)` deprecado en lugar del patrón type-safe `NavigationLink(value:)` + `.navigationDestination(for:)`.

**Prevención:**
```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)) { }

### Error 5: Nombres de simulador hardcodeados

**Qué sucede:** El agente escribe comandos de compilación con nombres específicos de simulador ("iPhone 16 Pro") que pueden no existir en tu sistema.

**Prevención:** MCP se encarga de esto  `list_sims` descubre los simuladores disponibles. En 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.

Error 6: Crear archivos en directorios incorrectos

Qué sucede: El agente crea un nuevo archivo de vista en la raíz del proyecto en lugar del subdirectorio Views/, o coloca un modelo en el grupo equivocado.

Prevención: Las anotaciones de estructura de archivos en CLAUDE.md guían la ubicación. Adicionalmente:

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

Error 7: No manejar la disponibilidad por plataforma

Qué sucede: El agente usa HealthKit en código compartido que compila para tvOS (donde HealthKit no está disponible), o usa ActivityKit en código de watchOS.

Prevención:

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

Error 8: Sobreingeniería de funciones simples

Qué sucede: El agente crea un protocolo, una extensión de protocolo, una implementación concreta, una factory y un contenedor de inyección de dependencias para lo que debería ser una función utilitaria de 20 líneas.

Prevención: Incluye un principio de simplicidad:

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

La evaluación honesta

Tras lanzar 8 apps iOS con agentes de IA, aquí está el resumen:

Los agentes transformaron: La velocidad de implementación. Lo que tomaba días ahora toma horas. Vistas SwiftUI, modelos SwiftData, tests unitarios, refactorización — todo esto ahora es producido principalmente por agentes y revisado por humanos.

Los agentes no transformaron: Las decisiones arquitectónicas, el diseño visual, la optimización de rendimiento ni el envío al App Store. Esto sigue siendo dirigido por humanos.

El multiplicador es real pero tiene límites. Estimo una mejora de productividad de 3-5x para proyectos bien documentados con una configuración adecuada de MCP y hooks. Proyectos sin documentar y sin hooks ven quizás una mejora de 1.5-2x — el agente pasa demasiado tiempo adivinando en lugar de construyendo.

La inversión que vale la pena: El tiempo dedicado a CLAUDE.md, hooks y la configuración de MCP. Cada hora de configuración ahorra muchas horas de corregir errores del agente. La configuración es el producto — el agente es el motor de ejecución.

Lo que me sorprendió: Cuánto cambiaron la dinámica los servidores MCP. Antes de MCP, los agentes eran editores de texto sofisticados que casualmente entendían Swift. Después de MCP, son compañeros de desarrollo que escriben, compilan, prueban, depuran e iteran. El ciclo de retroalimentación estructurado es la diferencia entre un agente que escribe código y uno que lo lanza a producción.

Lo que le diría a mi yo del pasado: Empieza con la app más pequeña (Reps, 14 archivos), configura correctamente MCP y los hooks, escribe un CLAUDE.md exhaustivo, y luego escala los patrones a proyectos más grandes. No empieces con la app multiplataforma de 63 archivos. La inversión en infraestructura es la misma independientemente del tamaño del proyecto — hazla una vez en un proyecto pequeño, y luego cópiala a todo lo demás.

El futuro: La integración nativa de agentes en Xcode 26.3 es el comienzo, no el final. Que Apple lance soporte para MCP significa que la cadena de herramientas se está moviendo hacia un desarrollo agent-first. Los desarrolladores que inviertan en estructuras de proyecto compatibles con agentes ahora — archivos CLAUDE.md limpios, arquitecturas testeables, hooks automatizados — verán esa inversión multiplicarse a medida que las herramientas mejoren.


Tarjeta de Referencia Rápida

Instalación (Configuración Única)

# 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

Secciones Esenciales 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 Esenciales

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

Reglas de Arquitectura

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

Prioridades de Herramientas 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)

Registro de Cambios

Fecha Cambios
2026-04-13 Publicación inicial. 8 apps, 3 runtimes, configuración de MCP, patrones de CLAUDE.md, hooks, casos de estudio.

Referencias


  1. XcodeBuildMCP incluye telemetría de Sentry por defecto. La documentación de privacidad del proyecto detalla qué se envía: mensajes de error, stack traces y, en algunos casos, rutas de archivos. La variable de entorno XCODEBUILDMCP_SENTRY_DISABLED=true desactiva el envío por completo. 

  2. Anthropic, “Model Context Protocol Specification,” modelcontextprotocol.io/specification. La especificación de MCP define el transporte JSON-RPC, el descubrimiento de herramientas y el protocolo de recursos que implementan tanto XcodeBuildMCP como el MCP de Apple para Xcode. 

  3. XcodeBuildMCP, github.com/getsentry/XcodeBuildMCP. Código abierto, mantenido por Sentry. 59 herramientas para flujos de trabajo de simulador, dispositivo, depuración y automatización de UI. Versionado semántico con registros de cambios. 

  4. Apple introdujo el servidor MCP de Xcode como parte de la iniciativa de herramientas inteligentes para desarrolladores en Xcode 26.3, posicionando MCP como la capa de interfaz entre los asistentes de programación con IA y la cadena de herramientas de Xcode. Consulta las Notas de la versión de Xcode para la documentación oficial. 

  5. Rudrank Riyam, “Exploring Xcode Using MCP Tools,” rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients, 2026. Confirmación independiente del conteo de herramientas MCP de Apple, la dependencia de XPC y las capacidades de búsqueda en documentación. 

  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. Los agentes con acceso estructurado a herramientas superaron significativamente a los agentes limitados a comandos de shell no estructurados. El hallazgo valida las interfaces MCP estructuradas para la efectividad de los agentes. 

  7. Documentación de Claude Code CLI, code.claude.com. Sistema de hooks, configuración de MCP, delegación a subagentes y definiciones de agentes. 

  8. SwiftFormat, github.com/nicklockwood/SwiftFormat. La herramienta de formateo de Swift utilizada en hooks PostToolUse para mantener un estilo de código consistente. 

  9. Sitio oficial de XcodeBuildMCP, xcodebuildmcp.com. Confirma 59 herramientas MCP mediante ejemplo de salida de CLI. Categorías de herramientas: simulador, dispositivo, depuración y automatización de UI. Instalación vía Homebrew o npx. 

  10. Swiftjective-C, “Agentic Coding in Xcode 26.3 with Claude Code and Codex,” swiftjectivec.com, febrero de 2026. Confirma que Xcode 26.3 incluye soporte nativo para Claude Agent y el runtime de Codex a través de Settings > Intelligence. 20 herramientas MCP expuestas mediante xcrun mcpbridge

  11. Blake Crosley, “Two MCP Servers Made Claude Code an iOS Build System,” blakecrosley.com/blog/xcode-mcp-claude-code, febrero de 2026. Guía de configuración paso a paso y resultados reales del flujo de trabajo de desarrollo iOS del mismo autor. 

NORMAL ios-agent-development.md EOF