Saltar al contenido
Development

Configurando Claude Code para un proyecto de iOS

Por Victor Da Luz
iosswiftmusickitclaude-codedev-logdeep-cut-atlas

Esta app se llamó después Deep Cut Atlas. Aquí se llama “Discoverer” en todo el texto, porque así se llamaba el día que pasó esto.

Llevo tiempo queriendo construir una app de iOS. La idea se llama Discoverer: encuentra lanzamientos nuevos de artistas en mi biblioteca de Apple Music que todavía no he agregado, para no quedarme atrás en música que sí me importa. Premisa sencilla, pero MusicKit + SwiftData + CloudKit + StoreKit es un stack real que hay que conectar.

Empecé creando el repositorio de git y escribiendo un CLAUDE.md. En mis proyectos de homelab y del blog, CLAUDE.md se ha vuelto el archivo más importante del repositorio: ahí defino las reglas de cómo los agentes que trabajan en el código deben comunicarse conmigo. Para esos proyectos las reglas son sobre todo de infraestructura: no ejecutar comandos destructivos sin preguntar, siempre revisar los archivos de estado antes de asumir algo, ese tipo de cosas.

Para un proyecto de iOS las preocupaciones son distintas. iOS tiene bordes filosos con los que un agente de propósito general se va a topar si no tiene un mapa.

MusicKit no funciona en el simulador. Nunca. Acceso a la biblioteca, búsqueda en el catálogo, reproducidos recientemente, escritura en playlists: todo requiere un iPhone físico con una suscripción activa de Apple Music. Si voy a dejar que un agente escriba código contra MusicKit, necesita saber esto desde el inicio, o voy a terminar con código que no se puede probar sin que me dé cuenta de por qué. El enfoque estándar es definir un protocolo (MusicLibraryServiceProtocol) con una implementación real y una simulada, inyectada según el entorno para que los builds del simulador usen la simulada automáticamente.

CloudKit cambia las reglas de SwiftData. SwiftData solo local permite propiedades no opcionales sin valores por defecto. CloudKit no lo permite: falla al inicializar el esquema. Cada propiedad de un @Model necesita ser opcional o tener un valor por defecto. Es el tipo de cosa que uno descubre a las malas en su primer proyecto con CloudKit.

La configuración sandbox de StoreKit solo carga desde el IDE de Xcode. Ejecutar xcodebuild test desde la terminal no la carga. Todas las pruebas de compras de StoreKit tienen que pasar por Xcode y luego Run. Esto importa porque dependo de xcodebuild para builds sin interfaz vía xcbeautify, pero cualquier trabajo de StoreKit necesita una sesión completa de Xcode.

@Observable, no ObservableObject. Swift 6 + SwiftUI trajo @Observable como el patrón correcto. Los agentes entrenados antes de que este patrón se estabilizara van a usar ObservableObject por defecto. Una regla explícita evita ese desvío.

Todo esto entró al CLAUDE.md como “restricciones críticas”, no como comentarios de arquitectura sino como reglas obligatorias que los agentes deben seguir en cada tarea. La regla de proyecto de aprendizaje vino primero, eso sí: los agentes deben explicar cada comando antes de ejecutarlo, interpretar la salida después, y no asumir que conozco los detalles internos de MusicKit o StoreKit. El homelab es un proyecto de aprendizaje. Este también.

La configuración real del repositorio tomó unos veinte minutos: git init, tomar la plantilla de .gitignore de Swift de GitHub (y agregarle .DS_Store y DerivedData/, que la plantilla omite), escribir un README con una descripción del proyecto y pasos de configuración pendientes, y confirmar los tres archivos como el commit inicial. Luego gh repo create discoverer --private --push para crear el repositorio en GitHub y subirlo en un solo paso.

El repositorio es privado hasta que la app esté lista para el App Store. En ese punto pasa a formar parte de la historia del lanzamiento. Por ahora es solo un lugar donde va a vivir el código, y las reglas ya están escritas.

Lo que sigue: el proyecto de Xcode en sí, con un TabView de 3 pestañas, el entitlement de MusicKit, el archivo de configuración de StoreKit, y la estructura de carpetas del CLAUDE.md. El CLAUDE.md ya está ahí, esperándolo.

Lecturas relacionadas