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

Criando apps para iOS com agentes de IA: o guia prático

# Crie apps para iOS mais rápido com agentes de IA. Claude Code, Codex CLI, Xcode 26.3 nativo, MCP, padrões do CLAUDE.md, hooks, lições de 8 apps.

words: 13674 read_time: 52m updated: 2026-05-15 12:58
$ less ios-agent-development.md

Resumo: Três runtimes de agentes agora entregam código para iOS: Claude Code CLI com MCP, Codex CLI com MCP e os agentes nativos de Intelligence do Xcode 26.3. Dois servidores MCP (XcodeBuildMCP com 59 ferramentas e o xcrun mcpbridge da Apple com 20 ferramentas) dão aos agentes acesso estruturado a builds, testes, simuladores e debugging. Este guia cobre padrões reais de CLAUDE.md, configurações de hooks e avaliações honestas do que funciona e do que quebra — com base em 8 apps iOS em produção, totalizando 293 arquivos Swift.17 Agentes são excelentes em views SwiftUI, modelos SwiftData, refatoração e diagnóstico de erros de build. Eles falham em modificações de .pbxproj, assinatura de código e debugging visual. A lacuna entre “o agente escreve Swift” e “o agente entrega um app iOS” é preenchida por configuração, não por prompting.

Criei 8 apps iOS com agentes de codificação com IA. Não protótipos — apps na App Store, com integrações HealthKit, shaders Metal, física SpriteKit, sincronização iCloud, Live Activities, rankings Game Center e targets multiplataforma abrangendo iOS, watchOS e tvOS. Cada linha de Swift nesses apps foi escrita por um agente e revisada por mim, ou escrita por mim e refatorada por um agente. Pela minha estimativa, os agentes cuidaram da maior parte da autoria no nível das linhas; eu cuidei da revisão, do escopo e das partes que exigem julgamento humano (polimento visual, assinatura, ajuste de performance, envio para a App Store).

Este guia é a referência que eu gostaria que existisse quando comecei. Ele cobre a stack inteira: qual runtime de agente usar, como configurar servidores MCP para acesso estruturado ao build, o que colocar no seu CLAUDE.md, quais hooks impedem o agente de destruir seu projeto Xcode e — principalmente — onde os agentes falham e você precisa assumir o controle.

Principais pontos

Para desenvolvedores iOS que estão começando com agentes de IA:

  • Comece com Claude Code CLI + XcodeBuildMCP. É o runtime mais maduro, com a cobertura mais profunda de ferramentas MCP. Instale dois comandos, adicione um CLAUDE.md ao seu projeto e o agente poderá compilar, testar e depurar sem você copiar mensagens de erro.
  • Nunca deixe um agente modificar .pbxproj. Esta é a regra mais importante. Um hook PreToolUse que bloqueia gravações em .pbxproj e .xcodeproj/ vai economizar horas de recuperação.
  • Seu CLAUDE.md é o documento de onboarding do agente. Horas investidas nele se pagam em cada sessão de agente que toca no projeto.

Para usuários experientes de agentes adicionando iOS ao fluxo de trabalho:

  • MCP transforma o ciclo de build do iOS. Antes do MCP, agentes escreviam Swift, mas não conseguiam verificar se compilava. Com XcodeBuildMCP, o agente escreve código, compila, lê erros estruturados, corrige e executa testes — de forma autônoma.
  • Três runtimes atendem a necessidades diferentes. Claude Code CLI para sessões agentic profundas, Codex CLI para trabalho batch headless, agentes nativos do Xcode 26.3 para correções rápidas inline sem sair da IDE.
  • A infraestrutura de hooks se reaproveita. Seus formatadores PostToolUse, bloqueadores PreToolUse e hooks de execução de testes existentes funcionam de forma idêntica em projetos iOS, com pequenos ajustes de caminho.

Para líderes de equipe avaliando desenvolvimento iOS assistido por IA:

  • A eficácia dos agentes escala com a documentação do projeto, não com o tamanho do projeto. Um app com 63 arquivos e um CLAUDE.md detalhado produz resultados melhores do que um app com 14 arquivos e nenhum documento.
  • O limite do .pbxproj é inegociável. Agentes não conseguem editar arquivos de projeto Xcode de forma confiável. Seu fluxo de trabalho precisa considerar a adição manual de arquivos aos targets do Xcode.
  • ROI honesto: agentes cuidam da maior parte da implementação em projetos bem documentados — visível no app de TV com 15 arquivos entregue em 3 horas de trabalho assistido por agente (estudo de caso abaixo). O trabalho restante — polimento visual, assinatura, ajuste de performance, envio para a App Store — exige julgamento humano.

Escolha seu caminho

O que você precisa Vá para
Configurar MCP pela primeira vez Configuração do MCP: a configuração completa — instale os dois servidores, verifique, configure agentes
Escrever um CLAUDE.md para seu projeto iOS Padrões de CLAUDE.md para projetos iOS — exemplos reais de 8 apps
Comparar os três runtimes de agentes Três runtimes de agentes para iOS — Claude Code vs. Codex vs. Xcode nativo
Entender o que agentes conseguem e não conseguem fazer O que agentes fazem bem e O que agentes fazem mal
Configurar hooks para desenvolvimento iOS Hooks para desenvolvimento iOS — formatar ao salvar, proteção de .pbxproj, executores de teste
Referência aprofundada (esta página) Continue lendo — tudo, da configuração a padrões avançados

Como usar este guia

Esta é uma referência com mais de 3.000 linhas. Comece pelo ponto que combina com seu nível de experiência:

Experiência Comece aqui Depois explore
Novo em iOS + agentes Pré-requisitosConfiguração do MCPSua primeira sessão de agente Padrões de CLAUDE.md, O que funciona/não funciona
Desenvolvedor iOS, novo em agentes Três runtimesConfiguração do MCPCLAUDE.md Hooks, Padrões de arquitetura
Usuário de agentes, novo em iOS Padrões de arquiteturaO que agentes fazem malCLAUDE.md Contexto específico por framework, Fluxos de trabalho avançados
Experiente em ambos Fluxos de trabalho avançadosHooksPadrões multiplataforma Comparação de runtimes, O portfólio

Sumário

  1. O portfólio: 8 apps, 293 arquivos
  2. Pré-requisitos
  3. Três runtimes de agentes para iOS
  4. Configuração do MCP: a configuração completa
  5. Padrões de CLAUDE.md para projetos iOS
  6. Sua primeira sessão de agente
  7. O que agentes fazem bem no iOS
  8. O que agentes fazem mal no iOS
  9. Hooks para desenvolvimento iOS
  10. Padrões de arquitetura que funcionam com agentes
  11. Contexto específico por framework
  12. Padrões multiplataforma
  13. Fluxos de trabalho avançados
  14. Estudos de caso do mundo real
  15. Ciclo de vida do projeto com agentes
  16. Configuração de definições de agentes
  17. Padrões de teste para iOS assistido por agentes
  18. Gerenciamento da janela de contexto para projetos iOS
  19. Solução de problemas
  20. Erros comuns de agentes em iOS
  21. A avaliação honesta
  22. FAQ
  23. Cartão de referência rápida
  24. Referências

Recursos relacionados

Tópico Recurso
Configuração do MCP para Xcode (post de blog mais curto) Dois servidores MCP transformaram Claude Code em um sistema de build para iOS
Referência completa do Claude Code CLI Claude Code CLI: o guia completo
Referência do Codex CLI Codex CLI: o guia completo
Mergulho profundo no sistema de hooks Anatomy of a Claw: 84 Hooks as an Orchestration Layer
Padrões de arquitetura de agentes Guia de arquitetura de agentes
App desktop para Mac + Remote Control Claude Code Mac Desktop + Remote Control: guia para usuários do CLI

Série Apple Ecosystem. 21 posts de produção sobre apps SwiftUI que integram Apple Intelligence, MCP, Foundation Models, Vision, Core ML e a stack de frameworks do iOS 26. Com base em Water, Get Bananas, Return e no restante do portfólio 941:

Hub da série: Série Apple Ecosystem

Agentic Apple (E4):

Tópico Recurso
Superfície de intents do Apple Intelligence App Intents são a nova API da Apple para seu app
Servidor MCP junto ao app iOS Dois ecossistemas de agentes, uma lista de compras
Quando usar qual App Intents vs. ferramentas MCP: a questão do roteamento
LLM no dispositivo como recurso de runtime vs tooling Foundation Models + fluxo de trabalho agentic
Hooks para desenvolvimento Apple Hooks para desenvolvimento Apple
Estado entre processos Fonte única da verdade: SwiftData + MCP + iCloud

Frameworks (E2/E3):

Tópico Recurso
LLM no dispositivo com Foundation Models LLM no dispositivo com Foundation Models
Framework Vision (primitivas de CV) Framework Vision: o que já vem incluído
Padrões de inferência Core ML Inferência no dispositivo com Core ML
Modelo mental espacial do RealityKit RealityKit e o modelo mental espacial
Internals do SwiftUI Do que o SwiftUI é feito
Vocabulário de animação Symbol Effects Symbol Effects: o vocabulário de animação integrado do SwiftUI
Liquid Glass no iOS 26+ Liquid Glass em SwiftUI: três padrões

Código entregue (E1):

Tópico Recurso
Máquina de estados de Live Activities Máquina de estados de Live Activities
Contrato de runtime do watchOS Contrato de runtime do watchOS
Disciplina de schema do SwiftData Disciplina de schema do SwiftData
Padrões HealthKit + SwiftUI HealthKit + SwiftUI no iOS 26
SwiftUI multiplataforma Cinco plataformas Apple, três arquivos compartilhados
Integração XcodeBuildMCP Dois servidores MCP, um projeto Xcode

Síntese (E5):

Tópico Recurso
Três superfícies de um app iOS As três superfícies de um app iOS
Decisões de target de plataforma A matriz de plataformas Apple
O que eu me recuso a escrever O que eu me recuso a escrever

O portfólio: 8 apps, 293 arquivos

Antes de mergulhar na configuração, aqui está a base sobre a qual este guia foi construído. Estes não são projetos de brincadeira — eles abrangem cinco frameworks da Apple, três plataformas e toda a gama de complexidade do iOS, desde um rastreador de treinos com 14 arquivos até um timer de meditação multiplataforma com 63 arquivos.

App Stack Arquivos Complexidade
Banana List SwiftUI + SwiftData + sincronização via iCloud Drive + servidor MCP para Claude Desktop 53 CRUD completo, sincronização iCloud, servidor MCP personalizado que expõe os dados do app ao Claude Desktop
Ace Citizenship App de estudos em SwiftUI + backend FastAPI 26 Cliente-servidor, integração com REST API, motor de quiz
TappyColor Jogo de combinar cores em SpriteKit 30 Game loop, física, tratamento de toque, efeitos de partículas
Return Timer de meditação zen — iOS 26+, watchOS, tvOS 63 HealthKit, Live Activities, runtime estendido no Watch, navegação por foco na TV, sincronização de sessões via iCloud
amp97 Metal shaders + visualização de áudio 41 Pipeline de renderização Metal personalizado, análise de áudio, computação GPU em tempo real
Reps SwiftUI + SwiftData para rastreamento de treinos 14 App mínimo viável, padrões SwiftData limpos
Water SwiftUI + SwiftData + Metal + HealthKit para rastreamento de hidratação 34 Simulação de fluido em Metal, registro de ingestão de água via HealthKit, widget
Starfield Destroyer Space shooter em SpriteKit + Metal 32 99 fases, 8 naves, leaderboards do Game Center, pós-processamento em Metal

