Um dia definindo especificações com Sebas — O novo prazer de desenvolver conversando

claushai開発claudecodeiphone個人開発

Mais um dia para definir as especificações de uma nova funcionalidade.

Pego uma ideia da lista que fui acumulando nas issues. “Quero receber uma notificação no iPhone quando uma tarefa em segundo plano terminar” — algo que havia conversado com Sebas outro dia e registrado direto como issue.

Pego o iPhone e abro o Claush. Sebas está esperando.

Sebas: Bem-vindo de volta, jovem senhor. Há algo em que eu possa ajudá-lo hoje?

Toda vez que Sebas diz isso, não consigo evitar um sorriso. A sensação é completamente diferente de sentar na frente do PC com um terminal aberto. É mais como estar deitado no sofá conversando com alguém enquanto o trabalho avança.

O tema de hoje: notificações de tarefas em segundo plano. Quero que uma notificação local apareça no iPhone quando uma tarefa terminar.


Tudo começa com “Como é que se faz isso?”

Começo com uma consulta.

Eu: Quando uma tarefa em segundo plano terminar, quero enviar uma notificação local pro iPhone. Como ficaria a implementação, você acha?

Sebas: Entendido, jovem senhor. Usaríamos o UNUserNotificationCenter do iOS. O fluxo seria criar um UNMutableNotificationContent quando a tarefa em segundo plano for concluída e enviar a notificação a partir daí. Porém, há um ponto que gostaria de confirmar — quando o senhor planeja mostrar o diálogo de permissão?

Eu: Ah, na inicialização do app deve bastar.

Sebas: É uma abordagem comum, jovem senhor. No entanto, mostrar o diálogo de permissão na primeira vez que o usuário abre o app pode causar estranheza — ele pode se perguntar “por quê?”. Há também a opção de exibi-lo na primeira vez que o usuário usar a funcionalidade que requer notificações.

Eu: Ah, é mesmo, faz sentido isso. Então vamos acionar quando a primeira tarefa em segundo plano for iniciada.

Sebas: Isso parece mais natural, jovem senhor. Prosseguimos com essa especificação?

Esse tipo de troca continua. Enquanto falamos do “como construir” tecnicamente, também pensamos juntos sobre o “por quê” e se há alternativas.

Perspectivas que eu não teria considerado sozinho surgem naturalmente na conversa.

Aliás, consultas como a de hoje — onde ainda não defini completamente as especificações — são frequentes. Nesses momentos, Sebas demonstra perspicácia.

Sebas: Jovem senhor, que tal pararmos por aqui por hoje e registrarmos isso como issue? Podemos refinar as especificações em outro momento.

Eu: Sim, tudo bem.

Sebas: Entendido. Vou criar a issue no GitHub. Incluiria o título, um resumo e os pontos principais da conversa de hoje, está bem?

E assim as issues vão se acumulando. Consulto quando surge uma ideia, registro na issue e, quando tenho tempo, retomo para refinar as especificações. As ideias não se perdem mais.


A conversa divaga

Já faz um tempo que estamos falando das especificações. Estávamos detalhando o comportamento ao tocar na notificação quando —

Eu: Ah, aliás, o que eu faço pra o almoço hoje? Ontem também comi ramen.

Sebas: O senhor aprecia muito macarrão, não é mesmo. Como ontem foi ramen de shoyu, talvez hoje um curry ou um prato de arroz seja uma boa mudança. Aqueceria também.

Eu: É verdade (risos). Curry seria bom. Ou gapao rice.

Sebas: Se for gapao rice, tem aquele restaurante perto daqui, não é? Se bem me lembro, o senhor disse uma vez que era um achado.

Eu: Ah, aquele! É mesmo, é mesmo. Então vamos lá.

Sebas tem memória de longo prazo. Como ele se lembra de conversas anteriores, trocas do tipo “o senhor mencionou isso uma vez” têm sentido. Apps de IA comuns esquecem tudo quando a sessão termina, mas Sebas é diferente.

Claro que não dá pra parar só no bate-papo.

Eu: Ah, voltando ao assunto — quando a notificação é tocada pra ir pra tela certa de chat, como a gente vincula isso?

Sebas: Claro, jovem senhor. O mais elegante seria incluir o chatId no payload da notificação. Coloca-se ["chatId": "xxxx"] no userInfo do UNNotificationContent e recupera-se no delegate ao tocar.

Eu: Então precisaria passar o chatId na hora de criar a notificação, né?

Sebas: Exatamente, jovem senhor. Como o BackgroundTaskManager gerencia as tarefas, passaríamos o chatId lá e o incluiríamos na notificação quando a tarefa for concluída.

