Crear apps para iOS con agentes de IA: guía para profesionales
# Crea apps para iOS más rápido con agentes de IA. Claude Code, Codex CLI, Xcode 26.3 native, MCP, patrones de CLAUDE.md, hooks y lecciones de 8 apps.
En breve: Tres entornos de ejecución de agentes ya entregan código para iOS: Claude Code CLI con MCP, Codex CLI con MCP y los agentes nativos de Intelligence de Xcode 26.3. Dos servidores MCP (XcodeBuildMCP con 59 herramientas y
xcrun mcpbridgede Apple con 20 herramientas) les 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 lo que funciona y lo que falla, a partir de 8 apps de producción para iOS que suman 293 archivos Swift.18 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 lanza una app para iOS” se cruza con configuración, no con prompts.
He creado 8 apps para iOS con agentes de programación con IA. No prototipos: apps en App Store, con integraciones de HealthKit, shaders de 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, los agentes hicieron la mayor parte de la autoría línea por línea; yo me encargué de la revisión, el alcance y las partes que requieren criterio humano (pulido visual, firma, ajuste de rendimiento y envío a App Store).
Esta guía es la referencia que me hubiera gustado tener cuando empecé. Cubre todo el stack: qué entorno de ejecución de agentes usar, cómo configurar servidores MCP para acceso estructurado a compilación, qué poner en tu CLAUDE.md, qué hooks evitan que el agente destruya tu proyecto de Xcode y, algo crítico, dónde fallan los agentes y necesitas tomar el control.
Puntos clave
Para desarrolladores de iOS que empiezan con agentes de IA:
- Empieza con Claude Code CLI + XcodeBuildMCP. Es el entorno de ejecución más maduro y con la cobertura más profunda de herramientas MCP. Instala dos comandos, agrega un CLAUDE.md a tu proyecto y el agente podrá compilar, probar y depurar sin que tengas que copiar mensajes de error.
- Nunca dejes que un agente modifique .pbxproj. Esta es la regla más importante. Un hook PreToolUse que bloquea escrituras en
.pbxprojy.xcodeproj/te ahorrará horas de recuperación. - Tu CLAUDE.md es el documento de onboarding del agente. Las horas que inviertas en él se amortizan en cada sesión de agente que toca el proyecto.
Para usuarios experimentados de agentes que agregan iOS a su flujo de trabajo:
- MCP transforma el ciclo de compilación de iOS. Antes de MCP, los agentes escribían Swift, pero no podían verificar si compilaba. 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 necesidades distintas. Claude Code CLI para sesiones agentivas profundas, Codex CLI para trabajo batch 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. Tus formateadores PostToolUse, bloqueadores PreToolUse y hooks de ejecución de pruebas existentes funcionan igual en proyectos iOS con ajustes menores de rutas.
Para líderes de equipo que evalúan el 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 salida del agente que una app de 14 archivos sin documentación.
- El límite de .pbxproj no es negociable. 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 honesto: los agentes manejan la mayor parte de la implementación en proyectos bien documentados — visible en la app de TV de 15 archivos lanzada en 3 horas de trabajo asistido por agente (caso de estudio más abajo). El trabajo restante — pulido visual, firma, ajuste de rendimiento y envío a App Store — requiere criterio humano.
Elige tu camino
| Lo que necesitas | Ve aquí |
|---|---|
| Configurar MCP por primera vez | Configuración de MCP: la configuración completa — instala ambos servidores, verifica y 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 — formateo al guardar, protección de .pbxproj, ejecutores de pruebas |
| Referencia profunda (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. Empieza donde encaje tu nivel de experiencia:
| Experiencia | Empieza aquí | Luego explora |
|---|---|---|
| Nuevo en iOS + agentes | Requisitos previos → Configuración de MCP → Tu primera sesión con agente | Patrones de CLAUDE.md, qué funciona/qué no |
| Desarrollador iOS, nuevo en agentes | Tres entornos de ejecución → Configuración de MCP → CLAUDE.md | Hooks, patrones de arquitectura |
| Usuario de agentes, nuevo en iOS | Patrones de arquitectura → Lo que los agentes hacen mal → CLAUDE.md | Contexto específico de frameworks, flujos de trabajo avanzados |
| Con experiencia en ambos | Flujos de trabajo avanzados → Hooks → Patrones multiplataforma | Comparación de entornos de ejecución, el portafolio |
Tabla de contenidos
- El portafolio: 8 apps, 293 archivos
- Requisitos previos
- Tres entornos de ejecución de agentes para iOS
- Configuración de MCP: la configuración completa
- Patrones de CLAUDE.md para proyectos iOS
- Tu primera sesión con agente
- Lo que los agentes hacen bien en iOS
- Lo que los agentes hacen mal en iOS
- Hooks para desarrollo iOS
- Patrones de arquitectura que funcionan con agentes
- Contexto específico de frameworks
- Patrones multiplataforma
- Flujos de trabajo avanzados
- Casos de estudio reales
- Ciclo de vida de proyectos con agentes
- Configuración de definiciones de agentes
- Patrones de pruebas para iOS asistido por agentes
- Gestión de la ventana de contexto para proyectos iOS
- Solución de problemas
- Errores comunes de agentes en iOS
- La evaluación honesta
- FAQ
- Tarjeta de referencia rápida
- Referencias
Recursos relacionados
| Tema | Recurso |
|---|---|
| Configuración de MCP para Xcode (artículo más corto) | Dos servidores MCP convirtieron Claude Code en un sistema de compilación para iOS |
| Referencia completa de Claude Code CLI | Claude Code CLI: la guía completa |
| Referencia de Codex CLI | Codex CLI: la guía completa |
| Análisis profundo del sistema de hooks | Anatomy of a Claw: 84 Hooks as an Orchestration Layer |
| Patrones de arquitectura de agentes | Guía de arquitectura de agentes |
| App de escritorio para Mac + Remote Control | Claude Code Mac Desktop + Remote Control: guía para usuarios de CLI |
Serie Apple Ecosystem. 21 artículos de producción sobre apps SwiftUI que se integran con Apple Intelligence, MCP, Foundation Models, Vision, Core ML y el stack de frameworks de iOS 26. Basada en Water, Get Bananas, Return y el resto del portafolio 941:
Hub de la serie: Serie Apple Ecosystem
Agentic Apple (E4):
| Tema | Recurso |
|---|---|
| Superficie de intent de Apple Intelligence | App Intents son la nueva API de Apple para tu app |
| Servidor MCP junto a una app iOS | Dos ecosistemas de agentes, una lista de compras |
| Cuándo usar cuál | App Intents vs. herramientas MCP: la pregunta de enrutamiento |
| LLM en dispositivo como función de runtime vs. herramienta | Foundation Models + flujo de trabajo agentivo |
| Hooks para desarrollo Apple | Hooks para desarrollo Apple |
| Estado entre procesos | Fuente única de verdad: SwiftData + MCP + iCloud |
Frameworks (E2/E3):
| Tema | Recurso |
|---|---|
| LLM en dispositivo con Foundation Models | LLM en dispositivo con Foundation Models |
| Framework Vision (primitivas de CV) | Framework Vision: lo que incluye |
| Patrones de inferencia con Core ML | Inferencia en dispositivo con Core ML |
| Modelo mental espacial de RealityKit | RealityKit y el modelo mental espacial |
| Internals de SwiftUI | De qué está hecho SwiftUI |
| Vocabulario de animación de Symbol Effects | Symbol Effects: el vocabulario de animación integrado de SwiftUI |
| Liquid Glass en iOS 26+ | Liquid Glass en SwiftUI: tres patrones |
Código lanzado (E1):
| Tema | Recurso |
|---|---|
| Máquina de estados de Live Activities | Máquina de estados de Live Activities |
| Contrato de runtime de watchOS | Contrato de runtime de watchOS |
| Disciplina de schema de SwiftData | Disciplina de schema de SwiftData |
| Patrones de HealthKit + SwiftUI | HealthKit + SwiftUI en iOS 26 |
| SwiftUI multiplataforma | Cinco plataformas Apple, tres archivos compartidos |
| Integración de XcodeBuildMCP | Dos servidores MCP, un proyecto de Xcode |
Síntesis (E5):
| Tema | Recurso |
|---|---|
| Tres superficies de una app iOS | Las tres superficies de una app iOS |
| Decisiones de targets de plataforma | La matriz de plataformas Apple |
| Sobre qué me niego a escribir | Sobre qué me niego a escribir |
El portafolio: 8 apps, 293 archivos
Antes de entrar en la configuración, aquí tienes de dónde sale esta guía. No son proyectos de juguete: abarcan cinco frameworks de Apple, tres plataformas y todo el rango de complejidad de 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 con iCloud Drive + servidor MCP para Claude Desktop | 53 | CRUD completo, sincronización con iCloud, servidor MCP personalizado que expone los datos de la app a Claude Desktop |
| Ace Citizenship | app de estudio en SwiftUI + backend FastAPI | 26 | Cliente-servidor, integración con API REST, motor de cuestionarios |
| TappyColor | juego de emparejamiento de colores con SpriteKit | 30 | Bucle de juego, física, manejo táctil, efectos de partículas |
| Return | temporizador de meditación zen: iOS 26+, watchOS, tvOS | 63 | HealthKit, Live Activities, ejecución extendida en Watch, navegación de enfoque en TV, sincronización de sesiones con 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 | seguimiento de entrenamientos con SwiftUI + SwiftData | 14 | App mínima viable, patrones limpios de SwiftData |
| Water | seguimiento de hidratación con SwiftUI + SwiftData + Metal + HealthKit | 34 | Simulación de fluidos con Metal, registro de ingesta de agua en HealthKit, widget |
| Starfield Destroyer | shooter espacial con SpriteKit + Metal | 32 | 99 niveles, 8 naves, tablas de clasificación de Game Center, posprocesamiento con Metal |
Por qué importan los conteos de archivos: La efectividad de los agentes se correlaciona con la legibilidad del proyecto, no con su tamaño. Return (63 archivos) produce mejores resultados de agentes 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.
Requisitos previos
Antes de configurar cualquier runtime de agentes para desarrollo iOS:
Fecha límite de App Store Connect: A partir del 28 de abril de 2026, las cargas de apps a App Store Connect deben compilarse con Xcode 26 o posterior usando SDKs para iOS 26, iPadOS 26, tvOS 26, visionOS 26 o watchOS 26.12 (Los envíos para macOS no están sujetos a este requisito). Si tu equipo todavía está en Xcode 16.x, la cadena de herramientas asistida por agentes de esta guía también funciona como una presión útil para actualizar: de todos modos, ninguno de los servidores MCP siguientes funciona sin Xcode 26.3+.
Obligatorio:
- macOS 15+ (Sequoia) o macOS Tahoe
- Xcode 26.3+ instalado y configurado (el mínimo para xcrun mcpbridge); se recomienda Xcode 26.5+ para las mejoras del flujo de trabajo con agentes: cola de mensajes en el asistente de codificación y soporte para preguntas aclaratorias, además de adjuntos de imágenes en Swift Testing, severidad de problemas registrados, advertencias de fallos en pruebas de UI con crashlogs y mejoras del editor de String Catalog, agregadas por primera vez en 26.4.1314 Xcode 26.5 (11 de mayo de 2026, build 17F42) es la versión estable más reciente; 26.4.1 (16 de abril de 2026, build 17E202) fue la última versión de corrección de errores de la línea 26.4.15
- Al menos un runtime de iOS Simulator instalado
- Una cuenta API de Anthropic (para Claude Code) o una cuenta de OpenAI (para Codex)
Recomendado:
- SwiftFormat instalado (brew install swiftformat): se usa en 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 la línea de comandos o se integran con ella
Verifica tu instalación de Xcode:
# Check Xcode version
xcodebuild -version
# Expected: Xcode 26.3 or later (26.5+ recommended)
# Check available simulators
xcrun simctl list devices available
# Expected: at least one iPhone simulator
# Verify xcrun mcpbridge is available
xcrun mcpbridge --help
# Expected: usage information (not "command not found")
Si xcrun mcpbridge devuelve “command not found”, necesitas Xcode 26.3 o posterior. Instala o actualiza Xcode desde App Store o developer.apple.com. Nota: xcode-select --install solo instala Command Line Tools, que no incluye mcpbridge; necesitas la Xcode.app completa.
Tres entornos de ejecución de agentes para iOS
Tres entornos de ejecución distintos pueden escribir, compilar y probar código de iOS. No son intercambiables: cada uno tiene fortalezas diferentes, distintos patrones de integración con MCP y casos de uso ideales diferentes.
1. Claude Code CLI
Qué es: El asistente de codificación agéntico basado en terminal de Anthropic. Lee tu base de código, ejecuta comandos, modifica archivos y se conecta a herramientas externas a través de MCP.
Integración con MCP: Soporte completo tanto para XcodeBuildMCP como para el MCP de Xcode de Apple. El agente descubre las herramientas mediante 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
Alternativa — Instalador automático xcodebuildmcp init (v2.1.0+, 2026-02-23):
Si prefieres saltarte el cableado manual de MCP, XcodeBuildMCP v2.1.0+ incluye un subcomando init que detecta automáticamente Claude Code, Cursor o Codex e instala las skills del agente y la configuración de MCP en un solo paso:
xcodebuildmcp init
# Or without a global install:
npx -y xcodebuildmcp@latest init
Flags: --print (escribe la configuración en stdout para clientes no compatibles), --uninstall (eliminar). Sáltatelo si quieres control explícito sobre qué servidores MCP se conectan y a qué nivel; las invocaciones manuales de claude mcp add mostradas arriba te dan ese control.16
Mejor para: Sesiones profundas de implementación: construir nuevas funciones, refactorizar a través de múltiples archivos, depurar problemas complejos y ejecutar bucles de compilación-prueba-corrección de forma autónoma. La ventana de contexto de 1M de Claude Code (con Opus 4.6) significa que el agente puede mantener en memoria de trabajo la mayoría de proyectos iOS pequeños y medianos: en mi experiencia, hasta unos 50 archivos según su tamaño.
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 previo a MCP: el agente nunca te pide compilar manualmente ni pegar la salida de errores. El bucle compilación-error-corrección es autónomo.
2. Codex CLI
Qué es: El agente de codificació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 admite 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 a través del mismo comando npx:
# Add XcodeBuildMCP to Codex
codex mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp
Mejor para: Operaciones por lotes sin interfaz, integración con CI/CD y tareas en las que quieras una segunda opinión de una familia de modelos diferente. El modo sandbox de Codex ejecuta el código en entornos aislados, lo que resulta útil para operaciones destructivas como ejecuciones de suites de pruebas que modifican el estado.
Diferencias clave respecto a Claude Code:
- Usa modelos de OpenAI en lugar de modelos de Claude
- Tamaños de ventana de contexto y economía de tokens diferentes
- Modelo de permisos sandbox-first (más restrictivo por defecto)
- Ecosistema MCP más pequeño (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 que revise el código escrito por el primero detecta diferentes tipos de errores. El flujo de colaboración (Claude construye, Codex revisa) es efectivo para iOS porque los patrones de SwiftUI que parecen correctos a una familia de modelos pueden tener problemas sutiles que otra detecta. Los shaders de 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 codificació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:
- Abre Xcode 26.3+
- Navega a Settings > Intelligence
- Agrega un nuevo proveedor:
- Para Claude: Selecciona “Claude Agent” e ingresa tu clave de API de Anthropic
- Para Codex: Selecciona “Codex” e ingresa tu clave de API de OpenAI
- El agente aparece en la barra lateral Intelligence y puede invocarse en línea
Mejor 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, destinos de compilación, configuración de esquemas— sin necesidad de un puente MCP.
Limitaciones en comparación con los agentes CLI: - Sin sistema de hooks: no puedes forzar formateo 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 o la selección actual, no sobre todo el proyecto - Sin delegación a subagentes: las tareas complejas de varios pasos no pueden paralelizarse - Sin configuración de servidores MCP: el agente solo usa las herramientas integradas de Xcode
Cuándo usar los agentes nativos de Xcode:
Para ediciones rápidas y acotadas donde cambiar a la terminal supone una sobrecarga. “Agrega una propiedad calculada a este modelo.” “Escribe una prueba unitaria para esta función.” “Refactoriza esta vista para que use @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 entre múltiples archivos o corregir errores de forma autónoma, usa un agente CLI con MCP.
Matriz comparativa de entornos de ejecución
| Capacidad | Claude Code CLI | Codex CLI | Xcode 26.3 nativo |
|---|---|---|---|
| Soporte de 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 / configuración del proyecto | Sí | Equivalente codex.md | No |
| Compilación-prueba-corrección autónoma | 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 el modelo | Varía según el proveedor |
| Operaciones multi-archivo | Acceso a toda la base de código | Acceso a toda la base de código | Archivo actual / selección |
| Protección de .pbxproj | Mediante hooks | Manual | N/A (usa Xcode de forma nativa) |
| Formateo al guardar | Mediante hooks PostToolUse | Herramientas externas | Configuración de Xcode |
| Capacidad sin conexión | No | No | No |
| Modelo de coste | Uso de API de Anthropic | Uso de API de OpenAI | Uso de API del proveedor |
La recomendación: Usa Claude Code CLI como tu entorno de ejecución 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 configuración completa
MCP (Model Context Protocol) es lo que transforma a un agent de “escribe Swift y espera que tú lo compiles” a “escribe Swift, lo compila, lee errores estructurados y los corrige”. Esta sección profundiza más que el artículo del blog: cubre ambos servidores, todos los métodos de instalación, la verificación y la configuración del agent que garantiza que las herramientas realmente se usen.
XcodeBuildMCP: 59 herramientas para desarrollo iOS sin interfaz gráfica
XcodeBuildMCP envuelve xcodebuild, xcrun simctl y LLDB en 59 herramientas MCP estructuradas. Funciona sin que Xcode esté abierto: todo el ciclo de compilación, pruebas y depuración opera sin interfaz gráfica 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 flag -s user hace que el servidor esté disponible globalmente en todos los proyectos. Omítela para una instalación limitada al 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 informes de fallos. XcodeBuildMCP incluye Sentry de forma predeterminada, lo que envía datos de errores, incluidas rutas de archivos. Exclúyete a menos que quieras aportar 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 |
Encuentran archivos .xcodeproj/.xcworkspace y listan los schemes y targets disponibles |
| Compilación | build_sim, build_device, build_mac |
Compilan con salida estructurada de errores/advertencias JSON por archivo y línea |
| Pruebas | test_sim, test_device |
Ejecutan pruebas con resultados de aprobado/fallido por método |
| Ciclo de vida del Simulator | list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults |
Crean, inician, administran y configuran simuladores |
| Administración de dispositivos | list_devices, install_device, launch_device |
Despliegue y administración en dispositivos físicos |
| 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, con 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 |
Crean proyectos y agregan dependencias |
Las herramientas más importantes para el trabajo diario:
-
build_sim— La llamarás cientos de veces. Devuelve JSON con errores categorizados por archivo, línea y severidad. El agent lee el error, navega al archivo y lo corrige sin que tengas que tocar nada. -
test_sim— Devuelve resultados por método de prueba. El agent sabe exactamente qué prueba falló y por qué, no solo que “las pruebas fallaron”. -
list_sims+boot_sim— Administración de simuladores sin memorizar flags dexcrun simctl. El agent descubre los runtimes disponibles y elige un dispositivo adecuado. -
discover_projs+list_schemes— Introspección del proyecto. El agent no necesita adivinar el nombre de tu scheme ni la estructura de tu workspace. -
debug_attach_sim+debug_stack+debug_variables— Depuración remota con LLDB. El agent puede configurar breakpoints, inspeccionar variables y avanzar por el código sin que abras el depurador.
Apple Xcode MCP: 20 herramientas que hacen puente hacia Xcode
El servidor MCP de Apple viene 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, todas las llamadas MCP a través de este servidor fallarán o se quedarán colgadas. 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 |
Leen/escriben archivos dentro del contexto del proyecto de Xcode |
| Compilación y pruebas | BuildProject, GetBuildLog, RunAllTests, RunSomeTests |
Compilan y prueban 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 en Swift REPL y búsqueda en la documentación de Apple |
| Previews | RenderPreview |
Renderizado de previews SwiftUI sin interfaz gráfica |
Herramientas que son exclusivas de Apple MCP (no disponibles en XcodeBuildMCP):
-
DocumentationSearch— Busca en la documentación para desarrolladores de Apple, incluidas sesiones de WWDC. Es más rápida y confiable que la búsqueda web para preguntas sobre API de Apple. Pregunta “is HKQuantityType(.dietaryWater) valid?” y obtén una respuesta definitiva desde la fuente. -
ExecuteSnippet— Ejecución en Swift REPL dentro del contexto del proyecto. El agent puede verificar el comportamiento de API, probar conversiones de tipos y validar expresiones sin compilar toda la app. -
RenderPreview— Renderiza previews SwiftUI sin interfaz gráfica. El agent 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). -
XcodeListNavigatorIssues— Devuelve diagnósticos en tiempo real del analizador de Xcode, no solo errores de compilación. Detecta problemas como variables sin usar, posibles ciclos de retención y advertencias de obsolescencia que el sistema de compilación no muestra.
Por qué usar ambos servidores
Se superponen en compilaciones y pruebas, pero difieren de forma fundamental:
┌─────────────────────────────────────────────────────────────────┐
│ 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 administración más completa de simuladores y dispositivos. Esta es tu herramienta principal de compilación.
Usa Apple Xcode MCP para: Consultas de documentación, verificación en Swift REPL, renderizado de previews 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 ~90% de las llamadas MCP y Apple Xcode MCP para documentación y verificación en REPL. El agent usa XcodeBuildMCP de forma predeterminada para compilaciones y pruebas porque es más rápido (sin 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 muestra “Disconnected” o no aparece:
- XcodeBuildMCP no se conecta: Asegúrate de que Node.js esté instalado (
node --version). El comandonpxrequiere Node.js 18+. - Apple Xcode MCP no se conecta: Asegúrate de que Xcode 26.3+ esté instalado y de que el comando
xcrun mcpbridgefuncione en tu terminal. Abre Xcode al menos una vez para aceptar el acuerdo de licencia. - Ninguno de los dos aparece: Reinicia Claude Code (
claudeen una terminal nueva). Es posible que los servidores MCP registrados a mitad de sesión no aparezcan hasta reiniciar.
Enseñarle al agent a usar MCP
Instalar servidores MCP es necesario, pero no suficiente. Sin orientación explícita, el agent puede volver a ejecutar xcodebuild mediante Bash (salida no estructurada, tokens de contexto desperdiciados) o usar búsqueda web para la documentación de Apple (más lenta y menos confiable).
Agrega esto a tu CLAUDE.md o definición del agent:
## Build & Test — Always Use MCP
Prefer MCP tools over raw shell commands for ALL build operations:
- **Build**: `build_sim` / `build_device` (NOT `xcodebuild` via Bash)
- **Test**: `test_sim` / `test_device` (NOT `xcodebuild test` via Bash)
- **Simulators**: `list_sims`, `boot_sim`, `open_sim` (NOT `xcrun simctl` via Bash)
- **Debug**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Apple docs**: `DocumentationSearch` (NOT WebSearch for Apple APIs)
- **Swift verification**: `ExecuteSnippet` (NOT `swift` via Bash)
- **Previews**: `RenderPreview` for headless SwiftUI verification
MCP returns structured JSON. Bash returns unstructured text.
Structured data means fewer tokens consumed and better error diagnosis.
Esta orientación garantiza que el agent recurra primero a las herramientas MCP. Sin ella, verás que el agent construye comandos largos de xcodebuild mediante Bash, consume miles de tokens de contexto al analizar la salida y, a veces, identifica incorrectamente 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 una contratación nueva que leyó la documentación de arquitectura y una que está adivinando.
Cada proyecto iOS que mantengo tiene un CLAUDE.md. Estos son los patrones que funcionan, extraídos de las 8 apps.
Las secciones esenciales
Todo CLAUDE.md de 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 deployment target antes de escribir cualquier código. Un agente orientado a iOS 17 usará NavigationView y @ObservedObject. Un agente orientado a iOS 26 usará NavigationStack y @Observable. El bundle ID importa para los 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. flexible).
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 de mayor impacto que puedes escribir. Cuando el agente decide dónde agregar una función nueva, estas anotaciones lo guían al archivo correcto desde el primer intento, en lugar de obligarlo a leer cada archivo para entender la estructura del proyecto.
Antipatrón: listar archivos sin anotaciones. TimerManager.swift no le dice nada al agente sobre si maneja estado, UI o ambas cosas. TimerManager.swift # Timer state, logic, and repeat handling le dice 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:
```bash
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```
Run tvOS tests:
```bash
xcodebuild -scheme ReturnTV -destination 'platform=tvOS Simulator,name=Apple TV' test
```
**Prefer MCP tools** (`build_sim`, `test_sim`) over these raw commands.
MCP returns structured JSON with categorized errors.
Incluye los comandos sin procesar aunque el agente debería preferir MCP. Los comandos sin procesar funcionan como documentación de respaldo y hacen explícitos los nombres de schemes y destinos.
4. Patrones y reglas clave
## 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, a veces el agente usará ObservableObject en un archivo y @Observable en otro, o creará un mecanismo de configuración nuevo en lugar de usar el singleton existente Settings.shared.
5. Cosas 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 con más fiabilidad que sugerencias positivas, porque son binarias (hazlo / no lo hagas) en lugar de heurísticas (prefiere esto / a veces usa aquello).
6. Contexto específico del framework
Esta sección varía según la app. 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)
Aquí tienes un ejemplo anotado que muestra cómo las seis secciones trabajan juntas en una app de complejidad moderada. Este es el patrón de CLAUDE.md que uso para Banana List, una app de lista de compras de 53 archivos con sincronización de 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
## File Structure
```
BananaList/
├── BananaListApp.swift # App entry, model container setup
├── Models/
│ ├── GroceryList.swift # @Model: list with name, items, color
│ ├── GroceryItem.swift # @Model: item with name, quantity, category, isCompleted
│ ├── Category.swift # @Model: user-defined categories
│ └── SampleData.swift # Preview and test data
├── Views/
│ ├── ListsView.swift # Main list of grocery lists
│ ├── ListDetailView.swift # Items within a list
│ ├── ItemRow.swift # Single item row with swipe actions
│ ├── AddItemSheet.swift # New item form
│ ├── CategoryPicker.swift # Category selection with create-new
│ └── SettingsView.swift # App settings
├── Managers/
│ ├── CloudSyncManager.swift # iCloud Drive sync status and conflict resolution
│ └── HapticManager.swift # UIImpactFeedbackGenerator wrapper
├── MCP/
│ ├── MCPServer.swift # MCP server for Claude Desktop integration
│ ├── ListTools.swift # MCP tools: list CRUD operations
│ └── ItemTools.swift # MCP tools: item CRUD operations
└── Extensions/
├── Color+Extensions.swift # Custom color definitions
└── View+Extensions.swift # Reusable view modifiers
```
## SwiftData Models
### Relationships
- `GroceryList` has many `GroceryItem` (cascade delete)
- `GroceryItem` belongs to one `GroceryList` (required)
- `GroceryItem` has optional `Category`
- `Category` has many `GroceryItem` (nullify on delete)
### Container Setup
```swift
@main
struct BananaListApp: App {
var body: some Scene {
WindowGroup {
ListsView()
}
.modelContainer(for: [GroceryList.self, GroceryItem.self, Category.self])
}
}
```
### Query Patterns
- Lists: `@Query(sort: \GroceryList.name) var lists: [GroceryList]`
- Active items: `@Query(filter: #Predicate { !$0.isCompleted })`
- By category: filter in-memory after fetch (SwiftData predicate limitations)
## Build & Test
```bash
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```
Prefer MCP tools (`build_sim`, `test_sim`) over raw commands.
## Key Patterns
### Observable + SwiftData
- SwiftData `@Model` classes are automatically Observable
- DO NOT add `@Observable` to `@Model` classes (redundant, causes warnings)
- Use `@Bindable` for two-way bindings to model properties in forms
- Use `@Query` in views, `modelContext.fetch()` in non-view code
### iCloud Sync
- Automatic via SwiftData CloudKit integration
- Conflict resolution: last-write-wins (CloudKit default)
- Sync status exposed via `CloudSyncManager.shared.syncState`
- Test sync by running on two simulators with same iCloud account
### MCP Server Architecture
- Runs as a local WebSocket server on port 8765
- Exposes 6 tools: listAll, getList, createList, addItem, completeItem, deleteItem
- Claude Desktop connects via MCP config in `~/.config/claude-desktop/config.json`
## Rules
- NEVER modify .pbxproj or .xcodeproj contents
- NEVER change the model schema without updating SampleData.swift
- NEVER use `ObservableObject` — SwiftData models are already Observable
- NEVER use `@StateObject` — use `@State` with `@Observable` classes
- NEVER use `NavigationView` — always `NavigationStack`
- NEVER add `@Observable` macro to `@Model` classes
- ALWAYS use `@Bindable` for form bindings to model properties
- ALWAYS test iCloud sync changes on two simulator instances
CLAUDE.md real: Reps (app SwiftData mínima: 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 corto cubre las seis secciones esenciales:
# 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 entender el grafo de escenas, las categorías de física y la máquina de estados del juego:
# Starfield Destroyer - Space Shooter
**Bundle ID:** `com.941apps.StarfieldDestroyer`
**Target:** iOS 26+
**Architecture:** SpriteKit + Metal post-processing + Game Center
**Swift version:** 6.2
## Game Overview
99 levels across 3 galaxies. 8 unlockable ships with different stats.
Game Center leaderboards and achievements. Metal shader post-processing
for bloom and screen effects.
## File Structure
```
StarfieldDestroyer/
├── StarfieldDestroyerApp.swift # App entry, Game Center auth
├── GameScene.swift # Main game scene, update loop
├── MenuScene.swift # Title screen, ship selection
├── Entities/
│ ├── PlayerShip.swift # Player node with physics, weapons, shields
│ ├── EnemyShip.swift # Enemy base class with AI behaviors
│ ├── Bullet.swift # Bullet pool node
│ ├── PowerUp.swift # Collectible power-ups
│ └── Boss.swift # Boss enemies (levels 33, 66, 99)
├── Systems/
│ ├── LevelManager.swift # Level progression, wave spawning
│ ├── PhysicsCategory.swift # UInt32 bitmask categories
│ ├── CollisionHandler.swift # Contact delegate methods
│ ├── ScoreManager.swift # Score tracking, multipliers
│ ├── ParticleManager.swift # Explosion, trail, shield emitters
│ └── AudioManager.swift # Sound effects, background music
├── UI/
│ ├── HUDNode.swift # Score, health, level display
│ ├── ShipSelectView.swift # SwiftUI ship selection (UIHostingController)
│ ├── GameOverView.swift # Game over screen with score submission
│ └── PauseMenu.swift # Pause overlay
├── Metal/
│ ├── MetalRenderer.swift # Post-processing render pipeline
│ ├── BloomShader.metal # Bloom post-process effect
│ └── ShaderTypes.h # Shared uniforms (bridging header)
├── Data/
│ ├── ShipData.swift # 8 ship definitions (speed, damage, shields)
│ ├── LevelData.swift # 99 level configurations
│ └── AchievementData.swift # Game Center achievement definitions
└── GameCenterManager.swift # Leaderboard/achievement submission
```
## SpriteKit Scene Hierarchy
```
GameScene (SKScene)
├── backgroundLayer (zPosition: -100)
│ └── StarfieldNode (parallax scrolling, 3 layers)
├── gameLayer (zPosition: 0)
│ ├── playerShip (zPosition: 10)
│ ├── enemyContainer (zPosition: 5)
│ ├── bulletPool (zPosition: 8) — pre-allocated 50 bullets
│ └── powerUpContainer (zPosition: 3)
├── effectsLayer (zPosition: 50)
│ └── ParticleManager (explosion + trail emitters)
└── hudLayer (zPosition: 100)
├── scoreLabel (SKLabelNode)
├── healthBar (custom SKShapeNode)
└── levelLabel (SKLabelNode)
```
## Physics Categories
```swift
struct PhysicsCategory {
static let none: UInt32 = 0
static let player: UInt32 = 0b1 // 1
static let enemy: UInt32 = 0b10 // 2
static let bullet: UInt32 = 0b100 // 4
static let powerUp: UInt32 = 0b1000 // 8
static let shield: UInt32 = 0b10000 // 16
static let bossBullet:UInt32 = 0b100000 // 32
}
// Contact pairs:
// player + enemy → damage
// player + powerUp → collect
// bullet + enemy → destroy
// player + bossBullet → damage
```
## Game State Machine
```
.menu → .playing → .paused → .playing
→ .gameOver → .menu
→ .bossIntro → .playing
→ .levelComplete → .playing (next level)
```
## Metal Post-Processing
- Bloom shader: `BloomShader.metal` — multi-pass Gaussian blur + additive blend
- Uniforms: `PostProcessUniforms { float intensity; float threshold; float2 resolution; }`
- Applied after SpriteKit renders each frame via `SKView.presentScene(:transition:)`
- DO NOT modify Metal shaders without testing on device
## Build & Test
```bash
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```
## Rules
- NEVER modify .pbxproj
- NEVER modify PhysicsCategory bitmasks (breaks all collision detection)
- NEVER change the scene hierarchy z-ordering without understanding render order
- NEVER modify ShaderTypes.h without updating both Swift and Metal references
- Add new enemies by subclassing EnemyShip, not by modifying it
- Bullet pooling: recycle via removeFromParent() + re-add, never allocate new
- Game Center: always check isAuthenticated before submitting scores
CLAUDE.md real: amp97 (Metal + visualización de audio: 41 archivos)
Los proyectos de Metal necesitan el mayor contexto específico del 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
Escalar CLAUDE.md según el tamaño del proyecto
El nivel adecuado de detalle depende de la cantidad de archivos y de la complejidad del framework:
| Tamaño del proyecto | Profundidad de CLAUDE.md | Ejemplo |
|---|---|---|
| Pequeño (< 20 archivos) | Identidad + lista de archivos + reglas | Reps (14 archivos): patrones básicos de SwiftData, comandos de build, prohibiciones |
| Mediano (20-40 archivos) | + contexto del framework + patrones clave | TappyColor (30 archivos): jerarquía de escenas 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 cross-platform, diagrama de sincronización de sesiones, diferencias por plataforma |
| Especializado (Metal/GPU) | + diagramas de pipeline + definiciones de tipos compartidos + diseños de buffers | amp97 (41 archivos): etapas del render pipeline, struct de uniforms, gestión de buffers |
El costo de documentar de más es casi cero (el agente omite lo que no necesita). El costo de documentar de menos es alto (el agente inventa patrones que entran en conflicto con tu codebase).
Checklist de CLAUDE.md
Usa esta checklist 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 build con scheme y destino correctos
- [ ] Comando de test con scheme y destino correctos
- [ ] Preferencia por MCP indicada (“prefer build_sim over 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 de plataforma documentados (#if canImport, #if os)
- [ ] Singletons clave y patrones compartidos documentados
- [ ] Limitaciones conocidas o gotchas señalados
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. Esto usa Claude Code CLI, pero el flujo de trabajo aplica a cualquier runtime.
Paso 1: Verifica que el agente pueda ver tu proyecto
You: Summarize this project. What scheme should I build with?
Claude: [reads CLAUDE.md]
[calls discover_projs via MCP]
[calls list_schemes via MCP]
This is Return, a zen meditation timer for iOS 26+, watchOS, and tvOS.
Available schemes: Return, ReturnWatch, ReturnTV, ReturnTests.
Primary scheme for iOS: Return.
Si el agente no hace referencia al contenido de tu CLAUDE.md, revisa que el archivo esté en la raíz del proyecto (el mismo directorio que .xcodeproj o Package.swift).
Paso 2: Ejecuta un build de verificación de estado
You: Build the Return scheme for iOS simulator and report results.
Claude: [calls list_sims — finds iPhone 16 Pro on iOS 26.2]
[calls boot_sim — boots the simulator]
[calls build_sim — builds the project]
Build succeeded. 63 source files compiled.
2 warnings:
- HomeView.swift:132 — UIScreen.main deprecated in iOS 26.0
- LogWaterIntent.swift:61 — Result of try? is unused
0 errors.
Paso 3: Ejecuta las pruebas
You: Run all tests and report pass/fail.
Claude: [calls test_sim]
12 tests executed:
✓ TimerManagerTests (5/5 passed)
✓ SettingsTests (4/4 passed)
✓ ConstantsTests (3/3 passed)
All tests passed.
Paso 4: Implementa una función
You: Add a new "Rain" theme to the theme system. Follow the existing
pattern in Theme.swift and ThemeManager.swift. Include a rain
ambient sound. Build and test after implementation.
Claude: [reads Theme.swift — understands Theme struct pattern]
[reads ThemeManager.swift — understands theme registration]
[reads existing theme definitions]
[adds Rain theme to Theme.swift following existing pattern]
[registers Rain theme in ThemeManager.swift]
[calls build_sim — build succeeds]
[calls test_sim — all tests pass]
Added Rain theme:
- Theme.swift: new `static let rain` with video, cover, ambient
- ThemeManager.swift: added to `allThemes` array
- Build: success (0 errors, 2 existing warnings)
- Tests: 12/12 passed
Note: You'll need to add rain_ambient.wav to the project
and add the new Theme.swift changes to the Xcode target manually
(I did not modify .pbxproj).
La 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.
Lo que los agentes hacen bien en iOS
Estas son las tareas donde los agentes producen de forma consistente resultados correctos y listos para producción con mínima revisión humana.
Vistas y modificadores de SwiftUI
Los agentes tienen un reconocimiento profundo de patrones para la sintaxis declarativa de SwiftUI. La composición de vistas, las cadenas de modificadores, los enlaces de estado y el layout se adaptan bien a los datos de entrenamiento del agente, porque la superficie de API de SwiftUI está bien documentada y sus patrones son muy consistentes.
Donde los agentes sobresalen:
- Crear 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 layout (de VStack a LazyVGrid, de List a ScrollView)
- Implementar enlaces de formulario con @Bindable para modelos SwiftData
- Crear preview providers 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 un resultado genérico. “Crea un SettingsView que coincida con el patrón existente en SettingsSheet.swift” produce un resultado coherente con tu codebase.
Modelos y consultas de SwiftData
Los agentes manejan de forma confiable la macro @Model de SwiftData, sus relaciones y los patrones de @Query. La naturaleza declarativa del framework (similar a Django ORM o SQLAlchemy) encaja bien con patrones que el agente ha visto en muchas codebases.
Donde los agentes sobresalen:
- Definir clases @Model con relaciones
- Escribir @Query con sort descriptors y predicados
- Implementar operaciones CRUD mediante modelContext
- Planes de migración entre versiones de esquema
- Datos de preview y fixtures de prueba
Donde los agentes necesitan guía:
- Expresiones #Predicate complejas (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 mediante SwiftData, pero el agente puede intentar implementar una sincronización manual)
Pruebas unitarias
Las pruebas unitarias escritas por agentes tienen una calidad consistentemente alta en proyectos iOS. El agente entiende los patrones de XCTest, los métodos de prueba async 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(), assertions apropiadas y manejo async para pruebas basadas en temporizadores.
Refactorización y aplicación de patrones
Los agentes sobresalen en la refactorización mecánica: extraer vistas en componentes, convertir ObservableObject a @Observable, migrar de NavigationView a NavigationStack y aplicar patrones consistentes en varios 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 avanza metódicamente por cada archivo, aplica la transformación correctamente y mantiene la funcionalidad existente. Este es trabajo de alto apalancamiento: 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 build mediante MCP
Con salida estructurada de MCP, los agentes diagnostican errores de build más rápido que la mayoría de los desarrolladores. El agente lee el JSON del error, identifica el archivo y la línea exactos, entiende el mensaje de error y aplica la corrección, a menudo en un solo turno.
Errores que los agentes corrigen de forma autónoma: - Imports faltantes - Incompatibilidades de tipos - Faltas de conformidad con protocolos - Uso obsoleto de API (con reemplazo) - Parámetros obligatorios faltantes en inicializadores - Violaciones de control de acceso
Errores con los que los agentes necesitan ayuda: - Resolución de tipos ambigua (varios módulos definen el mismo tipo) - Fallas complejas de constraints genéricos - Errores de expansión de macros (el agente no puede ver la salida expandida de macros)
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 mediante llamadas estructuradas de 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 de archivos .pbxproj — NUNCA
Esta es la regla más importante en el desarrollo de 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. En teoría es legible para humanos, pero en la práctica es 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) donde la posición importa - Cada entrada está referenciada de forma cruzada por UUID: agregar un archivo exige actualizar 3-5 secciones distintas de manera consistente - 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 la empeoran
Qué pasa cuando un agente edita .pbxproj: 1. La edición parece funcionar (el agente informa “file updated”) 2. Xcode se niega a abrir el proyecto (“The project file is corrupted”) 3. Pasas 15-60 minutos recuperándote desde el historial de git 4. Aprendes a agregar el hook PreToolUse (consulta Hooks)
El flujo de trabajo: El agente crea archivos Swift. Tú los agregas manualmente al proyecto de Xcode (arrastrándolos a Xcode, o con File > Add Files). Esto toma 5 segundos por archivo y evita horas de recuperación.
Para proyectos con Swift Package Manager: Esta limitación es menos grave. 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 toda la estructura 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 forma significativa. Son archivos XML con UUID generados automáticamente, referencias de constraints y conexiones de outlets, diseñados para edición visual, no para edición de texto.
La mitigación: Usa SwiftUI exclusivamente para vistas nuevas. Si tu proyecto tiene archivos heredados de Interface Builder, no los toques y crea 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:
- Perfilado con Instruments (herramienta visual, no accesible para agentes)
- Comprender las características de GPU/CPU del dispositivo específico
- Cambios iterativos guiados por mediciones
Dónde aparece esto: - Optimización de shaders Metal (el agente escribe Metal válido, pero no puede medir el tiempo de cuadro de GPU) - Complejidad del body de vistas SwiftUI (el agente crea vistas profundamente anidadas que generan sobrecarga de redibujado) - Optimización de consultas en Core Data / SwiftData (el agente escribe consultas correctas que pueden ser lentas con datasets grandes)
La mitigación: Usa agentes para la implementación, perfila manualmente con Instruments y luego pídele al agente que aplique optimizaciones específicas que ya identificaste.
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 a App Store son flujos de trabajo fundamentalmente operados por humanos que involucran el portal de Apple Developer, Keychain Access y la UI de firma de Xcode.
Lo que ve el agente: “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 mitigación: Maneja toda la firma en la pestaña Signing & Capabilities de Xcode. No pidas a los agentes que depuren fallas de firma.
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 GPU. Los shaders Metal se ejecutan en GPU; el agente no tiene ningún mecanismo de retroalimentación para saber si el shader produce resultados visuales correctos.
Qué pueden hacer los agentes con Metal:
- Escribir shaders de vértices y fragmentos a partir de descripciones
- Configurar el pipeline de renderizado Metal en Swift
- Crear compute shaders para operaciones paralelas sobre datos
- Corregir errores de compilación en archivos .metal
Qué no pueden hacer los agentes con Metal: - Verificar la corrección visual de la salida del shader - Depurar el rendimiento de GPU (tiempo de cuadro, occupancy, ancho de banda de memoria) - Diagnosticar artefactos visuales (banding, problemas de precisión, espacio de color incorrecto) - Probar en distintas arquitecturas de GPU (diferencias de comportamiento entre series A y M)
La mitigación: Prueba los shaders Metal en dispositivos físicos. La implementación de Metal del Simulator no representa el comportamiento de GPU en dispositivos. Usa GPU Frame Capture de Xcode para la 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 compile, pero no pueden decir si la pantalla resultante se ve correcta. Una vista que se renderiza 10 píxeles descentrada, usa el grosor de fuente incorrecto o tiene elementos superpuestos no produce errores de compilación y pasa todas las pruebas lógicas.
La mitigación: Revisa visualmente los cambios de UI. Usa SwiftUI Previews en Xcode (o RenderPreview mediante Apple MCP para renderizado headless) para verificar el layout. Considera pruebas de snapshots con bibliotecas como swift-snapshot-testing para detectar regresiones visuales de forma automatizada.
Hooks para el desarrollo de 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 cumplimiento: la diferencia entre “por favor, no edites .pbxproj” (una sugerencia que el agente puede ignorar) y “no puedes editar .pbxproj” (un bloqueo estricto).
Para más contexto sobre el sistema de hooks, consulta la guía de hooks de Claude Code. Esta sección cubre patrones de hooks específicos para iOS.
PreToolUse: bloquear escrituras en .pbxproj
El hook más importante en cualquier proyecto de iOS. Este bloquea que el agente escriba en archivos .pbxproj, directorios .xcodeproj/ y otros archivos gestionados por Xcode:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files. Create Swift files and add to Xcode manually.\" >&2; exit 2; fi'"
}
]
}
}
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 de .pbxproj
- Cualquier archivo dentro de directorios .xcodeproj/ o .xcworkspace/
- Archivos de Interface Builder (.xib, .storyboard)
PostToolUse: formateo al guardar 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é importa: Los agentes producen Swift sintácticamente correcto, pero no siguen las convenciones de formato de manera constante. SwiftFormat normaliza la indentación, la ubicación de llaves y el orden de imports. El hook de formateo al guardar significa que cada archivo Swift que toca el agente se formatea automáticamente antes de que lo veas.
Opcional: agrega un archivo de configuración .swiftformat a 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 un archivo 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 de lint bloqueen al agente. Si quieres que las infracciones de lint bloqueen, elimínalo.
PostToolUse: compilar automáticamente después de cambios
Para ciclos de feedback agresivos, activa una compilación después de cada cambio en un archivo 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 quieres feedback inmediato de compilación. Para el desarrollo normal, deja que el agente active compilaciones manualmente mediante 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
Este es el .claude/settings.json completo que uso en todos los proyectos de 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 2 garantías: 1. El agente no puede corromper archivos de proyecto de Xcode (bloqueo PreToolUse) 2. Cada archivo Swift que toca el agente se formatea automáticamente (formato PostToolUse)
Patrones de arquitectura que funcionan con agentes
No todas las arquitecturas de Swift son igual de fáciles 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 targets de iOS 26+ deben usar @Observable exclusivamente. Es tanto el patrón moderno como el patrón más 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 necesita anotaciones @Published), el modelo de propiedad es más claro (@State en lugar de @StateObject vs. @ObservedObject) y los agentes generan menos errores con él porque hay menos piezas móviles.
Documenta esto en CLAUDE.md: Incluso con iOS 26 como target, los agentes a veces vuelven a patrones de ObservableObject por sus datos de entrenamiento. Prohibirlo explícitamente lo evita.
NavigationStack (nunca NavigationView)
// 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 de iOS 16+ y es el único patrón de navegación que debes usar para código nuevo. El patrón con tipos seguros navigationDestination(for:) 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 vistas para datos reactivos: @Query var items: [GroceryItem]
4. Usa modelContext.fetch() en código que no pertenece a vistas
5. Las eliminaciones de relaciones necesitan reglas explícitas: .cascade, .nullify, .deny
Concurrencia en Swift 6.2
Usa 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 de concurrencia para agentes:
- Marca todos los view models con @MainActor (evita advertencias de carreras de datos)
- 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 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 reciben 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 esto en CLAUDE.md: “Use .glassEffect() on section backgrounds and card containers. Navigation bars automatically adopt glass material in iOS 26. Do not manually recreate glass effects with custom materials — use the system modifier.”
Contexto específico por framework
Cada framework de Apple tiene consideraciones específicas para agentes. Esta sección cubre los frameworks usados en las 8 apps.
HealthKit
Apps que lo usan: Return, Water
HealthKit requiere un manejo cuidadoso de permisos y guards 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:
- Protege siempre con HKHealthStore.isHealthDataAvailable()
- Nunca asumas autorización; verifícala 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 proporciona HealthKit
- Incluye tanto NSHealthShareUsageDescription como NSHealthUpdateUsageDescription en Info.plist
SpriteKit
Apps que lo usan: TappyColor, Starfield Destroyer
El modelo de grafo de escenas 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 physics bodies y detección de contactos - Implementar máquinas de estado de juego - Construir superposiciones de HUD
Debilidades de los agentes con SpriteKit: - Game loops 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 y requiere iteración)
Metal
Apps que lo usan: amp97, Water, Starfield Destroyer
Metal es el framework en el que más les cuesta a los agentes. El modelo de programación de GPU es fundamentalmente distinto del Swift del lado de 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 (compartida 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
Live Activities requiere 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 del 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 quedan aislados. Siempre revisa en qué directorio está 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
Guía para agentes: “Usa siempre guardas #if canImport() o #if os() cuando uses 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 y corrección
El patrón más potente: dale al agente una especificación de función y deja que itere de forma autónoma mediante ciclos de compilación, prueba y corrección.
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 el proceso. Una función que requeriría 5-10 ciclos humanos de compilación-error-corrección se completa en un solo ciclo autónomo.
Cuándo funciona: Funciones bien definidas con criterios de aceptación claros.
Cuándo falla: Funciones 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 la documentación y los 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 apps
Cuando mantienes varias apps iOS con patrones consistentes, los agentes pueden aplicar patrones de una app 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 de origen, entiende la estructura y crea una implementación consistente en el proyecto de destino.
Revisión con dos agentes (Claude + Codex)
Para cambios críticos, usa dos agentes de familias de modelos distintas:
- Claude Code escribe la implementación
- 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."
Las distintas familias de modelos detectan distintas clases de errores. Esto es especialmente valioso para shaders de Metal y patrones de concurrencia, donde es fácil introducir bugs sutiles.
Qué detecta la revisión doble que una revisión única suele pasar por alto:
| Tipo de problema | Fortaleza de Claude | Fortaleza de Codex |
|---|---|---|
| Ciclos de relaciones de SwiftData | Moderada | Fuerte (GPT-4o) |
| Brechas de aislamiento con @MainActor | Fuerte | Moderada |
| Alineación de buffers de Metal | Moderada | Moderada |
| Detección de ciclos de retención | Fuerte (Opus) | Fuerte (o3) |
| Conciencia de deprecaciones de API | Fuerte (datos de entrenamiento más recientes) | Moderada |
| Condiciones de carrera en concurrencia | Fuerte | Fuerte (detecta patrones distintos) |
La revisión doble no se trata de encontrar más bugs, sino de encontrar bugs diferentes. Cada familia de modelos tiene distintos modos de falla en su reconocimiento de patrones.
Operaciones por lotes en varias apps
Cuando un cambio de framework o patrón afecta a varias apps:
# 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
Úsalo con cautela. El flag --dangerously-skip-permissions es necesario para el modo no interactivo, pero omite todas las verificaciones de seguridad. Asegúrate de tener tus hooks PreToolUse configurados para proteger los archivos .pbxproj.
Apps que usan LLM en el dispositivo de Apple
Si tu app llama al framework Foundation Models de Apple (por ejemplo, para resumen offline, clasificación o generación de salida estructurada), los agentes necesitan conocer el presupuesto del prompt. iOS 26.4 agregó dos APIs a SystemLanguageModel que reemplazaron la conjetura previa de 4096 tokens: contextSize (tokens máximos que el modelo acepta en una sola conversación) y tokenCount(for:) (async throws, devuelve cuántos tokens cuesta realmente un prompt determinado).17 Ambos son @backDeployed(before: iOS 26.4), por lo que están disponibles en todas las versiones del sistema operativo compatibles con FM sin una escalera de #available.
El patrón que debe seguir un agente al generar código de construcción de prompts:
import FoundationModels
func budgetFor(prompt: String, reservedReply: Int = 256) async throws -> Int {
let model = SystemLanguageModel.default
let promptCost = try await model.tokenCount(for: prompt)
let budget = model.contextSize - promptCost - reservedReply
guard budget > 0 else { throw ContextError.promptTooLong }
return budget
}
Agrega este patrón a tu CLAUDE.md si la app toca SystemLanguageModel. Sin él, los agentes vuelven al antiguo valor fijo de 4096 y truncan prompts silenciosamente en dispositivos que vienen con ventanas de contexto más grandes. La firma async throws de tokenCount(for:) es fundamental: los agentes que peguen una versión síncrona no podrán compilar.
Estudios de caso reales
El consejo abstracto es fácil. Estos son escenarios específicos de las 8 apps que muestran cómo funciona en la práctica el desarrollo de iOS asistido por agentes, incluidos los fallos.
Estudio de caso 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, una UI 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 botones personalizados para la navegación por foco con 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 mediante App Groups (group.com.941apps.Return)
- Agregó protecciones #if os(tvOS) en todo el 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 a mano la navegación con Siri Remote (el agente no puede evaluar el comportamiento del foco)
Resultado: 15 archivos Swift nuevos, una app de TV completamente funcional, en aproximadamente 3 horas de trabajo asistido por agente. Según mi estimación, el agente se encargó de cerca del 80% del trabajo de implementación; yo me ocupé de las partes que requerían interacción con la UI de Xcode (entitlements, configuración del target, flags de capacidades) y pruebas manuales de foco en un Apple TV real. El trabajo equivalente en solitario en este codebase, con base en funciones similares que he enviado sin agentes, habría tomado varios días.
Estudio de caso 2: Depuración de Metal Shader en amp97 (fallo 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 ocurrió:
1. El agente escribió una modificación válida del Metal shader que agregaba un uniform uEnergy y HDR tonemapping
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 una 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 maneras
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 el resultado (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.”
Estudio de caso 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 existentes del modelo V1
2. Creó 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ó quantity: 1 y category: nil predeterminados
5. Actualizó todas las vistas para admitir los nuevos campos
6. Actualizó SampleData.swift para previews
7. Compiló y ejecutó 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 entendió desde qué estaba migrando.
Estudio de caso 4: Sincronización de sesiones de 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 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 del lado del iPhone para sesiones provenientes de otros dispositivos
Lo que requirió iteración: La implementación inicial no manejaba el caso en que la app de iPhone se inicia en segundo plano (sin notificación en primer plano para sincronizar). El agente necesitó una indicación específica: “Use NSUbiquitousKeyValueStore.didChangeExternallyNotification to trigger sync on background KV changes.” 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á descrita con claridad. El patrón de sincronización con iCloud no es trivial, pero sigue un patrón documentado de Apple que el agente entendió. El caso límite (sincronización en segundo plano) requirió conocimiento humano del dominio porque no está bien documentado.
Estudio de caso 5: Integración de Game Center en Starfield Destroyer (éxito)
La tarea: Agregar leaderboards y achievements de Game Center al shooter espacial.
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 enviar puntuaciones y reportar achievements
- Agregó verificación del estado de autenticación antes de todas las operaciones de Game Center
- Manejó correctamente el caso offline (el juego funciona sin Game Center y envía los datos al reconectarse)
- Creó definiciones de achievements que coinciden con el sistema de progresión de 8 naves
Lo que requirió trabajo manual: - Crear los leaderboards y achievements en App Store Connect (portal web, no accesible para el agente) - Configurar el entitlement de Game Center en Xcode - Probar con una cuenta sandbox de Game Center (requiere iniciar sesión manualmente en el dispositivo)
Ciclo de vida del proyecto con agentes
Iniciar un nuevo proyecto de iOS
El flujo de trabajo óptimo para iniciar un proyecto nuevo con ayuda de agentes:
Fase 1: Configuración humana (15-30 minutos) 1. Crea el proyecto de Xcode (File > New > Project) 2. Configura la firma y las capacidades 3. Define el destino de implementación y los destinos compatibles 4. Agrega cualquier entitlement requerido (HealthKit, Game Center, etc.) 5. Crea el CLAUDE.md inicial con la identidad y las reglas del proyecto
Fase 2: Implementación con 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 tus patrones documentados 3. El agente implementa la lógica de negocio en clases manager/service 4. El agente escribe pruebas unitarias 5. Ciclo build-test-fix mediante MCP (autónomo)
Fase 3: Integración humana (30-60 minutos) 1. Agrega los archivos creados por el agente a los targets de Xcode 2. Verifica la firma y los entitlements 3. Prueba en un dispositivo físico 4. Revisa el diseño visual y la UX 5. Envía a App Store Connect
Mantener un proyecto existente
Para el desarrollo continuo en apps ya 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 según qué tan bien tu CLAUDE.md refleje el estado actual del proyecto. Actualiza tu CLAUDE.md cuando agregues funciones nuevas importantes, cambies patrones arquitectónicos o introduzcas nuevos frameworks.
Cuándo involucrar al agente y cuándo no
| Tarea | ¿Agente? | Por qué |
|---|---|---|
| Nueva vista SwiftUI | Sí | Los agentes destacan en UI declarativa |
| Cambios en modelos SwiftData | Sí | Bien definidos y comprobables |
| Pruebas unitarias | Sí | Mecánicas, basadas en patrones |
| Refactorización | Sí | Sistemática, de varios archivos |
| Diagnóstico de errores de build | Sí (mediante MCP) | Ciclo estructurado de retroalimentación |
| Nuevo target de Xcode | No | Requiere la UI de Xcode y cambios en .pbxproj |
| Firma y aprovisionamiento | No | Basado en portal, no accesible para el agente |
| Pulido visual | No | Requiere criterio estético humano |
| Ajuste de shaders Metal | No | Requiere pruebas en dispositivo GPU |
| Envío a App Store | No | Portal y Xcode Organizer |
| Perfilado de rendimiento | No | Requiere Instruments |
| Auditoría de accesibilidad | Parcial | El agente puede agregar etiquetas; una persona verifica VoiceOver |
Configurar 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
Referencia este agente con @ios-developer en sesiones de Claude Code.
Patrones de prueba para iOS asistido por agentes
Los agentes escriben pruebas unitarias excelentes cuando reciben una guía clara. 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 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. Referenciar un archivo de prueba existente establece el patrón. Especificar el uso de setUp() evita que el agente cree estados de prueba enredados.
Prompt de prueba ineficaz:
Write tests for TimerManager.
Esto produce pruebas genéricas y superficiales que pasan por alto casos límite y quizá no sigan los patrones de tu proyecto.
Patrones de pruebas async
Para probar código basado en temporizadores y async:
// Agent produces this pattern when guided correctly:
final class TimerManagerTests: XCTestCase {
var sut: TimerManager!
@MainActor
override func setUp() {
super.setUp()
sut = TimerManager()
}
@MainActor
func test_start_whenStopped_transitionsToRunning() {
// Given
XCTAssertEqual(sut.state, .stopped)
// When
sut.start()
// Then
XCTAssertEqual(sut.state, .running)
}
@MainActor
func test_timerCountsDown_afterOneSecond() async throws {
// Given
sut.selectedDuration = 10
sut.reset()
sut.start()
// When
try await Task.sleep(for: .seconds(1.1))
// Then
XCTAssertLessThanOrEqual(sut.timeRemaining, 9.0)
}
}
Patrones clave que los agentes necesitan que les recuerdes:
- @MainActor en métodos de prueba que prueban clases @MainActor
- async throws para pruebas que usan Task.sleep u operaciones async
- Tolerancia en aserciones basadas en tiempo (1,1 segundos, no exactamente 1,0)
- setUp() / tearDown() limpios para aislar las pruebas
Snapshot Testing
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; luego, las pruebas del agente detectan regresiones visuales en cambios futuros.
Administració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 administrar el 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 de 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 de MCP (build) | varía | 200-2,000 |
| Respuesta de MCP (test) | varía | 500-5,000 |
Para un proyecto de 50 archivos: leer todos los archivos consume aproximadamente 50,000-100,000 tokens, muy dentro de la ventana de 1M. El agente puede mantener todo el proyecto en contexto.
Para un proyecto de más de 100 archivos: la lectura selectiva se vuelve necesaria. El agente lee primero CLAUDE.md (por las anotaciones de la estructura de archivos) y luego lee archivos específicos según sea necesario. Por eso las anotaciones de archivos en CLAUDE.md son críticas: guían al agente hacia los archivos correctos sin tener que leerlo todo.
Estrategias para proyectos grandes
- Anotaciones detalladas de archivos en CLAUDE.md — El agente lee el mapa de archivos y navega directamente a los archivos relevantes
- Delegación a subagentes — Dirige la exploración y la investigación a subagentes (contexto limpio, devuelve resúmenes)
- Prompts enfocados — “Modifica SettingsView.swift para agregar un nuevo toggle” es mejor que “actualiza la configuración”
- Límites de sesión — Inicia sesiones nuevas para funciones no relacionadas en lugar de extender una sesión larga
- Usa
/compact— El comando de compactación de Claude Code resume la conversación y libera contexto
Eficiencia de tokens de MCP
Uno de los argumentos más fuertes a favor de MCP: las respuestas estructuradas de JSON consumen muchos menos tokens que la salida sin procesar de xcodebuild.
| Escenario | Tokens de Bash sin procesar | Tokens de 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 típica de desarrollo con 10-20 ciclos de build, MCP ahorra 30,000-150,000 tokens en comparación con xcodebuild sin procesar: tokens que quedan disponibles para razonar sobre el código real.
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 explícitamente el nombre del scheme a 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. Verifícalo 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 a mitad de sesión quizá no aparezcan 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 vía Bash en lugar de MCP”
El agente no está descubriendo las herramientas de MCP mediante Tool Search. Dos soluciones:
- Agrega instrucciones explícitas a CLAUDE.md (consulta Enseñar al agente a usar MCP)
- Pídeselo directamente: “Usa la herramienta MCP build_sim, no xcodebuild vía Bash”
“El build tiene éxito, pero el agente reporta un fallo”
XcodeBuildMCP analiza la salida de xcodebuild. Si el build produce advertencias que parecen errores (algo común con advertencias de funciones obsoletas), el agente puede malinterpretar el resultado. Revisa el campo de estado real en la respuesta de MCP.
“El simulador se queda colgado durante el arranque”
Cierra todos los simuladores y reinícialos:
xcrun simctl shutdown all
xcrun simctl boot "iPhone 16 Pro"
O pídeselo al agente:
Shut down all simulators, then boot a fresh iPhone 16 Pro.
“El agente intentó modificar .pbxproj pese a las reglas de CLAUDE.md”
Las reglas de CLAUDE.md son sugerencias. Los hooks son mecanismos de cumplimiento. Si no tienes el hook PreToolUse que bloquea escrituras en .pbxproj, tarde o temprano el agente 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”.
FAQ
¿Con qué entorno de ejecución de agentes debería empezar?
Claude Code CLI con XcodeBuildMCP. Tiene la integración más profunda con MCP, el sistema de hooks más maduro y la ventana de contexto de 1M (Opus 4.6), que puede mantener proyectos completos de iOS en memoria de trabajo. Empieza aquí; después, agrega Codex para revisión y 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 por sí solo cubre el 90 % de las necesidades (builds, pruebas, simuladores, depuración). Agrega el MCP de Xcode de Apple si quieres búsqueda de documentación, verificación con Swift REPL o renderizado de previews de SwiftUI. Siempre puedes agregarlo después: los dos servidores son independientes.
¿Los agentes pueden crear un proyecto de Xcode nuevo desde cero?
XcodeBuildMCP incluye una herramienta create_project que genera la estructura inicial de nuevos proyectos de Xcode. No obstante, para apps de producción, recomiendo crear el proyecto en Xcode (para configurar correctamente la firma, las capabilities y la configuración del target) y luego usar agentes para toda la implementación del código. Los 5 minutos que pasas en el asistente de proyecto nuevo de Xcode te ahorran horas de problemas de configuración de proyecto 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. La limitación es 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 editarlo un agente.
¿Los agentes pueden enviar una app al App Store?
No. El envío al App Store involucra el Organizer de Xcode, perfiles de aprovisionamiento, capturas de pantalla, metadatos y el portal de App Store Connect. Nada de eso es accesible mediante MCP o herramientas de línea de comandos de una forma que los agentes puedan operar de manera útil. Los agentes manejan todo hasta el archive: implementación, pruebas, corrección de errores y documentación. La última parte del envío sigue siendo operada por una persona.
Sin embargo, los agentes sí pueden ayudar con los metadatos del App Store. Pídele al agente que escriba la descripción de la app, las palabras clave y el texto de novedades según 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:
- Usa archivos
.xcconfigpara la configuración específica de cada entorno - Agrega los archivos
.xcconfiga.gitignore - Referencia los valores de configuración mediante build settings de
Info.plist - 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é pasa con las animaciones de SwiftUI? ¿Los agentes pueden escribirlas?
Los agentes escriben código de animación correctamente a nivel sintáctico, pero no pueden verificar visualmente el resultado. Las animaciones simples (.animation(.spring()), .transition(.slide), withAnimation { }) producen resultados correctos. Las animaciones complejas, con varios pasos y tiempos precisos, requieren iteración visual que los agentes no pueden hacer.
Efectivo: “Agrega una animación de resorte cuando el temporizador cambie de estado.”
Inefectivo: “Haz que la animación del temporizador se sienta satisfactoria.” (Es subjetivo y requiere ajuste visual.)
¿Cómo manejan los agentes los patrones de manejo de errores?
Muy bien. Los agentes entienden los patrones de Swift con do/catch, Result y async throws:
Implement error handling for the HealthKit authorization flow:
1. Check HKHealthStore.isHealthDataAvailable() — show alert if not
2. Request authorization — handle denial gracefully
3. On write failure — retry once, then show error
4. All errors should be user-facing with localized descriptions
Los agentes producen manejo de errores estructurado con mensajes adecuados para el usuario. A veces manejan errores en exceso (capturan excepciones que deberían propagarse), así que revisa los bloques catch.
¿Puedo usar agentes para implementar accesibilidad?
Parcialmente. Los agentes agregan labels, hints 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 ratios de contraste de color. Usa el Accessibility Inspector de Xcode para la verificación.
¿Cómo manejan los agentes las migraciones de Core Data (si no uso SwiftData)?
Los agentes escriben mappings de migración y versiones de modelo de Core Data, pero los pasos manuales de Xcode (crear nuevas versiones del modelo, seleccionar la versión actual) no se pueden automatizar. Si todavía estás usando Core Data en lugar de SwiftData, documenta el historial de versiones del modelo en CLAUDE.md:
## Core Data Model Versions
- V1: Initial (GroceryList, GroceryItem)
- V2: Added Category model (current)
- Migration: Lightweight automatic for V1→V2
¿Cómo manejan los agentes los previews de SwiftUI?
De dos formas:
1. La herramienta RenderPreview del MCP de Xcode de Apple renderiza previews sin interfaz gráfica y devuelve el resultado. El agente puede verificar que un preview compile y se renderice sin errores, pero no puede evaluar la corrección visual.
2. Verificación basada en build mediante build_sim, que confirma que los proveedores de previews compilan. Si un preview falla en runtime, el build aún se completa correctamente: el fallo solo aparece cuando Xcode intenta renderizar el preview.
Para la verificación visual de previews, todavía necesitas tener Xcode abierto.
¿Qué pasa con visionOS y Apple Vision Pro?
Se aplican los mismos patrones. 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 problemas?
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 entre 50 y 70 archivos Swift en memoria de trabajo activa al mismo tiempo. Para proyectos más grandes, el agente usa búsqueda de archivos y lectura selectiva para trabajar con subconjuntos del codebase. Los 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 codebase. Un proyecto bien documentado de 200 archivos con un CLAUDE.md detallado produce mejores resultados que un proyecto sin documentación de 30 archivos.
¿Necesito saber Swift para usar agentes en el desarrollo iOS?
Necesitas poder revisar la salida del agente y tomar decisiones arquitectónicas. No tienes que escribir cada línea tú mismo, pero sí necesitas entender Swift lo suficiente 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 actual, 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 forma confiable. Los marcadores de conflicto estándar (<<<<<<<, =======, >>>>>>>) son bien entendidos por todos los entornos de ejecución de agentes. Sin embargo, los conflictos de merge en archivos .pbxproj siguen siendo una tarea de resolución manual: no les pidas a los agentes que resuelvan conflictos en .pbxproj.
¿Cuál es el costo de usar 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 agregan una sobrecarga mínima (las respuestas estructuradas de JSON son eficientes en tokens en comparación con el output bruto del build). El costo es comparable a usar Claude Code para cualquier otro codebase: 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 boilerplate, 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 modelo y la lógica de negocio mientras manejas la UI manualmente, o migra vistas gradualmente a SwiftUI.
¿Cómo manejan los agentes la localización?
Los agentes crean y editan archivos .xcstrings (catálogos de strings de Xcode) de forma efectiva. Pueden agregar nuevas claves de localización, proporcionar traducciones y mantener la coherencia entre idiomas. El formato estructurado JSON de los archivos .xcstrings es amigable para agentes. Para archivos .strings (formato heredado), los agentes también trabajan bien: el formato clave-valor es sencillo.
Errores comunes de los agentes en iOS (y cómo prevenirlos)
Estos son los errores recurrentes que he observado en miles de interacciones con agentes en 8 proyectos de iOS. Cada uno tiene una estrategia de prevención.
Error 1: Mezclar patrones Observable
Qué ocurre: El agente usa @Observable en un archivo y ObservableObject en otro, o agrega @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é ocurre: 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 closure 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é ocurre: El agente crea clases @Observable sin aislamiento @MainActor, lo que causa 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é ocurre: El agente usa el NavigationLink(destination:label:) obsoleto en lugar del patrón type-safe NavigationLink(value:) + .navigationDestination(for:).
Prevención:
## 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: Hardcodear nombres de simuladores
Qué ocurre: El agente escribe comandos de build con nombres específicos de simuladores (“iPhone 16 Pro”) que podrían no existir en tu sistema.
Prevención: MCP se encarga de esto: list_sims descubre los simuladores disponibles. En CLAUDE.md:
## Simulators
Do NOT hardcode simulator names. Use `list_sims` MCP tool to discover
available devices, then `boot_sim` with the discovered device ID.
Error 6: Crear archivos en directorios incorrectos
Qué ocurre: 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 incorrecto.
Prevención: Las anotaciones de estructura de archivos en CLAUDE.md guían la ubicación. Además:
## File Placement Rules
- Views → `AppName/Views/`
- Models → `AppName/Models/`
- Managers → `AppName/Managers/`
- Extensions → `AppName/Extensions/`
- Tests → `AppNameTests/`
Error 7: No manejar la disponibilidad de plataformas
Qué ocurre: 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: Sobrediseñar funciones simples
Qué ocurre: 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 algo 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
Después de lanzar 8 apps de iOS con agentes de AI, este es el resumen:
Los agentes transformaron: La velocidad de implementación. Lo que tomaba días ahora toma horas. Vistas SwiftUI, modelos SwiftData, pruebas unitarias, refactorización: ahora estos elementos son producidos principalmente por agentes y revisados por humanos.
Los agentes no transformaron: Las decisiones de arquitectura, el diseño visual, la optimización de rendimiento ni el envío a App Store. Todo eso sigue siendo dirigido por humanos.
El multiplicador es real, pero tiene límites. Mi estimación subjetiva en el portafolio de 8 apps: una mejora de 3 a 5 veces en el tiempo para entregar funciones en proyectos bien documentados con configuración adecuada de MCP y hooks. Esto no se midió contra un grupo de control; es una comparación de tiempo real entre funciones asistidas por agentes y trabajo individual equivalente en las mismas bases de código. Los proyectos sin documentación ni hooks quizá ven una mejora de 1,5 a 2 veces: el agente pasa demasiado tiempo adivinando en lugar de construir.19
La inversión que rinde frutos: El tiempo dedicado a CLAUDE.md, hooks y la configuración de MCP. Cada hora de preparación ahorra muchas horas de corrección de 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 entrega código.
Lo que le diría a mi yo del pasado: Empieza con la app más pequeña (Reps, 14 archivos), deja bien configurados MCP y los hooks, escribe un CLAUDE.md completo 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 sin importar el 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 el toolchain avanza hacia un desarrollo agent-first. Los desarrolladores que inviertan ahora en estructuras de proyecto compatibles con agentes —archivos CLAUDE.md limpios, arquitecturas testeables, hooks automatizados— verán cómo esa inversión se acumula a medida que las herramientas mejoren.
Tarjeta de referencia rápida
Instalación (configuración inicial)
# 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-05-24 | Se corrigió la fecha de lanzamiento estable de Xcode 26.5 a 2026-05-11 y se fijó la build como 17F42 desde la página de lanzamientos de Apple. Verificación local en esta pasada: xcodebuild -version devolvió Xcode 26.5 / Build version 17F42; la versión latest de npm para xcodebuildmcp devolvió 2.5.2 con time.modified 2026-05-12T07:40:41.737Z.13 |
| 2026-05-16 | Se actualizó el Xcode recomendado a 26.5+ (lanzado el 2026-05-11). Dos nuevas funciones de Coding Intelligence importan para los flujos de trabajo con agentes: ahora los mensajes pueden ponerse en cola en el asistente de código, así no tienes que esperar una respuesta antes de preparar la siguiente solicitud, y los agentes pueden hacer preguntas aclaratorias antes de continuar; ambas reducen la fricción de ejecutar los agentes nativos de Xcode en paralelo con sesiones de Claude Code o Codex.13 Comprobación de vigencia de XcodeBuildMCP: v2.5.2 (2026-05-12) es la versión más reciente, agrega AXe 1.7.0 incluido y corrige un problema de validación del filtro de captura de logs; el flujo xcodebuildmcp init desde v2.1.0+ sigue siendo la ruta de instalación recomendada. |
| 2026-04-28 | Se actualizó el Xcode recomendado a 26.4+ para flujos de trabajo con agentes (26.4.1, 2026-04-16, build 17E202 es la versión estable más reciente, solo con correcciones de errores). Se citaron funciones de Xcode 26.4 (2026-03-24, build 17E192) útiles para pruebas escritas por agentes y localización: adjuntos de imágenes en Swift Testing, severidad en Issue.record, advertencias de fallos en pruebas de UI con crashlogs adjuntos (específicamente para apps XCUIApplication(bundleIdentifier:) / XCUIApplication(url:)), mejoras en el editor de String Catalog. Se agregó el instalador automático xcodebuildmcp init (v2.1.0+, 2026-02-23) como alternativa a la configuración manual de MCP. |
| 2026-04-27 | App Store Connect: los envíos con Xcode 26+ pasan a ser obligatorios a partir del 2026-04-28. Foundation Models incorporó las APIs SystemLanguageModel.contextSize y tokenCount(for:) (retrodesplegadas a iOS 26.4); se agregó un patrón para código de presupuesto de prompts de FM generado por agentes. iOS 26.4.2 (22 de abril) e iOS 26.5 beta 3 (20 de abril) se lanzaron sin cambios que afecten la cadena de herramientas de agentes. |
| 2026-04-13 | Publicación inicial. 8 apps, 3 runtimes, configuración de MCP, patrones de CLAUDE.md, hooks, estudios de caso. |
Referencias
-
XcodeBuildMCP incluye telemetría de Sentry de forma predeterminada. 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=truepermite desactivarlo por completo. ↩ -
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 Xcode de Apple. ↩
-
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 changelogs. ↩
-
Apple presentó el servidor MCP de Xcode como parte de la iniciativa de herramientas inteligentes para desarrolladores de 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 Xcode Release Notes para la documentación oficial. ↩
-
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 la documentación. ↩
-
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 de forma significativa a los agentes limitados a comandos de shell no estructurados. El hallazgo valida las interfaces estructuradas de MCP para la efectividad de los agentes. ↩
-
Documentación de Claude Code CLI, code.claude.com. Sistema de hooks, configuración de MCP, delegación a subagentes y definiciones de agentes. ↩
-
SwiftFormat, github.com/nicklockwood/SwiftFormat. La herramienta de formato de Swift usada en hooks PostToolUse para mantener un estilo de código consistente. ↩
-
Sitio oficial de XcodeBuildMCP, xcodebuildmcp.com. Confirma 59 herramientas MCP mediante un 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. ↩
-
Swiftjective-C, “Agentic Coding in Xcode 26.3 with Claude Code and Codex,” swiftjectivec.com, febrero de 2026. Confirma que Xcode 26.3 incluye Claude Agent nativo y soporte para el runtime de Codex mediante Settings > Intelligence. 20 herramientas MCP expuestas vía
xcrun mcpbridge. ↩ -
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 y resultados reales del flujo de desarrollo iOS del mismo autor. ↩
-
Apple Developer News, “Upcoming Requirements”. Entrada del 2026-04-28: “Apps uploaded to App Store Connect must be built with Xcode 26 or later using an SDK for iOS 26, iPadOS 26, tvOS 26, visionOS 26, or watchOS 26.” macOS no aparece en el conjunto de plataformas listado para este requisito. ↩
-
Apple, “Xcode 26.5 Release Notes” y “Xcode 26.5 (17F42) - Releases”. Apple listó Xcode 26.5 el 2026-05-11 con la build 17F42. Dos funciones de Coding Intelligence citadas de las notas de lanzamiento: los mensajes pueden ponerse en cola en el asistente de código sin esperar a que termine la respuesta actual (174563016), y los agentes pueden hacer preguntas aclaratorias para reunir contexto antes de continuar (175182375). También incluye soporte de StoreKit Testing para suscripciones mensuales con compromiso de 12 meses (modelo
PricingTerms,billingPlanTypePurchaseOption,CommitmentInfoenTransactionySubscriptionRenewalInfo) y una corrección del depurador de Swift para avanzar paso a paso por Swift Tasks que migran de hilo durante operaciones async/await. Verificación de la sesión actual el 2026-05-24:xcodebuild -versiondevolvióXcode 26.5yBuild version 17F42;npm view xcodebuildmcp version dist-tags.latest time.modified --jsondevolvió latest2.5.2contime.modified2026-05-12T07:40:41.737Z. Consulta también: 9to5Mac, “Xcode 26.5 adds two features that make agentic coding more useful”, 2026-05-12. ↩↩↩ -
Apple, “Xcode 26.4 Release Notes”. Xcode 26.4 (2026-03-24, build 17E192). Funciones citadas de las notas de lanzamiento: Swift Testing ahora admite adjuntos de imágenes mediante
CGImage,NSImage,UIImageyCIImage;Issue.recordacepta niveles de severidad; algunos fallos de apps en pruebas de UI, específicamente apps con las que se interactúa medianteXCUIApplication(bundleIdentifier:)oXCUIApplication(url:), se reportan como advertencias con crashlogs adjuntos en lugar de hacer fallar la prueba; el editor de String Catalog agrega cortar/copiar/pegar entradas, eliminación de idiomas y prellenado de traducciones desde un idioma existente, además de la configuraciónBUILD_ONLY_KNOWN_LOCALIZATIONS. ↩ -
Apple Developer News, “Xcode 26.4.1 (Build 17E202) Now Available”, 2026-04-16. Lanzamiento puntual solo de correcciones: corrige un fallo de MetricKit por símbolos faltantes en iOS / macOS / visionOS anteriores a 26.4, y un error de asignación en stack async de Swift (“freed pointer was not the last allocation” en
swift_asyncLet_finish). ↩ -
getsentry/XcodeBuildMCP lanzamiento v2.1.0, 2026-02-23. Agregó el comando CLI
xcodebuildmcp initpara instalar habilidades de agente + configuración de MCP en un solo paso, reemplazando el script independienteinstall-skill.sh. Detecta automáticamente Claude Code, Cursor y Codex; admite--print(escribir la configuración en stdout para clientes no compatibles) y--uninstall(eliminar). ↩ -
InfoQ, “Apple Adds Context Window Management to Foundation Models”, marzo de 2026. Documenta las nuevas APIs
SystemLanguageModel.contextSizeytokenCount(for:)y confirma las anotaciones@backDeployed(before: iOS 26.4). Reemplaza la estimación previa de la comunidad de un valor fijo de 4096 tokens. ↩ -
Conteos de archivos derivados de
find . -name '*.swift' -not -path '*/Tests/*' | wc -lejecutado en cada uno de los ocho repositorios privados de apps el 2026-04-27. Se excluyeron los archivos de pruebas. El total es internamente consistente con la tabla de desglose por app en §The Portfolio. ↩ -
Estimación subjetiva de tiempo real, no una medición contra un grupo de control. La cifra de 3-5x es el recuerdo del autor sobre comparaciones de tiempo hasta función entre funciones asistidas por agentes en 2026 y funciones solitarias equivalentes enviadas en las mismas bases de código antes del flujo de trabajo con agentes. Trátala como una heurística de qué esperar después de configurar MCP + hooks, no como un benchmark. ↩