Desenvolvimento iOS com o meu Mac desligado

por Marcello Gonzatto Birkan, Fundador

Desenvolver para iOS sempre teve um pré-requisito físico: o Mac ligado na minha frente. Xcode, simulador, um cabo, eu ali. Esta semana eu tirei o Mac do caminho e o ciclo continuou inteiro — escrever o Swift, compilar, instalar num iPhone, percorrer a tela, fotografar o que apareceu e abrir o PR.

Quem faz isso é uma thread do Claude Projects, que roda numa VM Linux sem Xcode e sem simulador. O que faltava, o Revyl preenche: o CLI manda o código para um runner macOS que compila o .app, e depois abre um iPhone simulado na nuvem que a própria thread controla e fotografa. Como tudo isso é uma conversa, o aparelho de onde eu escrevo deixa de importar — esta eu conduzi do desktop, mas mandar a tarefa do celular é o mesmo gesto.

O que aconteceu de verdade

Testei no Coloreku, um jogo de cores que eu estou fazendo em SwiftUI. Mandei uma tarefa e fui fazer outra coisa.

A tarefa desta vez foi uma correção, e é honesto dizer isso: o que eu já rodei de ponta a ponta é um bug, não uma feature nova. Mas nada no laço depende disso. Escrever código, compilar, instalar, percorrer a tela e voltar com prova é o mesmo trabalho, seja a mudança de uma linha ou de uma tela inteira.

O bug era de ordem: com o Modo Rápido desligado, tocar numa célula vazia já pintava a célula, quando deveria apenas selecioná-la e esperar a cor vir da paleta. O que voltou:

  • tapCell reordenado no GameViewModel, que é onde a ordem errada estava
  • 12 testes escritos para os dois modos de entrada
  • build remoto e device na nuvem executados, com o fluxo percorrido de ponta a ponta
  • duas fotos da tela, tiradas durante o teste
  • PR #4 aberto, +233 −27, checagens verdes
A thread do Coloreku no Claude Projects: à esquerda, a foto da tela do jogo tirada no iPhone da nuvem, com o tabuleiro 2×2, a célula vazia só selecionada e o contador de MOVES em 0; à direita, o relato do agente, as duas fotos anexadas, a checklist do que foi feito e o PR #4 com as checagens verdes.

As fotos são a parte que mudou o meu jeito de trabalhar. A primeira mostra o tabuleiro 2×2 com o azul escolhido na paleta e a célula vazia tocada: ela ganhou só o contorno tracejado de seleção, e o contador de MOVES continua em 0. Antes da correção aquele toque já teria pintado. A segunda mostra o toque seguinte na paleta, a cor entrando, MOVES indo para 1, e o detector marcando em vermelho os três azuis em conflito.

Uma checagem verde diz que o código rodou. A foto diz que a tela ficou do jeito que eu pedi. São afirmações diferentes, e até agora só a primeira cabia numa thread.

O que ainda não funciona

Os 12 testes ainda não rodam. O alvo ColorekuTests não tem nenhum arquivo fonte, então a pasta de testes inteira não é compilada — um problema meu, anterior a tudo isso, que o agente encontrou e me avisou em vez de fingir que não existia. O PR está aberto esperando a minha revisão; não foi mergeado.

E o cerco é mais apertado do que parece:

  • Só simulador. Câmera, sensores, push e desempenho real continuam fora do alcance.
  • Swift itera devagar. Cada mudança exige um build remoto novo. Isso serve para entregar e provar uma mudança, não para ajuste fino de interface.
  • Um device por vez no plano grátis. Se duas threads tentarem ao mesmo tempo, elas esperam ou falham, então eu limito a uma thread de verificação de cada vez.
  • A conta chega em dois lugares: os tokens das threads e os minutos de simulador, a US$ 0,15 por minuto acima da cota grátis. Um device esquecido ligado é o erro mais caro que dá para cometer aqui.
  • O Xcode do runner para na 26.5. Um app que usa o SDK do iOS 27 simplesmente não compila lá.

Vale dizer com todas as letras: nem a Anthropic nem o Revyl afirmam ter testado esse fluxo de ponta a ponta. A documentação do próprio Revyl é explícita em não garantir que uma execução completa tenha sido feita. Por isso eu validei cada peça separadamente antes de confiar um projeto a ela, e por isso este post fala de um app e um PR, não de um processo.

As três coisas que fizeram funcionar

A configuração em si é curta, e quase tudo que deu trabalho foi descobrir onde ela vazava.

O CLI precisa entrar no PATH no script de setup do ambiente, não no meio da sessão. A chave de API vai como variável de ambiente, nunca no repositório. E a rede do ambiente precisa deixar passar o backend do Revyl explicitamente — a falha aqui aparece como um comando que demora dez segundos e morre sem explicar nada.

A terceira é a que eu não teria adivinhado: o CLAUDE.md do projeto precisa de uma seção de nuvem. O do Coloreku, como o de todos os meus apps, manda usar o MCP do Xcode e cair no xcodebuild se ele não estiver disponível. Na nuvem os dois fallbacks falham, porque nenhum dos dois existe. Uma instrução escrita para o Mac vira uma armadilha silenciosa quando a sessão está em outro lugar, e a regra nova — de tirar uma a três fotos da mudança visual durante o teste que já está rodando, entregá-las na conversa e não commitar nenhuma — foi junto no mesmo PR.

O que vem agora

O próximo é o Looté, que é o caso difícil: o CLAUDE.md dele é construído inteiro em volta do MCP do Xcode, e o deployment target é iOS 26.5, exatamente no limite da imagem do runner. Se ele passar, a regra vira padrão nos meus repositórios iOS, e a próxima tarefa que eu mandar vai ser uma feature.

Se você tem um app iOS parado esperando alguém ter tempo de abrir o Xcode, me conta.

Mais artigos

O que vem por aí neste blog

Histórias de projeto, notas de engenharia e o raciocínio por trás do jeito que a gente trabalha. As primeiras estão a caminho.

Ler mais

Conte sobre o seu projeto

Onde estamos

  • São Paulo
    São Paulo, SP
    Brasil