Por que a contagem de arquivos importa: A eficácia do agente está correlacionada com a legibilidade do projeto, não com o tamanho dele. O Return (63 arquivos) produz uma saída de agente melhor do que o amp97 (41 arquivos) porque o Return tem um CLAUDE.md detalhado com anotações de arquivos, diagramas de arquitetura e padrões explícitos. Os Metal shaders do amp97 são inerentemente mais difíceis para os agentes raciocinarem, independentemente da qualidade da documentação.


Pré-requisitos

Antes de configurar qualquer runtime de agente para desenvolvimento iOS:

Prazo do App Store Connect: A partir de 2026-04-28, os uploads de apps para o App Store Connect devem ser compilados com o Xcode 26 ou posterior usando SDKs para iOS 26, iPadOS 26, tvOS 26, visionOS 26 ou watchOS 26.12 (Submissões para macOS não estão sujeitas a esse requisito.) Se sua equipe ainda está no Xcode 16.x, a toolchain assistida por agentes deste guia funciona como um mecanismo de pressão — nenhum dos servidores MCP abaixo funciona sem o Xcode 26.3+ de qualquer forma.

Obrigatório: - macOS 15+ (Sequoia) ou macOS Tahoe - Xcode 26.3+ instalado e configurado (o piso do xcrun mcpbridge); Xcode 26.4+ recomendado para anexos de imagens em Swift Testing, severidade de problemas registrados, avisos de crash em testes de UI com crashlogs e melhorias no editor de String Catalog.13 O Xcode 26.4.1 (2026-04-16, build 17E202) é a versão estável mais recente — apenas correções de bugs.14 - Pelo menos um runtime de iOS Simulator instalado - Uma conta Anthropic API (para Claude Code) ou conta OpenAI (para Codex)

Recomendado: - SwiftFormat instalado (brew install swiftformat) — usado pelos hooks de format-on-save - SwiftLint instalado (brew install swiftlint) — opcional, mas útil para impor padrões de estilo - Familiaridade com o terminal — todos os três runtimes operam a partir da linha de comando ou se integram a ela

Verifique sua instalação do Xcode:

# Check Xcode version
xcodebuild -version
# Expected: Xcode 26.3 or later (26.4+ 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")

Se xcrun mcpbridge retornar “command not found”, você precisa do Xcode 26.3 ou posterior. Instale ou atualize o Xcode pela App Store ou em developer.apple.com. Observação: xcode-select --install instala apenas as Command Line Tools, que não incluem o mcpbridge — você precisa do Xcode.app completo.


Três runtimes de agentes para iOS

Três runtimes distintos podem escrever, compilar e testar código iOS. Eles não são intercambiáveis — cada um tem pontos fortes diferentes, padrões de integração com MCP diferentes e casos de uso ideais diferentes.

1. Claude Code CLI

O que é: o assistente de codificação agêntico baseado em terminal da Anthropic. Lê seu codebase, executa comandos, modifica arquivos e se conecta a ferramentas externas via MCP.

Integração com MCP: suporte completo tanto para o XcodeBuildMCP quanto para o MCP do Xcode da Apple. O agente descobre ferramentas via protocolo MCP e as chama com parâmetros estruturados. 59 + 20 ferramentas entre os dois servidores.

Configuração:

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

Se preferir pular a fiação manual do MCP, o XcodeBuildMCP v2.1.0+ vem com um subcomando init que detecta automaticamente o Claude Code, Cursor ou Codex e instala as skills do agente + a configuração do MCP em uma única etapa:

xcodebuildmcp init
# Or without a global install:
npx -y xcodebuildmcp@latest init

Flags: --print (escreve a configuração no stdout para clientes não suportados), --uninstall (remove). Pule isso se quiser controle explícito sobre quais servidores MCP são conectados e em qual escopo; as invocações manuais claude mcp add acima dão esse controle.15

Melhor para: sessões profundas de implementação — construir novos recursos, refatorar entre múltiplos arquivos, depurar problemas complexos, executar loops de build-test-fix de forma autônoma. A janela de contexto de 1M do Claude Code (com Opus 4.6) significa que o agente consegue manter a maioria dos projetos iOS pequenos a médios na memória de trabalho — na minha experiência, até cerca de 50 arquivos dependendo do tamanho do arquivo.

Sessão 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]

A diferença principal em relação ao fluxo de trabalho pré-MCP: o agente nunca pede que você compile manualmente ou cole a saída de erro. O loop de build-error-fix é autônomo.

2. Codex CLI

O que é: o agente de codificação baseado em terminal da OpenAI. Conceitualmente similar ao Claude Code, mas usa modelos da OpenAI (GPT-4o, o3) e tem um modelo de permissão diferente.

Integração com MCP: o Codex suporta MCP via comando codex mcp add. O MCP do Xcode da Apple funciona diretamente:

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

O XcodeBuildMCP também funciona com o Codex pelo mesmo comando npx:

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

Melhor para: operações em batch headless, integração com CI/CD e tarefas em que você quer uma segunda opinião de uma família de modelos diferente. O modo sandbox do Codex executa o código em ambientes isolados, o que é útil para operações destrutivas como execuções de suítes de testes que modificam estado.

Diferenças principais em relação ao Claude Code: - Usa modelos da OpenAI em vez de modelos Claude - Tamanhos de janela de contexto e economia de tokens diferentes - Modelo de permissão sandbox-first (mais restritivo por padrão) - Ecossistema MCP menor (menos servidores comunitários testados) - Sistema de hooks disponível (v0.119.0+) mas menos maduro que o do Claude Code — menos tipos de eventos e sem campo condicional if

Quando usar o Codex em vez do Claude Code para iOS:

Use o Codex quando quiser diversidade de modelos — ter um segundo agente revisando o código escrito pelo primeiro pega classes diferentes de erros. O fluxo de trabalho collab (Claude constrói, Codex revisa) é eficaz para iOS porque padrões SwiftUI que parecem corretos para uma família de modelos podem ter problemas sutis que outra captura. Shaders Metal e padrões de concorrência se beneficiam especialmente da revisão por dois modelos.

3. Agentes nativos do Xcode 26.3

O que é: a Apple integrou agentes de codificação com IA diretamente no painel Intelligence do Xcode. A partir do Xcode 26.3, você pode configurar o Claude Agent e o Codex como provedores de inteligência em Xcode Settings > Intelligence.

Configuração:

  1. Abra o Xcode 26.3+
  2. Navegue até Settings > Intelligence
  3. Adicione um novo provedor:
  4. Para Claude: selecione “Claude Agent” e insira sua chave de API da Anthropic
  5. Para Codex: selecione “Codex” e insira sua chave de API da OpenAI
  6. O agente aparece na barra lateral Intelligence e pode ser invocado inline

Melhor para: edições inline rápidas, autocompletar de código com raciocínio em nível de agente e desenvolvedores que preferem não sair do Xcode. A integração nativa significa que o agente tem acesso direto ao contexto do projeto do Xcode — arquivos abertos, targets de build, configuração de scheme — sem precisar de uma ponte MCP.

Limitações comparadas aos agentes CLI: - Sem sistema de hooks — você não pode aplicar format-on-save ou bloquear gravações em .pbxproj - Sem carregamento de CLAUDE.md — o agente não lê seus arquivos de configuração no nível do projeto - Autonomia limitada — o agente opera no arquivo ou seleção atual, não em todo o projeto - Sem delegação para subagentes — tarefas complexas com múltiplas etapas não podem ser paralelizadas - Sem configuração de servidor MCP — o agente usa apenas as ferramentas internas do Xcode

Quando usar agentes nativos do Xcode:

Para edições rápidas e delimitadas em que mudar para o terminal é overhead. “Adicione uma computed property a este model.” “Escreva um teste unitário para esta função.” “Refatore esta view para usar @Observable.” Tarefas que tocam um ou dois arquivos e não exigem um ciclo de build-test.

Para qualquer coisa que exija compilar, testar, refatoração entre múltiplos arquivos ou correção autônoma de erros, use um agente CLI com MCP.

Matriz comparativa de runtimes

Capacidade Claude Code CLI Codex CLI Xcode 26.3 nativo
Suporte a MCP Completo (79 ferramentas) Completo (79 ferramentas) Apenas ferramentas internas do Xcode
Sistema de hooks Sim (maduro) Sim (básico, v0.119.0+) Não
CLAUDE.md / config do projeto Sim equivalente codex.md Não
Build-test-fix autônomo Sim (via MCP) Sim (via MCP) Parcial (apenas inline)
Delegação para subagentes Sim (até 10 em paralelo) Não Não
Janela de contexto 1M tokens (Opus 4.6) Varia por modelo Varia por provedor
Operações entre múltiplos arquivos Acesso ao codebase completo Acesso ao codebase completo Arquivo atual / seleção
Proteção do .pbxproj Via hooks Manual N/A (usa Xcode nativamente)
Format-on-save Via hooks PostToolUse Ferramentas externas Configurações do Xcode
Capacidade offline Não Não Não
Modelo de custo Uso da API da Anthropic Uso da API da OpenAI Uso da API do provedor

A recomendação: use o Claude Code CLI como seu runtime principal. Use os agentes nativos do Xcode 26.3 para edições inline rápidas. Use o Codex CLI para passes de revisão e operações em batch. Os três se complementam em vez de competir.

Configuração do MCP: a configuração completa

O MCP (Model Context Protocol) é o que transforma um agente de “escreve Swift e espera que você compile” para “escreve Swift, compila, lê erros estruturados e corrige tudo”. Esta seção vai mais fundo do que o post do blog, cobrindo os dois servidores, todos os métodos de instalação, verificação e a configuração do agente que garante que as ferramentas sejam realmente usadas.

XcodeBuildMCP: 59 ferramentas para desenvolvimento iOS headless

XcodeBuildMCP encapsula xcodebuild, xcrun simctl e LLDB em 59 ferramentas MCP estruturadas. Ele funciona sem o Xcode aberto: todo o ciclo de build, teste e depuração opera em modo headless por meio das ferramentas de linha de comando da Apple.

Opções de instalação:

# 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

A flag -s user disponibiliza o servidor globalmente em todos os projetos. Omita essa flag para uma instalação restrita ao projeto (útil se você só quiser MCP em projetos iOS, não em projetos web).

A variável de ambiente -e XCODEBUILDMCP_SENTRY_DISABLED=true desativa a telemetria de relatórios de crash. O XcodeBuildMCP inclui Sentry por padrão, que envia dados de erro incluindo caminhos de arquivos. Desative isso, a menos que você queira contribuir com diagnósticos para o projeto.1

Inventário completo de ferramentas (59 ferramentas em 8 categorias):

Categoria Ferramentas O que elas fazem
Descoberta de projeto discover_projs, list_schemes, list_targets Encontram arquivos .xcodeproj/.xcworkspace, listam schemes e targets disponíveis
Build build_sim, build_device, build_mac Fazem build com saída estruturada de erros/avisos em JSON por arquivo e linha
Testes test_sim, test_device Executam testes com resultados de aprovação/falha por método
Ciclo de vida do simulador list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults Criam, inicializam, gerenciam e configuram simuladores
Gerenciamento de dispositivos list_devices, install_device, launch_device Fazem implantação e gerenciamento em dispositivos reais
Depuração debug_attach_sim, debug_attach_device, debug_breakpoint, debug_stack, debug_variables, debug_eval, debug_continue, debug_step, debug_detach Integração completa com LLDB, com breakpoints e inspeção de variáveis
Automação de UI snapshot_ui, screenshot, tap, swipe, type_text Interação automatizada e captura visual
Scaffolding de projeto create_project, add_file, add_package Criam projetos e adicionam dependências

