Pular para o conteúdo
Development

Configurando o Claude Code para um projeto iOS

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

Este app foi renomeado depois para Deep Cut Atlas. Abaixo ele é chamado de “Discoverer” o tempo todo, porque era assim que se chamava no dia em que isso aconteceu.

Já faz um tempo que eu queria construir um app para iOS. A ideia se chama Discoverer: ela mostra lançamentos novos de artistas da minha biblioteca do Apple Music que eu ainda não adicionei, para eu não ficar por fora de músicas que realmente me importam. Premissa simples, mas MusicKit + SwiftData + CloudKit + StoreKit é uma stack de verdade para juntar.

Comecei criando o repositório git e escrevendo um CLAUDE.md. Nos meus projetos de homelab e de blog, o CLAUDE.md virou o arquivo mais importante do repositório - é onde eu defino as regras de como os agentes que trabalham no código devem se comunicar comigo. Para esses projetos, as regras são principalmente sobre infraestrutura: não rodar comandos destrutivos sem perguntar, sempre checar os arquivos de estado antes de assumir algo, esse tipo de coisa.

Para um projeto iOS, as preocupações são diferentes. iOS tem algumas arestas afiadas nas quais um agente de código de propósito geral vai tropeçar sem um mapa.

O MusicKit não funciona no simulador. Nunca. Acesso à biblioteca, busca no catálogo, tocadas recentemente, escrita em playlists - tudo isso exige um iPhone físico com uma assinatura ativa do Apple Music. Se eu vou deixar um agente escrever código usando o MusicKit, ele precisa saber disso desde o início, ou eu vou acabar com código que não pode ser testado sem eu perceber o motivo. A abordagem padrão é definir um protocolo (MusicLibraryServiceProtocol) com uma implementação real e uma mock, injetadas via ambiente para que builds de simulador usem o mock automaticamente.

O CloudKit muda as regras do SwiftData. O SwiftData somente local permite ter propriedades não opcionais sem valores padrão. O CloudKit não permite; ele trava na inicialização do schema. Toda propriedade @Model precisa ser opcional ou ter um valor padrão. É o tipo de coisa que você descobre da pior forma no seu primeiro projeto com CloudKit.

A configuração de sandbox do StoreKit só carrega pela IDE do Xcode. Rodar xcodebuild test pelo terminal não a carrega. Todo teste de compra do StoreKit precisa passar pelo Xcode, com o botão Run. Isso importa porque eu dependo do xcodebuild para builds headless via xcbeautify, mas qualquer trabalho com StoreKit exige uma sessão completa do Xcode.

@Observable, não ObservableObject. Swift 6 + SwiftUI consagrou o @Observable como o padrão certo. Agentes treinados antes desse padrão se estabilizar vão recorrer ao ObservableObject por padrão. Uma regra explícita evita esse desvio.

Tudo isso entrou no CLAUDE.md como “Restrições críticas”, não como comentários de arquitetura, mas como regras rígidas que os agentes devem seguir em toda tarefa. A regra de projeto de aprendizado veio primeiro, porém: os agentes precisam explicar cada comando antes de rodá-lo, interpretar a saída depois, e não assumir que eu conheço os detalhes internos do MusicKit ou do StoreKit. O homelab é um projeto de aprendizado. Este também é.

A configuração do repositório em si levou uns vinte minutos: git init, baixei o template .gitignore de Swift do GitHub (e adicionei .DS_Store e DerivedData/, que o template deixa de fora), escrevi um README com uma visão geral do projeto e passos de configuração provisórios, e fiz commit dos três arquivos como o commit inicial. Depois, gh repo create discoverer --private --push para criar o repositório no GitHub e fazer push em um único passo.

O repositório é privado até o app estar pronto para a App Store. Nesse ponto ele passa a fazer parte da história do lançamento. Por enquanto é só um lugar onde o código vai viver e as regras já estão escritas.

A seguir: o projeto Xcode em si - uma TabView de 3 abas, entitlement do MusicKit, arquivo de configuração do StoreKit, e a estrutura de pastas definida no CLAUDE.md. O CLAUDE.md já está lá esperando por ele.

Leitura relacionada

Development

A playlist que já tinha o nome certo

Um artefato de renomeação, uma API sem campo de autor pra atualizar, e um teste em dispositivo real provando que o bug já tinha se corrigido sozinho, fechado como aceitar como está.

Ler

Você também pode achar útil

Proton

Proton Drive

Armazenamento em nuvem criptografado, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
Proton

Proton VPN

VPN comercial com filtragem NetShield e interruptor de desligamento automático.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
AdGuard

AdGuard para iOS

Bloqueio de anúncios e rastreadores em todo o sistema no iOS, sem necessidade de um servidor DNS separado.

Como afiliado da AdGuard, ganho com compras qualificadas.

Saiba mais