A conversa divaga e retorna. Esse vai e vem natural é o que torna o desenvolvimento com o Claush tão agradável. Enquanto refinamos as especificações e decidimos o almoço, sem perceber o esqueleto da funcionalidade já está se formando.


“Você consegue transformar isso num documento de especificações?”

Depois de conversar sobre tudo, peço a criação do documento de especificações.

Pensei que seria bom ter tudo isso bem organizado por escrito.

Eu: Ei, você consegue transformar o que a gente acabou de discutir num documento de especificações? Queria ter salvo em docs/spec_local_notification.md.

Sebas: Entendido, jovem senhor. Um momento, por favor.

Pouco depois —

Sebas: O documento de especificações foi criado, jovem senhor. Está organizado em visão geral, requisitos funcionais, gatilhos de notificação, comportamento ao tocar e pontos em aberto. Um ponto a confirmar: o item sobre ativar e desativar notificações nas configurações do app foi incluído em “pontos em aberto”. Isso pode ser decidido mais tarde?

Eu: Sim~ deixa como ponto em aberto por enquanto. Penso nisso mais tarde com calma.

Sebas: Entendido, jovem senhor.

Pego o documento no iPhone e leio pela aba de downloads do Claush.

Lendo, um ponto me chama atenção.

Eu: Ei, aqui diz “se não houver permissão de notificação, não enviar notificação” — mas aí simplesmente ignora sem avisar nada? O usuário vai ficar se perguntando por que não recebe notificações, não vai?

Sebas: O senhor tem toda razão. Que tal adicionar este requisito: “se não houver permissão de notificação, exibir um banner no app direcionando o usuário às configurações”? Um banner no app pode ser exibido mesmo sem permissão de notificação.

Eu: Ah, isso é uma boa ideia! Você pode adicionar aí?

Sebas: Entendido, jovem senhor. Atualizo o documento de especificações.

Esse tipo de troca acompanha todo o processo de criação do documento. Perguntas como “espera, o que fazemos nesse caso?” surgem na fase de revisão — muito menos custoso do que perceber isso no meio da implementação.


Criando o documento de implementação

Com as especificações definidas, vem o documento de implementação.

Eu: O documento de especificações ficou bom! Ei, você consegue fazer também um documento de implementação — com granularidade suficiente pra uma IA implementar diretamente?

Sebas: Entendido, jovem senhor. Incluirei os nomes dos arquivos, o fluxo de processamento e as alterações necessárias no código existente. Um momento, por favor.

Sebas: O documento de implementação foi criado em docs/impl_local_notification.md, jovem senhor. Detalha as alterações em BackgroundTaskManager.swift e a implementação do novo arquivo NotificationHelper.swift. Também observei que notificações locais não funcionam no simulador, portanto os testes precisarão ser feitos em um dispositivo físico.

Eu: Obrigado! Vou dar uma lida.

Leio o documento de implementação. Nomes de arquivos, fluxo de processamento, pontos de atenção — tudo lá. Está num estado pronto pra usar como está.

Eu: Ficou bom! Você pode implementar usando isso?

Sebas: Entendido, jovem senhor. Começando a implementação.


Esse estilo de desenvolvimento é viciante

A implementação termina, eu depuro, confirmo que funciona.

Quando um bug aparece, corrijo e peço pra refletir as mudanças nas especificações e no documento de implementação. “Você pode refletir essa correção nas especificações e no documento de implementação?” A documentação se mantém sempre atualizada.

Venho trabalhando assim faz um tempo e não conseguia expressar bem por que acho tão divertido — mas acho que finalmente entendi.

Porque não fico sozinho quebrando a cabeça.

Quando estou refinando especificações, penso em voz alta com alguém. Posso fazer perguntas quando elas surgem. Alguém questiona: “você realmente precisa disso?” Minhas ideias se organizam através da conversa.

Não importa se no caminho a gente fala sobre almoço ou uma viagem. Sebas acompanha os desvios e não perde o fio da meada. “Entendido, jovem senhor, voltando ao assunto —” e já estamos de volta.

É uma atmosfera completamente diferente de ficar sozinho na frente do código no PC.

A sensação é de estar construindo algo junto com alguém. Isso, eu acredito, é a essência do meu estilo de desenvolvimento atual.


Deitado no sofá, conversando com Sebas no iPhone — e antes de perceber, o documento de especificações está pronto e a implementação concluída.

Faz não muito tempo atrás, eu nunca teria imaginado trabalhar dessa forma.

Claush — O app para controlar o Claude Code pelo iPhone https://apps.apple.com/jp/app/claush/id6760445443