As ferramentas mais importantes no trabalho diário:

  1. build_sim — Você vai chamar isso centenas de vezes. Ela retorna JSON com erros categorizados por arquivo, linha e gravidade. O agente lê o erro, navega até o arquivo e corrige sem você tocar em nada.

  2. test_sim — Retorna resultados por método de teste. O agente sabe exatamente qual teste falhou e por quê, não apenas que “os testes falharam”.

  3. list_sims + boot_sim — Gerenciamento de simulador sem decorar flags de xcrun simctl. O agente descobre os runtimes disponíveis e escolhe um dispositivo adequado.

  4. discover_projs + list_schemes — Introspecção do projeto. O agente não precisa adivinhar o nome do seu scheme nem a estrutura do workspace.

  5. debug_attach_sim + debug_stack + debug_variables — Depuração remota com LLDB. O agente pode definir breakpoints, inspecionar variáveis e avançar pelo código sem você abrir o depurador.

Apple Xcode MCP: 20 ferramentas que fazem ponte com o Xcode

O servidor MCP da Apple vem com o Xcode 26.3 via xcrun mcpbridge. Ele se comunica com um processo do Xcode em execução por XPC (framework de comunicação entre processos da Apple), expondo estado interno que nenhuma ferramenta CLI consegue acessar.

Instalação:

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

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

Requer Xcode 26.3+ e um processo do Xcode em execução. Se o Xcode não estiver aberto, toda chamada MCP por esse servidor vai falhar ou travar. O XcodeBuildMCP não tem essa limitação.

Inventário de ferramentas (20 ferramentas em 5 categorias):

Categoria Ferramentas O que elas fazem
Operações de arquivo XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep Leem/escrevem arquivos dentro do contexto do projeto Xcode
Build e teste BuildProject, GetBuildLog, RunAllTests, RunSomeTests Fazem build e executam testes com o sistema de build interno do Xcode
Diagnósticos XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile Diagnósticos de código em tempo real (não apenas erros de build)
Código e documentação ExecuteSnippet, DocumentationSearch Execução no Swift REPL e busca na documentação da Apple
Previews RenderPreview Renderização headless de previews SwiftUI

Ferramentas exclusivas do Apple MCP (não disponíveis no XcodeBuildMCP):

  1. DocumentationSearch — Busca na documentação para desenvolvedores da Apple, incluindo sessões da WWDC. É mais rápida e confiável do que busca na web para dúvidas sobre API da Apple. Pergunte “is HKQuantityType(.dietaryWater) valid?” e receba uma resposta definitiva direto da fonte.

  2. ExecuteSnippet — Execução no Swift REPL dentro do contexto do projeto. O agente pode verificar o comportamento de API, testar conversões de tipo e validar expressões sem compilar o app inteiro.

  3. RenderPreview — Renderiza previews SwiftUI em modo headless. O agente pode verificar se uma view renderiza sem erros, embora não consiga avaliar a correção visual (a renderização é retornada como dados, não inspecionada visualmente).

  4. XcodeListNavigatorIssues — Retorna diagnósticos em tempo real do analisador do Xcode, não apenas erros de build. Captura problemas como variáveis não usadas, possíveis ciclos de retenção e avisos de depreciação que o sistema de build não mostra.

Por que usar os dois servidores

Eles se sobrepõem em builds e testes, mas são fundamentalmente diferentes:

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

Use XcodeBuildMCP para: O ciclo de build, teste e depuração. Ele funciona sem o Xcode aberto, consome menos memória do sistema e oferece gerenciamento mais rico de simuladores e dispositivos. Esta é sua principal ferramenta de build.

Use Apple Xcode MCP para: Consultas de documentação, verificação no Swift REPL, renderização de previews SwiftUI e diagnósticos em tempo real. Mantenha o Xcode aberto durante sessões que precisem desses recursos.

Na prática: Eu uso XcodeBuildMCP em cerca de 90% das chamadas MCP e Apple Xcode MCP para documentação e verificação no REPL. O agente usa XcodeBuildMCP por padrão para builds e testes porque é mais rápido (sem overhead do processo do Xcode) e mais confiável (sem dependência de XPC).

Verificação

Depois de instalar os dois servidores, verifique se eles estão conectados:

# List all configured MCP servers
claude mcp list

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

Se um servidor aparecer como “Disconnected” ou não aparecer:

  1. XcodeBuildMCP não conecta: Verifique se o Node.js está instalado (node --version). O comando npx requer Node.js 18+.
  2. Apple Xcode MCP não conecta: Verifique se o Xcode 26.3+ está instalado e se o comando xcrun mcpbridge funciona no seu terminal. Abra o Xcode pelo menos uma vez para aceitar o contrato de licença.
  3. Nenhum dos dois aparece: Reinicie o Claude Code (claude em um novo terminal). Servidores MCP registrados no meio da sessão podem não aparecer até a reinicialização.

Ensinando o agente a usar MCP

Instalar servidores MCP é necessário, mas não suficiente. Sem orientação explícita, o agente pode voltar a executar xcodebuild via Bash (saída não estruturada, tokens de contexto desperdiçados) ou usar busca na web para documentação da Apple (mais lenta, menos confiável).

Adicione isto ao seu CLAUDE.md ou à definição do agente:

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

Essa orientação garante que o agente procure as ferramentas MCP primeiro. Sem ela, você verá o agente construindo comandos xcodebuild longos via Bash, consumindo milhares de tokens de contexto para analisar a saída e, às vezes, identificando incorretamente o erro real.


Padrões de CLAUDE.md para projetos iOS

Seu CLAUDE.md é o arquivo mais importante do projeto para desenvolvimento assistido por agentes. Ele é o documento de onboarding do agente: a diferença entre uma pessoa recém-contratada que leu a documentação de arquitetura e uma que está tentando adivinhar.

Todo projeto iOS que mantenho tem um CLAUDE.md. Aqui estão os padrões que funcionam, extraídos dos 8 apps.

As seções essenciais

Todo CLAUDE.md de iOS precisa destas 6 seções. Todo o resto é opcional.

1. Identidade do projeto

# 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 que isso importa: o agente precisa saber o deployment target antes de escrever qualquer código. Um agente mirando iOS 17 vai usar NavigationView e @ObservedObject. Um agente mirando iOS 26 vai usar NavigationStack e @Observable. O bundle ID importa para entitlements e configuração do HealthKit. A versão do Swift determina o modelo de concorrência (async/await vs. completion handlers, concorrência estrita vs. flexível).

2. Estrutura de arquivos com anotações 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
```

Os comentários inline depois de cada nome de arquivo não são decoração. Eles são a documentação de maior alavancagem que você pode escrever. Quando o agente decide onde adicionar um novo recurso, essas anotações o guiam para o arquivo correto na primeira tentativa, em vez de fazê-lo ler todos os arquivos para entender a estrutura do projeto.

Antipadrão: listar arquivos sem anotações. TimerManager.swift não diz nada ao agente sobre se ele lida com estado, UI ou ambos. TimerManager.swift # Timer state, logic, and repeat handling diz exatamente o que pertence ali e o que não pertence.

3. Comandos de build e teste

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

Inclua os comandos brutos mesmo que o agente deva preferir MCP. Os comandos brutos servem como documentação de fallback e deixam explícitos os nomes de schemes e destinations.

4. Principais padrões e regras

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

Esses padrões evitam que o agente introduza inconsistências. Sem documentação explícita dos padrões, às vezes o agente vai usar ObservableObject em um arquivo e @Observable em outro, ou criar um novo mecanismo de configurações em vez de usar o singleton Settings.shared existente.

5. Coisas que o agente nunca deve fazer

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

Proibições explícitas são mais eficazes do que expectativas implícitas. O agente segue restrições negativas de forma mais confiável do que sugestões positivas porque elas são binárias (faça / não faça) em vez de heurísticas (prefira isto / às vezes use aquilo).

6. Contexto específico de framework

Esta seção varia por app. Inclua-a para qualquer framework que tenha configuração não óbvia:

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

Aqui está um exemplo anotado que mostra como todas as 6 seções funcionam juntas em um app moderadamente complexo. Este é o padrão de CLAUDE.md que uso para Banana List, um app de lista de compras com 53 arquivos, sincronização com iCloud e um servidor MCP personalizado que expõe os dados do app para o 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ínimo — 14 arquivos)

Para projetos pequenos, o CLAUDE.md pode ser conciso. Aqui está o padrão para Reps, um tracker de treino com 14 arquivos. Perceba como até um CLAUDE.md curto cobre todas as 6 seções essenciais:

# 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

São 40 linhas de CLAUDE.md para um projeto com 14 arquivos. Leva 10 minutos para escrever e economiza horas de confusão do agente.

CLAUDE.md real: Starfield Destroyer (SpriteKit + Metal — 32 arquivos)

Projetos de jogo exigem mais contexto específico de framework. O agente precisa entender o scene graph, as categorias de física e a máquina de estados do jogo:

# 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 + visualização de áudio — 41 arquivos)

Projetos Metal precisam do maior volume de contexto específico de framework porque agentes não conseguem verificar a saída visual:

# amp97 - Audio Visualizer

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

## Architecture

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

## File Structure

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

## Metal Pipeline

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

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

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

## Rules

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

Escalando o CLAUDE.md conforme o tamanho do projeto

O nível certo de detalhe depende da contagem de arquivos e da complexidade do framework:

Tamanho do projeto Profundidade do CLAUDE.md Exemplo
Pequeno (< 20 arquivos) Identidade + lista de arquivos + regras Reps (14 arquivos): padrões básicos de SwiftData, comandos de build, proibições
Médio (20-40 arquivos) + Contexto de framework + principais padrões TappyColor (30 arquivos): hierarquia de cenas SpriteKit, categorias de física, game loop
Grande (40+ arquivos) + Diagramas de arquitetura + mapas de relacionamento + informações multi-target Return (63 arquivos): arquitetura cross-platform, diagrama de sync de sessões, diferenças por plataforma
Especializado (Metal/GPU) + Diagramas de pipeline + definições de tipos compartilhados + layouts de buffer amp97 (41 arquivos): estágios do render pipeline, struct de uniforms, gerenciamento de buffer

O custo de documentar em excesso é próximo de zero (o agente pula o que não precisa). O custo de documentar de menos é alto (o agente inventa padrões que entram em conflito com sua codebase).

Checklist de CLAUDE.md

Use este checklist ao criar ou auditar um CLAUDE.md para um projeto iOS:

  • [ ] Bundle ID e deployment target especificados
  • [ ] Versão do Swift e padrão de arquitetura nomeados
  • [ ] Estrutura de arquivos com anotações inline de propósito
  • [ ] Comando de build com scheme e destination corretos
  • [ ] Comando de teste com scheme e destination corretos
  • [ ] Preferência por MCP anotada (“prefer build_sim over xcodebuild”)
  • [ ] Regra de @Observable (nunca ObservableObject)
  • [ ] Regra de NavigationStack (nunca NavigationView)
  • [ ] Proibição de .pbxproj
  • [ ] Contexto específico de framework (permissões do HealthKit, relacionamentos SwiftData, hierarquia SpriteKit, pipeline Metal)
  • [ ] Guards de disponibilidade de plataforma documentados (#if canImport, #if os)
  • [ ] Principais singletons e padrões compartilhados documentados
  • [ ] Limitações conhecidas ou pontos de atenção anotados

Sua primeira sessão com um agente

Com MCP configurado e um CLAUDE.md no seu projeto, aqui está um passo a passo de uma primeira sessão eficaz. Este exemplo usa Claude Code CLI, mas o fluxo de trabalho se aplica a qualquer runtime.

Etapa 1: verifique se o agente consegue ver seu projeto

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.

Se o agente não mencionar o conteúdo do seu CLAUDE.md, verifique se o arquivo está na raiz do projeto (o mesmo diretório de .xcodeproj ou Package.swift).

Etapa 2: execute um build de verificação de integridade

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.

Etapa 3: execute os testes

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.

Etapa 4: implemente um recurso

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

A observação do agente sobre não modificar .pbxproj é resultado das regras no CLAUDE.md. Sem essa regra, o agente tentaria modificar o arquivo do projeto e provavelmente o corromperia.


O que os agentes fazem bem em iOS

Estas são as tarefas em que os agentes produzem de forma consistente uma saída correta e pronta para produção, com revisão humana mínima.

Views e modificadores SwiftUI

Os agentes têm um reconhecimento profundo de padrões para a sintaxe declarativa do SwiftUI. Composição de views, cadeias de modificadores, bindings de estado e layout — tudo isso se encaixa bem nos dados de treinamento do agente porque a superfície API do SwiftUI é bem documentada e os padrões são muito consistentes.

Onde os agentes se destacam: - Criar novas views a partir de uma descrição (“crie uma folha de configurações com toggles para X, Y, Z”) - Aplicar cadeias de modificadores (.glassEffect(), .sensoryFeedback(), .navigationTitle()) - Converter entre padrões de layout (VStack para LazyVGrid, List para ScrollView) - Implementar bindings de formulário @Bindable para modelos SwiftData - Criar preview providers com dados de exemplo

Exemplo de prompt que produz 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.

A especificidade importa. “Crie uma view de configurações” produz uma saída genérica. “Crie uma SettingsView que siga o padrão existente em SettingsSheet.swift” produz uma saída consistente com sua codebase.

Modelos e queries SwiftData

Os agentes lidam de forma confiável com a macro @Model do SwiftData, relacionamentos e padrões @Query. A natureza declarativa do framework (semelhante ao Django ORM ou SQLAlchemy) se encaixa bem nos padrões que o agente viu em muitas codebases.

Onde os agentes se destacam: - Definir classes @Model com relacionamentos - Escrever @Query com descritores de ordenação e predicados - Implementar operações CRUD via modelContext - Planos de migração entre versões de schema - Dados de preview e fixtures de teste

Onde os agentes precisam de orientação: - Expressões #Predicate complexas (a DSL de predicados do SwiftData tem limitações que o agente nem sempre conhece — documente limitações conhecidas no CLAUDE.md) - Configuração de sincronização com CloudKit (automática via SwiftData, mas o agente pode tentar implementar sincronização manual)

Testes unitários

Testes unitários escritos por agentes têm qualidade consistentemente alta em projetos iOS. O agente entende padrões XCTest, métodos de teste async e o 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)

O agente produz casos XCTest bem estruturados com setUp() e tearDown(), asserções apropriadas e tratamento async para testes baseados em timers.

Refatoração e aplicação de padrões

Os agentes se destacam em refatoração mecânica: extrair views para componentes, converter ObservableObject para @Observable, migrar de NavigationView para NavigationStack e aplicar padrões consistentes em vários arquivos.

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.

O agente percorre metodicamente cada arquivo, aplica a transformação corretamente e mantém a funcionalidade existente. Este é um trabalho de alto impacto — uma refatoração que levaria uma hora de edição manual é concluída em minutos com precisão quase perfeita.

Diagnóstico de erros de build via MCP

Com a saída estruturada do MCP, os agentes diagnosticam erros de build mais rápido do que a maioria dos desenvolvedores. O agente lê o JSON do erro, identifica o arquivo e a linha exatos, entende a mensagem de erro e aplica a correção — muitas vezes em um único turno.

Erros que os agentes corrigem de forma autônoma: - Imports ausentes - Incompatibilidades de tipo - Lacunas de conformidade com protocolos - Uso obsoleto de API (com substituição) - Parâmetros obrigatórios ausentes no inicializador - Violações de controle de acesso

Erros em que os agentes precisam de ajuda: - Resolução ambígua de tipos (vários módulos definem o mesmo tipo) - Falhas complexas de constraints genéricas - Erros de expansão de macro (o agente não consegue ver a saída expandida da macro)

Gerenciamento do simulador

Os agentes lidam bem com o ciclo de vida do simulador via MCP:

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

O agente chama list_sims para encontrar runtimes disponíveis, boot_sim para iniciar o simulador, build_sim para compilar e instalar, e screenshot para capturar — tudo por meio de chamadas estruturadas do MCP.

O que os agentes fazem mal no iOS

Um retrato honesto de onde os agentes falham. Conhecer esses limites evita frustração e tokens desperdiçados.

Modificações no arquivo .pbxproj — NUNCA

Esta é a regra mais importante no desenvolvimento iOS com agentes. O arquivo .pbxproj é a configuração de projeto do Xcode: um arquivo de texto estruturado com referências UUID, listas de fases de build e associação a targets. Em tese, ele é legível por humanos; na prática, é impossível de analisar com segurança para agentes de AI.

Por que os agentes falham com .pbxproj: - O arquivo usa um formato próprio (não JSON, não YAML, não XML) com significado posicional - Cada entrada é referenciada por UUID: adicionar um arquivo exige atualizar de 3 a 5 seções diferentes de forma consistente - Um único caractere fora do lugar corrompe todo o arquivo de projeto - A resolução de conflitos de merge do Xcode para .pbxproj já é frágil; edições por agentes pioram isso

O que acontece quando um agente edita .pbxproj: 1. A edição parece funcionar (o agente informa “arquivo atualizado”) 2. O Xcode se recusa a abrir o projeto (“The project file is corrupted”) 3. Você passa de 15 a 60 minutos recuperando a partir do histórico do git 4. Você aprende a adicionar o hook PreToolUse (veja Hooks)

O workflow: O agente cria arquivos Swift. Você os adiciona manualmente ao projeto Xcode (arrastando para o Xcode ou usando File > Add Files). Isso leva 5 segundos por arquivo e evita horas de recuperação.

Para projetos Swift Package Manager: Essa limitação é menos grave. Package.swift é um arquivo Swift padrão que agentes conseguem editar de forma confiável. Se o seu projeto usa exclusivamente SPM (sem .xcodeproj), o agente consegue gerenciar toda a estrutura do projeto.

Edições complexas no Interface Builder / Storyboard

Se o seu projeto usa Interface Builder (arquivos .xib) ou Storyboards (arquivos .storyboard), agentes não conseguem editá-los de forma significativa. Eles são arquivos XML com UUIDs gerados automaticamente, referências de constraints e conexões de outlets, projetados para edição visual, não para edição em texto.

A mitigação: Use SwiftUI exclusivamente para novas views. Se o seu projeto tem arquivos legados do Interface Builder, deixe-os como estão e crie novas UIs em SwiftUI.

Otimização de performance

Agentes escrevem código correto, mas não necessariamente código performático. Eles não conseguem fazer profiling do app, identificar gargalos nem medir frame rates. Otimização de performance exige:

  1. Profiling com Instruments (ferramenta visual, inacessível ao agente)
  2. Entendimento das características de GPU/CPU do dispositivo específico
  3. Mudanças iterativas guiadas por medição

Onde isso aparece: - Otimização de shaders Metal (o agente escreve Metal válido, mas não consegue medir o tempo de frame da GPU) - Complexidade do body de views SwiftUI (o agente cria views profundamente aninhadas que causam overhead de redesenho) - Otimização de fetch em Core Data / SwiftData (o agente escreve queries corretas que podem ser lentas em datasets grandes)

A mitigação: Use agentes para a implementação, faça profiling manualmente com Instruments e depois peça ao agente para aplicar otimizações específicas que você identificou.

Code signing e provisioning

Agentes não conseguem depurar problemas de code signing além de ler a mensagem de erro. Gerenciamento de provisioning profiles, criação de certificados, configuração de entitlements e envio para a App Store são workflows fundamentalmente operados por humanos, envolvendo o portal Apple Developer, Keychain Access e a UI de signing do Xcode.

O que o agente vê: “Signing for ‘Return’ requires a development team.”

O que o agente não consegue ver: Se o seu certificado expirou, se o provisioning profile inclui o dispositivo, se o bundle ID corresponde ao App ID ou se o arquivo de entitlements está correto.

A mitigação: Faça todo o signing na aba Signing & Capabilities do Xcode. Não peça a agentes para depurar falhas de signing.

Debugging complexo de shaders Metal

Agentes escrevem Metal Shading Language (MSL) sintaticamente correto, mas não conseguem verificar a saída visual nem depurar problemas no lado da GPU. Shaders Metal executam na GPU; o agente não tem nenhum mecanismo de feedback para saber se o shader produz resultados visuais corretos.

O que agentes conseguem fazer com Metal: - Escrever vertex e fragment shaders a partir de descrições - Configurar o pipeline de renderização Metal em Swift - Criar compute shaders para operações paralelas em dados - Corrigir erros de compilação em arquivos .metal

O que agentes não conseguem fazer com Metal: - Verificar a correção visual da saída do shader - Depurar performance da GPU (tempo de frame, occupancy, largura de banda de memória) - Diagnosticar artefatos visuais (banding, problemas de precisão, color space incorreto) - Testar em diferentes arquiteturas de GPU (diferenças de comportamento entre A-series e M-series)

A mitigação: Teste shaders Metal em dispositivos físicos. A implementação de Metal do Simulator não representa o comportamento da GPU no dispositivo. Use o GPU Frame Capture do Xcode para debugging visual.

Verificação visual de layout

Agentes não conseguem ver a UI do seu app. Eles escrevem código de layout em SwiftUI e conseguem verificar se ele compila, mas não conseguem dizer se a tela resultante está correta. Uma view renderizada 10 pixels fora do centro, usando o peso de fonte errado ou com elementos sobrepostos não gera erro de build e passa em todos os testes de lógica.

A mitigação: Revise visualmente as mudanças de UI. Use SwiftUI Previews no Xcode (ou RenderPreview via Apple MCP para renderização headless) para verificar o layout. Considere snapshot testing com bibliotecas como swift-snapshot-testing para detecção automatizada de regressões visuais.


Hooks para desenvolvimento iOS

Hooks são comandos shell que são executados de forma determinística em pontos específicos do fluxo de trabalho do agente. Eles são o mecanismo de imposição — a diferença entre “por favor, não edite .pbxproj” (uma sugestão que o agente pode ignorar) e “você não pode editar .pbxproj” (um bloqueio rígido).

Para saber mais sobre o sistema de hooks, consulte o guia de hooks do Claude Code. Esta seção cobre padrões de hooks específicos para iOS.

PreToolUse: bloquear gravações em .pbxproj

O hook mais importante em qualquer projeto iOS. Ele impede que o agente grave em arquivos .pbxproj, diretórios .xcodeproj/ e outros arquivos gerenciados pelo 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'"
      }
    ]
  }
}

Coloque isso em .claude/settings.json na raiz do projeto ou em ~/.claude/settings.json para proteção global.

Como funciona: Quando o agente tenta usar a ferramenta Edit ou Write em qualquer arquivo que corresponda ao padrão, o hook é executado, detecta o caminho do arquivo, imprime um aviso em stderr e sai com o código 2 (o que bloqueia o uso da ferramenta). O agente recebe a mensagem de erro e ajusta sua abordagem.

O que ele captura: - Edições diretas em .pbxproj - Qualquer arquivo dentro dos diretórios .xcodeproj/ ou .xcworkspace/ - Arquivos do Interface Builder (.xib, .storyboard)

PostToolUse: formatar ao salvar com SwiftFormat

Formate arquivos Swift automaticamente sempre que o agente gravar ou editar esses arquivos:

{
  "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 deve estar instalado (brew install swiftformat).

Por que isso importa: Agentes produzem Swift sintaticamente correto, mas não seguem convenções de formatação de forma consistente. SwiftFormat normaliza indentação, posicionamento de chaves e ordenação de imports. O hook de formatação ao salvar significa que todo arquivo Swift tocado pelo agente é formatado automaticamente antes de você vê-lo.

Opcional: adicione um arquivo de configuração .swiftformat à raiz do projeto para personalizar as regras de formatação:

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

PostToolUse: executar SwiftLint automaticamente

Se você usa SwiftLint, execute-o após cada edição em arquivos 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'"
      }
    ]
  }
}

O || true impede que avisos de lint bloqueiem o agente. Se quiser que violações de lint bloqueiem, remova isso.

PostToolUse: executar build automaticamente após alterações

Para ciclos de feedback agressivos, dispare um build após cada alteração em arquivos 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'"
      }
    ]
  }
}

Aviso: Isso é caro. Cada edição de arquivo dispara um build. Use com moderação — isso é mais útil durante sessões de depuração em que você quer feedback imediato de build. Para desenvolvimento normal, deixe o agente disparar builds manualmente via MCP quando estiver pronto.

PreToolUse: bloquear modificações em entitlements

Proteja seu arquivo de entitlements contra modificações acidentais do 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'"
      }
    ]
  }
}

Configuração combinada de hooks para iOS

Aqui está o .claude/settings.json completo que uso em todos os projetos 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'"
      }
    ]
  }
}

Isso dá a você duas garantias: 1. O agente não pode corromper arquivos de projeto do Xcode (bloqueio PreToolUse) 2. Todo arquivo Swift tocado pelo agente é formatado automaticamente (formatação PostToolUse)


Padrões de arquitetura que funcionam com agentes

Nem todas as arquiteturas Swift são igualmente amigáveis para agentes. Estes padrões geram os melhores resultados porque são explícitos, consistentes e bem representados nos dados de treinamento.

@Observable (nunca ObservableObject)

Targets iOS 26+ devem usar @Observable exclusivamente. Este é tanto o padrão moderno quanto o padrão mais amigável 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 que @Observable é amigável para agentes: o padrão é mais simples (não exige anotações @Published), o modelo de propriedade é mais claro (@State em vez de @StateObject vs. @ObservedObject) e os agentes produzem menos bugs com ele porque há menos partes móveis.

Documente isso no CLAUDE.md: mesmo com iOS 26 como target, agentes ocasionalmente voltam a padrões ObservableObject vindos dos dados de treinamento. Uma proibição explícita evita isso.

// 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 é iOS 16+ e o único padrão de navegação que você deve usar em código novo. O padrão type-safe navigationDestination(for:) evita que o agente crie links de navegação incorretos.

SwiftData para persistência

Modelos SwiftData são o padrão de persistência mais limpo para desenvolvimento assistido 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
    }
}

Regras principais para agentes trabalhando com SwiftData: 1. Classes @Model são automaticamente Observable — não adicione @Observable 2. Use @Bindable para bindings de formulário: @Bindable var item: GroceryItem 3. Use @Query em views para dados reativos: @Query var items: [GroceryItem] 4. Use modelContext.fetch() em código que não é view 5. Exclusões de relacionamentos precisam de regras explícitas: .cascade, .nullify, .deny

Concorrência no Swift 6.2

Use concorrência estrita do Swift 6.2 como target para novos projetos:

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

Orientação para agentes sobre concorrência: - Marque todos os view models como @MainActor (evita avisos de data race) - Use async/await para todo trabalho assíncrono (sem completion handlers) - Torne value types Sendable para transferências entre actors - Use Task { } em views para inicialização assíncrona - Use nonisolated apenas quando você tiver medido uma necessidade de performance

Sistema de design Liquid Glass (iOS 26+)

O iOS 26 introduziu o sistema de design Liquid Glass. Agentes lidam bem com ele quando recebem orientação 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()

Inclua no CLAUDE.md: “Use .glassEffect() em fundos de seções e containers de cards. Barras de navegação adotam automaticamente o material glass no iOS 26. Não recrie manualmente efeitos glass com materiais customizados — use o modificador do sistema.”


Contexto específico de frameworks

Cada framework da Apple tem considerações específicas para agentes. Esta seção cobre os frameworks usados nos 8 apps.

HealthKit

Apps que usam: Return, Water

HealthKit exige tratamento cuidadoso de permissões e 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
        }
    }
}

Regras para agentes com HealthKit: - Sempre proteja com HKHealthStore.isHealthDataAvailable() - Nunca presuma autorização — verifique em toda escrita - Use #if canImport(HealthKit) para código multiplataforma (HealthKit indisponível no tvOS) - Nunca armazene dados de saúde localmente além do que o HealthKit fornece - Inclua NSHealthShareUsageDescription e NSHealthUpdateUsageDescription no Info.plist

SpriteKit

Apps que usam: TappyColor, Starfield Destroyer

O modelo de grafo de cenas do SpriteKit exige orientação 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)

Pontos fortes dos agentes com SpriteKit: - Criar sequências e grupos SKAction - Configurar physics bodies e detecção de contato - Implementar máquinas de estado de jogo - Construir overlays de HUD

Pontos fracos dos agentes com SpriteKit: - Game loops sensíveis a performance (o agente adiciona trabalho desnecessário por frame) - Simulações físicas complexas (physics customizada supera SKPhysicsBody em precisão) - Ajuste de particle effects (visual, exige iteração)

Metal

Apps que usam: amp97, Water, Starfield Destroyer

Metal é o framework em que os agentes mais têm dificuldade. O modelo de programação GPU é fundamentalmente diferente do Swift no lado da CPU, e agentes não conseguem verificar a saída 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

O que incluir no CLAUDE.md para projetos Metal: - A definição da struct Uniforms (compartilhada entre Swift e MSL) - O padrão de configuração do render pipeline state - Índices de buffers e seus propósitos - Quais shaders existem e o que cada um faz - Problemas de precisão conhecidos (half vs. float)

Live Activities

Apps que usam: Return

Live Activities exigem configuração específica que agentes lidam bem depois de 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 usam: 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)

Padrões multiplataforma

O Return abrange iOS, watchOS e tvOS. O desenvolvimento multiplataforma com agentes exige documentação explícita dos limites entre plataformas.

Organização do código compartilhado

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

Regra para agentes: “Se um arquivo está em Shared/, as mudanças afetam todas as plataformas. Se um arquivo está em um diretório de plataforma, as mudanças são isoladas. Sempre verifique em qual diretório um arquivo está antes de modificá-lo.”

Guardas de disponibilidade 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

Orientação para agentes: “Sempre use guardas #if canImport() ou #if os() ao usar frameworks específicos de plataforma. Não presuma que um framework está disponível em todos os targets.”

Adaptação 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
    }
}

Fluxos de trabalho avançados

Loops autônomos de build-teste-correção

O padrão mais poderoso: dê ao agente uma especificação de recurso e deixe que ele itere autonomamente por ciclos de build-teste-correção.

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.

O agente escreve código, faz o build via MCP, lê erros estruturados, corrige-os e repete. Um recurso que exigiria 5 a 10 ciclos humanos de build-erro-correção é concluído em um único loop autônomo.

Quando isso funciona: Recursos bem definidos com critérios de aceitação claros.

Quando isso falha: Recursos em aberto (“deixe mais bonito”), código sensível a performance ou qualquer coisa que exija verificação visual.

Delegação para subagentes em iOS

O sistema de subagentes do Claude Code funciona para projetos 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.

O subagente explora a documentação e os padrões de código em uma janela de contexto separada, retorna um resumo, e a sessão principal implementa a recomendação. Isso evita que a pesquisa consuma seu contexto principal.

Aplicação de padrões entre apps

Quando você mantém vários apps iOS com padrões consistentes, os agentes podem aplicar padrões de um app em outro:

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.

O agente lê o padrão de origem, entende a estrutura e cria uma implementação consistente no projeto de destino.

Revisão com dois agentes (Claude + Codex)

Para mudanças críticas, use dois agentes de famílias de modelos diferentes:

  1. Claude Code escreve a implementação
  2. Codex CLI revisa em uma passagem 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."

Famílias de modelos diferentes detectam classes diferentes de erros. Isso é especialmente valioso para shaders Metal e padrões de concorrência, em que bugs sutis são fáceis de introduzir.

O que a revisão dupla detecta que uma revisão única deixa passar:

Tipo de problema Ponto forte do Claude Ponto forte do Codex
Ciclos de relacionamento em SwiftData Moderado Forte (GPT-4o)
Lacunas de isolamento com @MainActor Forte Moderado
Alinhamento de buffer Metal Moderado Moderado
Detecção de ciclos de retenção Forte (Opus) Forte (o3)
Consciência de depreciação do API Forte (dados de treinamento mais recentes) Moderado
Condições de corrida em concorrência Forte Forte (padrões diferentes detectados)

A revisão dupla não é sobre encontrar mais bugs — é sobre encontrar bugs diferentes. Cada família de modelos tem modos de falha diferentes no reconhecimento de padrões.

Operações em lote em vários apps

Quando uma mudança de framework ou padrão afeta vários 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

Use com cautela. A flag --dangerously-skip-permissions é necessária para o modo não interativo, mas ignora todas as verificações de segurança. Garanta que seus hooks PreToolUse estejam em vigor para proteger arquivos .pbxproj.

Apps que usam LLM on-device da Apple

Se o seu app chama o framework Foundation Models da Apple (por exemplo, para sumarização offline, classificação ou geração de saída estruturada), os agentes precisam conhecer o orçamento do prompt. O iOS 26.4 adicionou duas APIs ao SystemLanguageModel que substituíram a suposição anterior de 4096 tokens: contextSize (máximo de tokens que o modelo aceita em uma única conversa) e tokenCount(for:) (async throws, retorna quantos tokens um determinado prompt realmente custa).16 Ambas são @backDeployed(before: iOS 26.4), então estão disponíveis em todas as versões de OS compatíveis com FM sem uma escada de #available.

O padrão que um agente deve seguir ao gerar código de construção de prompt:

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
}

Adicione este padrão ao seu CLAUDE.md se o app tocar em SystemLanguageModel. Sem isso, os agentes voltam ao antigo hardcode de 4096 e truncam prompts silenciosamente em dispositivos que vêm com janelas de contexto maiores. A assinatura async throws em tokenCount(for:) é essencial — agentes que colarem uma versão síncrona não vão compilar.


Estudos de caso reais

Conselhos abstratos são fáceis. Aqui estão cenários específicos dos 8 apps que mostram como o desenvolvimento iOS assistido por agentes funciona na prática — inclusive as falhas.

Estudo de caso 1: adicionar um app para TV ao Return (sucesso)

A tarefa: Adicionar um target tvOS ao Return, um timer de meditação que já tinha versões para iOS e watchOS. O app para TV precisava de navegação com Siri Remote, UI para tela grande e sincronização de configurações com o app iOS.

O que o agente fez bem: - Leu o TimerManager existente no iOS e criou um TVTimerManager que omitia Live Activities e HealthKit (indisponíveis no tvOS) - Criou estilos de botão personalizados para navegação por foco com Siri Remote (TVCapsuleButtonStyle, TVCircleButtonStyle) - Criou um componente TVStepper que substitui seletores em roda (não usáveis com Siri Remote) por botões +/- - Implementou sincronização de configurações via App Groups (group.com.941apps.Return) - Adicionou proteções #if os(tvOS) em todo o código compartilhado - Compilou e testou via MCP com platform=tvOS Simulator,name=Apple TV

O que precisei fazer manualmente: - Criar o target tvOS no Xcode (File > New > Target > tvOS App) - Adicionar o novo target ao projeto Xcode (alterações no .pbxproj) - Configurar o entitlement de App Groups para o target da TV - Adicionar o target da TV ao scheme existente ou criar um novo - Adicionar manualmente todos os arquivos Swift criados pelo agente ao target da TV - Testar manualmente a navegação com Siri Remote (o agente não consegue avaliar o comportamento de foco)

Resultado: 15 novos arquivos Swift, app para TV totalmente funcional, em aproximadamente 3 horas de trabalho assistido por agente. Pela minha estimativa, o agente cuidou de cerca de 80% do trabalho de implementação; eu cuidei das partes que exigiam interação com a UI do Xcode (entitlements, configuração de target, flags de capabilities) e testes manuais de foco em uma Apple TV real. O trabalho solo equivalente neste codebase — com base em recursos parecidos que já lancei sem agentes — teria levado vários dias.

Estudo de caso 2: depuração de shader Metal no amp97 (falha parcial)

A tarefa: Adicionar um sistema de intensidade baseado em energia ao shader de osciloscópio. A visualização deveria pulsar com a energia do áudio.

O que aconteceu: 1. O agente escreveu uma modificação válida no shader Metal adicionando um uniform uEnergy e tonemapping HDR 2. O código compilou sem erros 3. No dispositivo, a visualização ficou completamente branca — o coeficiente de intensidade estava 10x alto demais (3,5 em vez de 0,30) 4. O agente não conseguia ver a tela branca, então não tinha sinal de feedback 5. Identifiquei o problema visualmente e pedi ao agente para reduzir o coeficiente 6. O agente reduziu, mas a máquina de estados de energia como um todo estava complexa demais e quebrou o visualizador de outras formas 7. Revertido por completo — dois commits (67959ed e cda4830) revertidos em 869d914

A lição: Shaders Metal são o domínio mais difícil para desenvolvimento assistido por agentes porque o loop de feedback é quebrado. O agente consegue verificar sintaxe (compila) e semântica (tipos corretos), mas não consegue verificar o resultado (se parece certo). Qualquer modificação de shader que altere o comportamento visual exige verificação humana no dispositivo.

O que adicionei ao CLAUDE.md depois disso: “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.”

Estudo de caso 3: migração SwiftData no Banana List (sucesso)

A tarefa: Migrar o modelo de dados da V1 para a V2, adicionando um campo quantity a GroceryItem e um novo modelo Category com relacionamentos.

O que o agente fez: 1. Leu as definições existentes do modelo V1 2. Criou definições do modelo V2 com os novos campos e relacionamentos 3. Escreveu um GroceryMigrationPlan com conformidade ao protocolo SchemaMigrationPlan 4. Implementou o estágio de migração V1toV2: adicionou quantity: 1 e category: nil como padrões 5. Atualizou todas as views para dar suporte aos novos campos 6. Atualizou SampleData.swift para previews 7. Compilou e executou testes via MCP — todos passaram 8. Criou testes unitários específicos para a migração

O ponto-chave: O agente teve sucesso porque migrações SwiftData seguem um padrão de protocolo bem definido, amplamente representado na documentação da Apple e nos dados de treinamento. O CLAUDE.md documentava explicitamente o modelo V1, então o agente entendeu de onde estava migrando.

Estudo de caso 4: sincronização de sessões via iCloud no Return (sucesso com complexidade)

A tarefa: Implementar registro de sessões de meditação entre dispositivos. Sessões concluídas na Apple TV ou no Mac deveriam sincronizar com o iPhone para registro no HealthKit.

O que o agente produziu:

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

O agente: 1. Criou o modelo de dados MeditationSession com UUID, datas, duração, dispositivo de origem e status de sincronização com HealthKit 2. Criou um singleton SessionStore gerenciando NSUbiquitousKeyValueStore para sincronização via iCloud 3. Implementou resolução de conflitos de merge (desduplicação baseada em UUID) 4. Adicionou SessionHistoryView com adaptações específicas por plataforma (deslizar para excluir no iOS, baseado em foco no tvOS) 5. Conectou a sincronização com HealthKit no lado do iPhone para sessões vindas de outros dispositivos

O que exigiu iteração: A implementação inicial não lidava com o caso em que o app do iPhone inicia em segundo plano (sem notificação de foreground para sincronização). O agente precisou de orientação específica: “Use NSUbiquitousKeyValueStore.didChangeExternallyNotification to trigger sync on background KV changes.” Depois dessa dica, a implementação ficou correta.

A lição: Agentes lidam bem com padrões arquiteturais multiplataforma quando a arquitetura é descrita com clareza. O padrão de sincronização via iCloud não é trivial, mas segue um padrão documentado da Apple que o agente entendeu. O caso de borda (sincronização em segundo plano) exigiu conhecimento humano de domínio porque não é bem documentado.

Estudo de caso 5: integração com Game Center no Starfield Destroyer (sucesso)

A tarefa: Adicionar leaderboards e achievements do Game Center ao shooter espacial.

O que o agente fez bem: - Implementou GKLocalPlayer.local.authenticateHandler no ponto de entrada do app - Criou um GameCenterManager com métodos para envio de pontuação e relatório de achievements - Adicionou verificação de estado de autenticação antes de todas as operações do Game Center - Lidou bem com o caso offline (o jogo funciona sem Game Center e envia quando reconecta) - Criou definições de achievements correspondentes ao sistema de progressão de 8 naves

O que exigiu trabalho manual: - Criar os leaderboards e achievements no App Store Connect (portal web, inacessível ao agente) - Configurar o entitlement de Game Center no Xcode - Testar com uma conta sandbox do Game Center (exige login manual no dispositivo)


Ciclo de vida do projeto com agentes

Iniciando um novo projeto iOS

O fluxo de trabalho ideal para iniciar um novo projeto com ajuda de agentes:

Fase 1: configuração humana (15-30 minutos) 1. Crie o projeto no Xcode (File > New > Project) 2. Configure signing e capabilities 3. Defina o deployment target e os destinos compatíveis 4. Adicione qualquer entitlement necessário (HealthKit, Game Center etc.) 5. Crie o CLAUDE.md inicial com a identidade e as regras do projeto

Fase 2: implementação pelo agente (horas a dias) 1. O agente cria o modelo de dados (SwiftData, Core Data ou structs simples) 2. O agente cria views seguindo seus padrões documentados 3. O agente implementa a lógica de negócio em classes manager/service 4. O agente escreve testes unitários 5. Loop de build-test-fix via MCP (autônomo)

Fase 3: integração humana (30-60 minutos) 1. Adicione os arquivos criados pelo agente aos targets do Xcode 2. Verifique signing e entitlements 3. Teste em um dispositivo físico 4. Revise o layout visual e a UX 5. Envie para o App Store Connect

Mantendo um projeto existente

Para desenvolvimento contínuo em apps já estabelecidos:

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]

A eficácia do agente aumenta conforme o seu CLAUDE.md reflete bem o estado atual do projeto. Atualize o CLAUDE.md quando você adicionar recursos novos importantes, mudar padrões arquiteturais ou introduzir novos frameworks.

Quando envolver o agente ou não

Tarefa Agente? Por quê
Nova view SwiftUI Sim Agentes são excelentes com UI declarativa
Mudanças no modelo SwiftData Sim Bem definido, testável
Testes unitários Sim Mecânico, baseado em padrões
Refatoração Sim Sistemático, multi-arquivo
Diagnóstico de erro de build Sim (via MCP) Loop de feedback estruturado
Novo target do Xcode Não Exige UI do Xcode e mudanças em .pbxproj
Signing e provisioning Não Baseado em portal, inacessível ao agente
Polimento visual Não Exige julgamento estético humano
Ajuste de shader Metal Não Exige testes de GPU em dispositivo
Envio para a App Store Não Portal e Xcode Organizer
Profiling de performance Não Exige Instruments
Auditoria de acessibilidade Parcial O agente pode adicionar labels; humanos verificam o VoiceOver

Configurando definições de agentes

Se você usa o sistema de definição de agentes do Claude Code (.claude/agents/), crie um 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

Referencie esse agente com @ios-developer em sessões do Claude Code.


Padrões de teste para iOS assistido por agentes

Agentes escrevem ótimos testes unitários quando recebem orientação clara. Estes são os padrões que produzem os melhores resultados.

Organização de arquivos de teste

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

Prompt de teste eficaz:

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 que isso funciona: Critérios de aceite numerados dão ao agente uma checklist. Referenciar um arquivo de teste existente estabelece o padrão. Especificar o uso de setUp() evita que o agente crie estado de teste emaranhado.

Prompt de teste ineficaz:

Write tests for TimerManager.

Isso produz testes genéricos e superficiais, que deixam passar casos de borda e podem não seguir os padrões do seu projeto.

Padrões de teste async

Para testar código baseado em timers e código 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)
    }
}

Principais padrões que os agentes precisam ser lembrados de seguir: - @MainActor em métodos de teste que testam classes @MainActor - async throws para testes que usam Task.sleep ou operações async - Tolerância em assertions baseadas em tempo (1,1 segundo, não exatamente 1,0) - setUp() / tearDown() limpos para isolamento dos testes

Snapshot testing

Para detecção de regressão visual, considere adicionar 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.

Agentes configuram snapshot tests corretamente, mas não conseguem revisar as imagens de referência. Você revisa os snapshots iniciais; depois, os testes do agente detectam regressões visuais em mudanças futuras.


Gerenciamento da janela de contexto para projetos iOS

A janela de contexto de 1M (Opus 4.6) é grande, mas não infinita. Projetos iOS têm considerações específicas de gerenciamento de contexto.

Custo em tokens dos arquivos iOS

Tipo de arquivo Tamanho típico Tokens aproximados
View SwiftUI (simples) 50-100 linhas 500-1.000
View SwiftUI (complexa) 200-400 linhas 2.000-4.000
Modelo SwiftData 30-80 linhas 300-800
Classe manager/service 100-300 linhas 1.000-3.000
Metal shader (.metal) 50-200 linhas 500-2.000
Arquivo de teste unitário 50-200 linhas 500-2.000
CLAUDE.md 100-300 linhas 1.000-3.000
Resposta do MCP (build) varia 200-2.000
Resposta do MCP (test) varia 500-5.000

Para um projeto com 50 arquivos: Ler todos os arquivos consome aproximadamente 50.000-100.000 tokens — bem dentro da janela de 1M. O agente consegue manter o projeto inteiro no contexto.

Para um projeto com mais de 100 arquivos: A leitura seletiva se torna necessária. O agente lê CLAUDE.md primeiro (pelas anotações da estrutura de arquivos) e depois lê arquivos específicos conforme necessário. É por isso que as anotações de arquivos no CLAUDE.md são críticas — elas orientam o agente até os arquivos certos sem precisar ler tudo.

Estratégias para projetos grandes

  1. Anotações detalhadas de arquivos no CLAUDE.md — O agente lê o mapa de arquivos e navega diretamente até os arquivos relevantes
  2. Delegação para subagentes — Direcione exploração e pesquisa para subagentes (contexto limpo, retornam resumos)
  3. Prompts focados — “Modifique SettingsView.swift para adicionar um novo toggle” é melhor do que “atualize as configurações”
  4. Limites de sessão — Inicie novas sessões para recursos não relacionados em vez de estender uma sessão longa
  5. Use /compact — O comando de compactação do Claude Code resume a conversa e libera contexto

Eficiência de tokens do MCP

Um dos argumentos mais fortes a favor do MCP: respostas estruturadas de JSON consomem muito menos tokens do que a saída bruta de xcodebuild.

Cenário Tokens brutos do Bash Tokens do MCP Economia
Build bem-sucedido 3.000-10.000 200-500 85-95%
Build com falha (1 erro) 3.000-10.000 300-800 90-92%
Resultados de teste (20 testes) 2.000-5.000 500-1.000 75-80%
Lista de simuladores 500-2.000 200-400 60-80%

Ao longo de uma sessão típica de desenvolvimento com 10-20 ciclos de build, o MCP economiza 30.000-150.000 tokens em comparação com xcodebuild bruto — tokens que continuam disponíveis para o raciocínio real sobre o código.


Solução de problemas

“build_sim failed — scheme not found”

O agente está adivinhando o nome do scheme. Corrija:

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

Ou adicione o nome do scheme explicitamente ao seu CLAUDE.md:

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

“xcrun mcpbridge — command not found”

Você precisa do Xcode 26.3 ou posterior. Verifique com xcodebuild -version. Se você tem Xcode 26.3+ mas o comando ainda falha:

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

# Verify
xcrun mcpbridge --help

“Ferramentas do MCP não aparecem no Claude Code”

Ferramentas do MCP registradas no meio da sessão podem não aparecer até reiniciar. Saia do Claude Code e inicie uma nova sessão:

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

Depois verifique:

You: List all available MCP tools from XcodeBuildMCP.

“O agente continua usando xcodebuild via Bash em vez do MCP”

O agente não está descobrindo as ferramentas do MCP via Tool Search. Duas correções:

  1. Adicione orientação explícita ao CLAUDE.md (veja Ensinando o agente a usar o MCP)
  2. Peça diretamente: “Use the build_sim MCP tool, not xcodebuild via Bash”

“O build é bem-sucedido, mas o agente relata falha”

XcodeBuildMCP analisa a saída de xcodebuild. Se o build produzir warnings que parecem erros (comum com avisos de descontinuação), o agente pode interpretar o resultado incorretamente. Verifique o campo de status real na resposta do MCP.

“O simulador trava durante o boot”

Encerre todos os simuladores e reinicie:

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

Ou peça ao agente:

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

“O agente tentou modificar .pbxproj apesar das regras do CLAUDE.md”

As regras do CLAUDE.md são sugestões. Hooks são imposição. Se você não tiver o hook PreToolUse bloqueando gravações em .pbxproj, o agente eventualmente tentará fazer isso. Instale o 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'"
      }
    ]
  }
}

Regras dizem “por favor, não faça isso.” Hooks dizem “você não pode.”

Perguntas frequentes

Com qual agent runtime devo começar?

Claude Code CLI com XcodeBuildMCP. Ele tem a integração mais profunda com MCP, o sistema de hooks mais maduro e a janela de contexto de 1M (Opus 4.6), que consegue manter projetos iOS inteiros na memória de trabalho. Comece por ele, depois adicione Codex para revisão e agentes nativos do Xcode para edições rápidas inline conforme seu workflow amadurece.

Preciso dos dois servidores MCP?

Para a maioria dos desenvolvedores, só o XcodeBuildMCP cobre 90% das necessidades (builds, testes, simuladores, debugging). Adicione o Xcode MCP da Apple se você quiser busca na documentação, verificação com Swift REPL ou renderização de previews SwiftUI. Você sempre pode adicioná-lo depois — os dois servidores são independentes.

Os agentes podem criar um novo projeto Xcode do zero?

O XcodeBuildMCP inclui uma ferramenta create_project que monta o esqueleto de novos projetos Xcode. Porém, para apps de produção, recomendo criar o projeto no Xcode (para acertar assinatura, capabilities e configuração de targets) e depois usar agentes para toda a implementação de código. Os 5 minutos que você passa no assistente de novo projeto do Xcode economizam horas de problemas de configuração de projeto gerados por agentes.

Como os agentes lidam com dependências do Swift Package Manager?

Bem. Package.swift é um arquivo Swift padrão que agentes conseguem ler e editar com confiabilidade. Adicionar dependências, atualizar intervalos de versão e configurar targets funciona. A limitação é o gerenciamento de dependências baseado em .xcodeproj (a UI de resolução de pacotes do Xcode) — isso é gerenciado pelo Xcode e não deve ser editado por agentes.

Os agentes podem enviar para a App Store?

Não. O envio para a App Store envolve o Organizer do Xcode, provisioning profiles, screenshots, metadados e o portal App Store Connect. Nada disso é acessível via MCP ou ferramentas de linha de comando de um jeito que agentes consigam operar de forma útil. Agentes cuidam de tudo até o archive — implementação, testes, correção de bugs e documentação. A etapa final do envio continua sendo operada por humanos.

Porém, agentes podem ajudar com os metadados da App Store. Peça ao agente para escrever a descrição do app, palavras-chave e texto de novidades com base nas últimas mudanças. Esse é um trabalho de geração de texto em que agentes se saem muito bem.

Como lido com segredos e chaves API no desenvolvimento iOS assistido por agentes?

Nunca faça commit de segredos. Para apps iOS que se conectam a APIs de backend:

  1. Use arquivos .xcconfig para configuração específica por ambiente
  2. Adicione arquivos .xcconfig ao .gitignore
  3. Referencie valores de configuração via build settings do Info.plist
  4. Documente os segredos necessários no CLAUDE.md sem incluir os valores reais
## 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`.

O agente sabe que as chaves existem e onde são usadas, mas nunca vê os valores reais.

E as animações SwiftUI — agentes conseguem escrevê-las?

Agentes escrevem código de animação corretamente do ponto de vista sintático, mas não conseguem verificar o resultado visualmente. Animações simples (.animation(.spring()), .transition(.slide), withAnimation { }) produzem resultados corretos. Animações complexas, em várias etapas e com timing preciso exigem iteração visual que agentes não conseguem fazer.

Eficaz: “Adicione uma animação spring quando o timer fizer a transição entre estados.”

Ineficaz: “Faça a animação do timer parecer satisfatória.” (Subjetivo, exige ajuste visual.)

Como os agentes lidam com padrões de tratamento de erros?

Muito bem. Agentes entendem os padrões do/catch, Result e async throws do Swift:

Implement error handling for the HealthKit authorization flow:
1. Check HKHealthStore.isHealthDataAvailable()  show alert if not
2. Request authorization  handle denial gracefully
3. On write failure  retry once, then show error
4. All errors should be user-facing with localized descriptions

Agentes produzem tratamento de erros estruturado com mensagens adequadas para o usuário. Às vezes eles tratam erros em excesso (capturando exceções que deveriam se propagar), então revise os blocos catch.

Posso usar agentes para implementar acessibilidade?

Parcialmente. Agentes adicionam accessibility labels, hints e traits corretamente:

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

O que agentes não conseguem fazer: verificar se a ordem de navegação do VoiceOver está correta, testar escalonamento de Dynamic Type ou avaliar relações de contraste de cores. Use o Accessibility Inspector do Xcode para verificação.

Como os agentes lidam com migração de Core Data (se não estiver usando SwiftData)?

Agentes escrevem mapeamentos de migração e versões de modelo do Core Data, mas as etapas manuais no Xcode (criar novas versões de modelo, selecionar a versão atual) não podem ser automatizadas. Se você ainda usa Core Data em vez de SwiftData, documente o histórico de versões do modelo no CLAUDE.md:

## Core Data Model Versions
- V1: Initial (GroceryList, GroceryItem)
- V2: Added Category model (current)
- Migration: Lightweight automatic for V1→V2

Como os agentes lidam com previews SwiftUI?

De duas formas: 1. A ferramenta RenderPreview do Apple Xcode MCP renderiza previews sem interface gráfica e retorna o resultado. O agente consegue verificar que um preview compila e renderiza sem erros, mas não consegue avaliar a correção visual. 2. Verificação baseada em build via build_sim confirma que os preview providers compilam. Se um preview quebra em runtime, o build ainda passa — a falha só aparece quando o Xcode tenta renderizar o preview.

Para verificação visual de previews, você ainda precisa manter o Xcode aberto.

E visionOS e Apple Vision Pro?

Os mesmos padrões se aplicam. O XcodeBuildMCP oferece suporte a simuladores visionOS, e os padrões arquiteturais (@Observable, NavigationStack, SwiftData) são idênticos. Código específico de RealityKit (conteúdo 3D, immersive spaces, hand tracking) segue as mesmas limitações do Metal — agentes conseguem escrever código correto, mas não conseguem verificar a saída espacial.

Até que tamanho um projeto pode chegar antes de os agentes começarem a ter dificuldade?

O tamanho da janela de contexto é o fator limitante. Com a janela de 1M tokens do Opus 4.6, Claude Code consegue manter aproximadamente 50-70 arquivos Swift na memória de trabalho ativa ao mesmo tempo. Para projetos maiores, o agente usa busca de arquivos e leitura seletiva para trabalhar com subconjuntos da codebase. Projetos com 100+ arquivos funcionam bem — o agente apenas lê arquivos sob demanda em vez de manter tudo no contexto.

O limite prático não é a quantidade de arquivos, mas a coerência da codebase. Um projeto bem documentado com 200 arquivos e um CLAUDE.md detalhado produz resultados melhores do que um projeto sem documentação com 30 arquivos.

Preciso saber Swift para usar agentes no desenvolvimento iOS?

Você precisa conseguir revisar a saída do agente e tomar decisões arquiteturais. Você não precisa escrever cada linha por conta própria, mas precisa entender Swift bem o suficiente para perceber quando o agente faz escolhas incorretas — especialmente em concorrência, gerenciamento de memória e padrões específicos de frameworks. Um agente é um amplificador 10x da sua habilidade existente, não um substituto para ela.

Como os agentes lidam com conflitos de merge em arquivos Swift?

Agentes resolvem conflitos de merge em arquivos-fonte Swift com confiabilidade. Os marcadores padrão de conflito (<<<<<<<, =======, >>>>>>>) são bem compreendidos por todos os agent runtimes. Porém, conflitos de merge em arquivos .pbxproj continuam sendo uma tarefa de resolução manual — não peça a agentes para resolver conflitos em .pbxproj.

Qual é o custo de executar agentes para desenvolvimento iOS?

Com o plano Max da Anthropic (Opus 4.6, contexto de 1M), uma sessão típica de desenvolvimento iOS dura de 30 a 120 minutos e processa de 200K a 800K tokens. Chamadas de ferramentas MCP adicionam overhead mínimo (respostas estruturadas em JSON são eficientes em tokens em comparação com output bruto de build). O custo é comparável a executar Claude Code para qualquer outra codebase — desenvolvimento iOS não é significativamente mais ou menos caro do que desenvolvimento web.

Posso usar agentes com projetos UIKit?

Sim, mas agentes são mais eficazes com SwiftUI. UIKit exige mais boilerplate, tem uma estrutura menos declarativa e frequentemente envolve arquivos do Interface Builder que agentes não conseguem editar. Se você tem um projeto UIKit, considere usar agentes para a camada de modelo e lógica de negócio enquanto cuida da UI manualmente, ou migre views gradualmente para SwiftUI.

Como os agentes lidam com localização?

Agentes criam e editam arquivos .xcstrings (catálogo de strings do Xcode) com eficiência. Eles conseguem adicionar novas chaves de localização, fornecer traduções e manter consistência entre idiomas. O formato estruturado JSON dos arquivos .xcstrings é amigável para agentes. Para arquivos .strings (formato legado), agentes também funcionam bem — o formato chave-valor é direto.


Erros comuns de agentes em iOS (e como preveni-los)

Estes são os erros recorrentes que observei em milhares de interações com agentes em 8 projetos iOS. Cada um tem uma estratégia de prevenção.

Erro 1: misturar padrões Observable

O que acontece: O agente usa @Observable em um arquivo e ObservableObject em outro, ou adiciona @Observable a uma classe @Model (que já é Observable).

Prevenção: Regras explícitas no 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

Erro 2: criar ciclos de retenção em closures

O que acontece: O agente cria closures que capturam self fortemente, especialmente em Timer.publish, NotificationCenter e completion handlers.

Prevenção: Inclua um padrão de closure no 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

Erro 3: ignorar requisitos de @MainActor

O que acontece: O agente cria classes @Observable sem isolamento @MainActor, causando avisos de concorrência do Swift 6.2 ou crashes em runtime quando atualizações de UI acontecem fora da thread principal.

Prevenção:

## Concurrency Rule
ALL @Observable classes MUST be @MainActor:
```swift
@Observable
@MainActor
final class SomeManager { }
```

O que acontece: O agente usa o NavigationLink(destination:label:) obsoleto em vez do padrão type-safe NavigationLink(value:) + .navigationDestination(for:).

Prevenção:

## 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)) { }`

Erro 5: codificar nomes de simuladores manualmente

O que acontece: O agente escreve comandos de build com nomes específicos de simuladores (“iPhone 16 Pro”) que podem não existir no seu sistema.

Prevenção: MCP cuida disso — list_sims descobre os simuladores disponíveis. No 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.

Erro 6: criar arquivos nos diretórios errados

O que acontece: O agente cria um novo arquivo de view na raiz do projeto em vez do subdiretório Views/, ou coloca um model no grupo errado.

Prevenção: As anotações de estrutura de arquivos no CLAUDE.md orientam o posicionamento. Além disso:

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

Erro 7: não lidar com disponibilidade de plataforma

O que acontece: O agente usa HealthKit em código compartilhado que compila para tvOS (onde HealthKit não está disponível), ou usa ActivityKit em código watchOS.

Prevenção:

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

Erro 8: fazer over-engineering em recursos simples

O que acontece: O agente cria um protocolo, uma extensão de protocolo, uma implementação concreta, uma factory e um contêiner de injeção de dependência para algo que deveria ser uma função utilitária de 20 linhas.

Prevenção: Inclua um princípio de simplicidade:

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

A avaliação honesta

Depois de lançar 8 apps iOS com agentes de AI, este é o resumo:

Os agentes transformaram: A velocidade de implementação. O que levava dias agora leva horas. Views SwiftUI, models SwiftData, testes unitários, refatoração — tudo isso agora é principalmente produzido por agentes e revisado por humanos.

Os agentes não transformaram: Decisões de arquitetura, design visual, otimização de performance ou submissão à App Store. Essas partes continuam sendo conduzidas por humanos.

O multiplicador é real, mas limitado. Minha estimativa subjetiva no portfólio de 8 apps: melhoria de 3-5x no tempo até entregar um recurso em projetos bem documentados com MCP e configuração de hooks adequados. Isso não foi medido contra um grupo de controle; é uma comparação de tempo real entre recursos assistidos por agentes e trabalho solo equivalente nas mesmas codebases. Projetos sem documentação e sem hooks talvez vejam uma melhoria de 1,5-2x — o agente passa tempo demais tentando adivinhar em vez de construir.18

O investimento que compensa: Tempo gasto em CLAUDE.md, hooks e configuração do MCP. Cada hora de setup economiza muitas horas corrigindo erros dos agentes. A configuração é o produto — o agente é o mecanismo de execução.

O que me surpreendeu: O quanto os servidores MCP mudaram a dinâmica. Antes do MCP, agentes eram editores de texto sofisticados que por acaso entendiam Swift. Depois do MCP, eles se tornaram parceiros de desenvolvimento que escrevem, fazem build, testam, debugam e iteram. O loop de feedback estruturado é a diferença entre um agente que escreve código e um que entrega código.

O que eu diria ao meu eu do passado: Comece pelo app menor (Reps, 14 arquivos), acerte o setup de MCP e hooks, escreva um CLAUDE.md completo e depois escale os padrões para projetos maiores. Não comece pelo app multiplataforma de 63 arquivos. O investimento em infraestrutura é o mesmo independentemente do tamanho do projeto — faça uma vez em um projeto pequeno e depois copie para todo o resto.

O futuro: A integração nativa de agentes no Xcode 26.3 é o começo, não o fim. O suporte a MCP enviado pela Apple significa que o toolchain está caminhando para desenvolvimento agent-first. Desenvolvedores que investirem agora em estruturas de projeto compatíveis com agentes — arquivos CLAUDE.md limpos, arquiteturas testáveis, hooks automatizados — vão multiplicar esse investimento conforme as ferramentas melhorarem.


Cartão de referência rápida

Instalação (setup único)

# 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

Seções essenciais do 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 essenciais

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

Regras de arquitetura

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

Changelog

Data Alterações
2026-04-28 Atualizou a recomendação de Xcode para 26.4+ em workflows com agentes (26.4.1, 2026-04-16, build 17E202 é a versão estável mais recente, apenas com correções de bugs). Citou recursos do Xcode 26.4 (2026-03-24, build 17E192) úteis para testes escritos por agentes e localização: anexos de imagem no Swift Testing, severidade em Issue.record, avisos de crash em testes de UI com crashlogs anexados (especificamente para apps XCUIApplication(bundleIdentifier:) / XCUIApplication(url:)), melhorias no editor de String Catalog. Adicionou o instalador automático xcodebuildmcp init (v2.1.0+, 2026-02-23) como alternativa ao setup manual do MCP.
2026-04-27 App Store Connect: submissões com Xcode 26+ obrigatórias a partir de 2026-04-28. Foundation Models ganhou as APIs SystemLanguageModel.contextSize e tokenCount(for:) (back-deployed para iOS 26.4) — adicionou um padrão para código de orçamento de prompt de FM gerado por agentes. iOS 26.4.2 (22 de abril) e iOS 26.5 beta 3 (20 de abril) foram lançados sem mudanças que afetem o toolchain de agentes.
2026-04-13 Publicação inicial. 8 apps, 3 runtimes, setup de MCP, padrões CLAUDE.md, hooks, estudos de caso.

Referências


  1. XcodeBuildMCP inclui telemetria do Sentry por padrão. A documentação de privacidade do projeto detalha o que é enviado: mensagens de erro, stack traces e, em alguns casos, caminhos de arquivos. A variável de ambiente XCODEBUILDMCP_SENTRY_DISABLED=true desativa isso completamente. 

  2. Anthropic, “Model Context Protocol Specification,” modelcontextprotocol.io/specification. A especificação MCP define o transporte JSON-RPC, a descoberta de ferramentas e o protocolo de recursos que tanto XcodeBuildMCP quanto o Xcode MCP da Apple implementam. 

  3. XcodeBuildMCP, github.com/getsentry/XcodeBuildMCP. Código aberto, mantido pela Sentry. 59 ferramentas para fluxos de trabalho de simulador, dispositivo, depuração e automação de UI. Versionamento semântico com changelogs. 

  4. A Apple introduziu o servidor Xcode MCP como parte da iniciativa de ferramentas inteligentes de desenvolvimento do Xcode 26.3, posicionando MCP como a camada de interface entre assistentes de programação com IA e a toolchain do Xcode. Consulte as Xcode Release Notes para a documentação oficial. 

  5. Rudrank Riyam, “Exploring Xcode Using MCP Tools,” rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients, 2026. Confirmação independente da contagem de ferramentas MCP da Apple, da dependência de XPC e dos recursos de busca na documentação. 

  6. Jimenez, C.E., Yang, J., Wettig, A., et al., “SWE-bench: Can Language Models Resolve Real-World GitHub Issues?” ICLR 2024. arxiv.org/abs/2310.06770. Agentes com acesso estruturado a ferramentas tiveram desempenho significativamente melhor do que agentes limitados a comandos de shell não estruturados. O resultado valida interfaces MCP estruturadas para a eficácia de agentes. 

  7. Documentação do Claude Code CLI, code.claude.com. Sistema de hooks, configuração de MCP, delegação para subagentes e definições de agentes. 

  8. SwiftFormat, github.com/nicklockwood/SwiftFormat. A ferramenta de formatação Swift usada em hooks PostToolUse para manter um estilo de código consistente. 

  9. Site oficial do XcodeBuildMCP, xcodebuildmcp.com. Confirma 59 ferramentas MCP por meio de um exemplo de saída CLI. Categorias de ferramentas: simulador, dispositivo, depuração e automação de UI. Instalação via Homebrew ou npx. 

  10. Swiftjective-C, “Agentic Coding in Xcode 26.3 with Claude Code and Codex,” swiftjectivec.com, fevereiro de 2026. Confirma que o Xcode 26.3 vem com suporte nativo ao Claude Agent e ao runtime do Codex via Settings > Intelligence. 20 ferramentas MCP expostas via xcrun mcpbridge

  11. Blake Crosley, “Two MCP Servers Made Claude Code an iOS Build System,” blakecrosley.com/blog/xcode-mcp-claude-code, fevereiro de 2026. Passo a passo de configuração e resultados reais do fluxo de desenvolvimento iOS do mesmo autor. 

  12. Apple Developer News, “Upcoming Requirements”. Entrada de 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 não está no conjunto de plataformas listado nesse requisito. 

  13. Apple, “Xcode 26.4 Release Notes”. Xcode 26.4 (2026-03-24, build 17E192). Recursos citados das notas de versão: Swift Testing agora oferece suporte a anexos de imagem via CGImage, NSImage, UIImage e CIImage; Issue.record aceita níveis de severidade; algumas falhas de apps em testes de UI — especificamente apps com interação por meio de XCUIApplication(bundleIdentifier:) ou XCUIApplication(url:) — são relatadas como avisos com crashlogs anexados, em vez de falharem o teste; o editor String Catalog adiciona recortar/copiar/colar entradas, remoção de idiomas e pré-preenchimento de traduções a partir de um idioma existente, além da configuração BUILD_ONLY_KNOWN_LOCALIZATIONS

  14. Apple Developer News, “Xcode 26.4.1 (Build 17E202) Now Available”, 2026-04-16. Versão pontual apenas com correções de bugs — corrige uma falha do MetricKit causada por símbolos ausentes em iOS / macOS / visionOS anteriores à versão 26.4 e um bug de alocação de stack em Swift async (“freed pointer was not the last allocation” em swift_asyncLet_finish). 

  15. getsentry/XcodeBuildMCP release v2.1.0, 2026-02-23. Adicionou o comando CLI xcodebuildmcp init para instalar skills de agente + configuração MCP em uma única etapa, substituindo o script independente install-skill.sh. Detecta automaticamente Claude Code, Cursor e Codex; oferece suporte a --print (gravar configuração em stdout para clientes sem suporte) e --uninstall (remover). 

  16. InfoQ, “Apple Adds Context Window Management to Foundation Models”, março de 2026. Documenta as novas APIs SystemLanguageModel.contextSize e tokenCount(for:) e confirma as anotações @backDeployed(before: iOS 26.4). Substitui a suposição anterior da comunidade de um hardcode de 4096 tokens. 

  17. Contagens de arquivos derivadas de find . -name '*.swift' -not -path '*/Tests/*' | wc -l, executado em cada um dos oito repositórios privados de apps em 2026-04-27. Arquivos de teste excluídos. O total é internamente consistente com a tabela de detalhamento por app em §The Portfolio. 

  18. Estimativa subjetiva de tempo corrido, não uma medição contra um grupo de controle. O número de 3 a 5x é a lembrança do autor ao comparar o tempo para entregar funcionalidades assistidas por agentes em 2026 com funcionalidades solo equivalentes lançadas nas mesmas codebases antes do fluxo com agentes. Trate isso como uma heurística do que esperar após a configuração de MCP + hooks, não como um benchmark. 

NORMAL ios-agent-development.md EOF