Como pedir ao Claude Code para converter um script de uma linguagem para outra sem mudar o comportamento

conversão de script de uma linguagem para outra com Claude Code mantendo o mesmo comportamento
Resposta rápida

Converter script com Claude Code sem mudar o comportamento é questão de método, não de sorte: você congela a saída esperada do script original antes de qualquer edição, mapeia o comportamento no modo plano (que pesquisa e propõe sem editar o código-fonte), escreve as regras invioláveis no CLAUDE.md (lido no início de toda sessão), converte em fatias pequenas e compara o antigo com o novo a cada fatia. Se algo sair torto, o /rewind (ou Esc Esc com o campo vazio) volta código, conversa ou os dois. O resto é repetir até a última função 🙂

Fala aí, beleza? Script convertido que roda não é script convertido que funciona igual

O perigo de uma migração de linguagem quase nunca é o erro vermelho na tela

É o silêncio: o script novo executa, não reclama de nada, e devolve um código de saída diferente do antigo num caso de borda que só vai aparecer às 3 da manhã, no meio de um pipeline

Shell pra Python, JavaScript pra TypeScript, tanto faz o par de linguagens: o risco é sempre o mesmo

Aqui a gente vai pelo caminho chato e seguro de converter script com Claude Code: define a saída esperada ANTES, converte em fatias pequenas e compara os dois lados a cada fatia

Bora ver na prática?

O que você precisa antes de começar a conversão

Antes de começar a conversão, se liga no checklist:

  • o script original rodando de verdade, e versionado em git (commit a cada fatia validada é o teu ponto de retorno fora da sessão)
  • um conjunto de entradas de exemplo que cubra o caminho feliz E os casos chatos (argumento faltando, arquivo inexistente, entrada vazia)
  • o runtime da linguagem de destino instalado e funcionando
  • um CLAUDE.md no projeto (esse aqui você monta já dentro do Claude Code, é o primeiro item da lista que precisa do terminal aberto)
Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 45min

Com o Claude Code aberto no projeto, o comando /init gera um CLAUDE.md inicial analisando o codebase (comandos de build, instruções de teste, convenções)

E se já existir um CLAUDE.md ali, o /init sugere melhorias em vez de sobrescrever o que você escreveu

Por que isso importa tanto numa migração? Porque arquivos CLAUDE.md guardam instruções persistentes de projeto e são lidos no início de toda sessão

Ou seja: a regra "não mude o código de saída" continua valendo amanhã, depois do /clear, depois de você fechar o notebook e voltar na segunda 😀

Passo a passo: convertendo o script sem mudar o comportamento

Sete passos, na ordem. Pode colar os prompts, eles são só o esqueleto, adapte pro seu script

1. Congele a saída esperada antes de tocar no código

Primeiro roda o script ORIGINAL nas entradas de exemplo e salva tudo: saída padrão, saída de erro e código de saída

mkdir -p ref
for caso in casos/*.txt; do
  nome=$(basename "$caso" .txt)
  bash script.sh < "$caso" > "ref/$nome.out" 2> "ref/$nome.err"
  echo $? > "ref/$nome.exit"
done

Esses arquivos viram a tua referência, o contrato

Sem eles, "mesmo comportamento" é opinião, e opinião não passa em code review

É o mesmo raciocínio de quando você vai pedir melhoria de performance sem métrica: sem número congelado antes, qualquer resultado parece bom

O erro comum deste passo: gerar a referência só do caminho feliz

O caso de borda é justamente onde as linguagens divergem, então ele PRECISA estar no conjunto

2. Mapeie o comportamento em modo plano, sem deixar editar

Agora sim abre o Claude Code, mas com a mão amarrada

O modo plano faz o Claude pesquisar e propor mudanças sem aplicá-las: ele lê arquivos e explora, mas não edita o código-fonte

Pra entrar nele, pressiona Shift+Tab (que cicla entre manual, accept edits, plan e auto) ou prefixa um prompt único com /plan

Prompt pronto:

/plan Leia o script.sh e descreva o comportamento observável dele:
argumentos aceitos, mensagens impressas em stdout e stderr, ordem
dessas mensagens, códigos de saída por situação e efeitos colaterais
em arquivos. Não proponha código ainda, só o mapa do comportamento.

O que você quer aqui é o MAPA, não a tradução

O erro comum deste passo: já pedir a conversão junto com o mapeamento

O Claude entrega um arquivo inteiro convertido, bonito, e você perde a chance de discordar do entendimento dele antes de virar código

3. Escreva as regras invioláveis da migração no CLAUDE.md

Aquele mapa do passo 2 vira regra escrita

## Regras da migração de script.sh para script.py

- A saída em stdout deve ser byte a byte igual à referência em ref/
- Os códigos de saída devem ser idênticos aos do original
- As mensagens de erro mantêm o mesmo texto e a mesma ordem
- Nada de "melhorar" mensagem, renomear flag ou trocar formato de log
- Refatoração e conversão são tarefas separadas: aqui só convertemos

Como o CLAUDE.md é lido no início de cada sessão, essas regras sobrevivem à conversa

O erro comum deste passo: escrever regra vaga tipo "manter o comportamento"

Comportamento é abstrato, código de saída é concreto. Seja chato na escrita

4. Converta em fatias pequenas, nunca o arquivo inteiro

Uma função por prompt. Um bloco por prompt

Converta APENAS a função parse_args do script.sh para Python, seguindo
as regras da migração no CLAUDE.md. Mantenha os nomes das mensagens e
o código de saída. Não toque no resto do arquivo.

O motivo é bem prático: quando a comparação falha numa fatia de 20 linhas, você sabe onde procurar

Quando falha num arquivo de 400 linhas convertido de uma vez, você vai debugar tradução, e debugar tradução é pior que escrever do zero

O erro comum deste passo: aceitar as "melhorias de brinde"

O modelo adora arrumar uma mensagem feia ou trocar um echo por um log estruturado no meio do caminho, e aí o comportamento mudou

5. Compare os dois lados a cada fatia

A cada fatia convertida, roda os dois e compara contra a referência

for caso in casos/*.txt; do
  nome=$(basename "$caso" .txt)
  python script.py < "$caso" > "novo.out" 2> "novo.err"
  echo $? > "novo.exit"
  diff "ref/$nome.out" novo.out || echo "DIVERGIU stdout: $nome"
  diff "ref/$nome.exit" novo.exit || echo "DIVERGIU exit: $nome"
done

Diferença encontrada agora custa um prompt

Diferença encontrada em produção custa a tua tarde

O erro comum deste passo: comparar só o stdout

Código de saída e stderr fazem parte do contrato, principalmente se o script vive dentro de um cron ou de um CI

6. Automatize a comparação com um hook PostToolUse

Dá pra deixar a comparação rodando sozinha sempre que o Claude mexer em arquivo

Hooks são configurados pelo comando /hooks ou pelo arquivo settings.json

Você escolhe o evento PostToolUse com o matcher "Edit|MultiEdit|Write", que dispara sempre que o Claude modifica um arquivo, e aponta pro teu script de comparação

Só que tem uma pegadinha importante: o PostToolUse dispara DEPOIS que a ferramenta já executou

Por isso hooks PostToolUse não conseguem desfazer a ação

O erro comum deste passo: tratar o hook como guarda-costas

Ele é alarme, não é cadeado: avisa que divergiu, mas a edição já está no arquivo

7. Quando sair errado, volte pelo rewind

O checkpointing do Claude Code captura automaticamente o estado do código antes de cada prompt do usuário

E ele guarda snapshots de arquivos dos 100 checkpoints mais recentes de uma sessão, ou seja: é rede de segurança DENTRO da sessão, não substituto do commit

Pra usar isso, abre o menu de rewind com /rewind ou pressionando Esc duas vezes com o campo de prompt vazio

Lá dentro você escolhe entre restaurar código e conversa, restaurar só a conversa, restaurar só o código, resumir a partir daquele ponto ou resumir até aquele ponto

Na conversão, o mais útil costuma ser restaurar só o código: você mantém o fio da conversa (o Claude continua sabendo o que já foi mapeado) e joga fora a tradução ruim

O erro comum deste passo: insistir em consertar por cima

Tradução torta em cima de tradução torta vira frankenstein. Volta e refaz a fatia

Dois casos comuns: shell para Python e JavaScript para TypeScript

Shell para Python: onde o comportamento escorrega

Shell e Python discordam em coisas silenciosas

Os três suspeitos de sempre:

  • código de saída: no shell ele vem de graça do último comando, em Python você precisa dizer explicitamente qual é
  • ordem das mensagens: stdout e stderr podem sair em ordem diferente dependendo de buffer, e o teu diff de referência pega isso na hora
  • expansão de argumentos: aspas, glob e variável vazia se comportam de um jeito no shell e de outro depois de traduzidos

A boa notícia é que nada disso é surpresa se o passo 1 foi bem feito: os exemplos de referência já cobrem esses casos, e a divergência aparece na fatia, não no deploy

JavaScript para TypeScript: aperte o parafuso aos poucos

Aqui o pulo do gato é usar as flags do compilador como degraus, em vez de ligar tudo no primeiro dia

Flag O que ela faz Quando ligar
allowJs permite importar arquivos JavaScript no projeto além de .ts e .tsx logo no começo, pra conviver com o código antigo
checkJs funciona junto com allowJs e reporta erros dentro dos arquivos JavaScript, equivalente a // @ts-check no topo de todos eles depois, pra enxergar o estrago sem converter nada ainda
noImplicitAny erro sempre que o TypeScript inferiria o tipo any quando a maior parte já virou .ts
strict liga todas as opções da família de modo estrito de uma vez por último, quando o resto estiver verde

Deixar strict pro fim é proposital: ligar ele no começo é abrir uma enxurrada de erros de uma vez e transformar migração em faxina

E faxina e conversão juntas é a receita pra ninguém mais saber o que mudou o comportamento 🙂

Quando o script é grande: subagentes, worktrees e contexto

Script grande não cabe numa sessão só, e é aí que o método costuma desandar

Subagente de verificação. Subagentes do Claude Code são arquivos markdown em .claude/agents/, com frontmatter YAML contendo name, description e campos opcionais de modelo e de acesso a ferramentas

---
name: verificador-de-saida
description: Roda o script original e o convertido nas entradas de
  referencia e relata apenas as divergencias encontradas
---

Execute a comparacao entre a referencia em ref/ e a saida atual.
Relate apenas divergencias: caso, campo (stdout, stderr ou exit) e
a diferenca exata. Nao proponha correcoes.

Cada subagente roda em uma janela de contexto própria e só a mensagem final volta pra sessão principal

Na prática isso é ouro numa conversão longa: o barulho da comparação fica lá dentro, e a sessão principal recebe só o veredito

Worktree pra não pisar no próprio pé. O Claude Code permite rodar sessões paralelas isoladas em git worktrees, pelo CLI com claude --worktree (ou claude --worktree nome)

A recomendação é adicionar .claude/worktrees/ ao .gitignore, e um arquivo .worktreeinclude leva arquivos ignorados pelo git (como o .env) pra cada novo worktree

Gestão de contexto. Três comandos resolvem quase tudo: /context mostra o tamanho e a composição do contexto atual, /compact compacta a conversa mantendo um resumo, e /clear apaga tudo e começa do zero

Minha régua mental: /compact quando as fatias seguem dependentes entre si, /clear quando a próxima fatia é independente de verdade

E pra fechar, a flag -p (ou --print) faz qualquer comando claude rodar de forma não interativa, o famoso modo headless, útil pra scripts e batch

Dá pra pendurar a comparação de saídas num script do CI e nunca mais depender de você lembrar de rodar

Erros que aparecem na conversão (e como prevenir)

O Esc Esc não abriu o menu de rewind

Causa: havia texto no campo de prompt, e nesse caso o Esc duplo limpa o texto em vez de abrir o menu

Prevenção: esvazia o input antes, ou usa direto o /rewind e para de sofrer

O checkpoint que você queria não está mais lá

Causa: o Claude Code guarda snapshots de arquivos dos 100 checkpoints mais recentes de uma sessão

Numa conversão de fatia em fatia, com prompt curto, você chega nesse número mais rápido do que imagina

Prevenção: commit em git a cada fatia validada, com mensagem dizendo qual função foi convertida

É a mesma disciplina de atualizar dependência sem quebrar o projeto: passo pequeno, commit, próximo passo

O hook rodou, avisou, e a edição errada continuou aplicada

Causa: o PostToolUse dispara depois que a ferramenta já executou, então ele não desfaz nada

Prevenção: hook como alarme, /rewind ou git como desfazer. Cada um no seu quadrado

O Claude editou antes de você aprovar o plano

Causa: a sessão estava em um modo que aceita edição quando você descreveu a migração inteira

Prevenção: entra em modo plano ANTES de descrever a migração, com Shift+Tab ou com o prefixo /plan

Descrever a tarefa fora do plano é praticamente autorizar o primeiro rascunho a virar código

Conclusão

Preservar comportamento não é sorte nem prompt mágico, é método

Referência congelada antes de qualquer edição, mapa do comportamento em modo plano, regras escritas no CLAUDE.md, fatias pequenas, comparação a cada fatia e /rewind na mão quando der ruim

Se você fizer só isso, a conversão deixa de ser aposta e vira processo chato, que é exatamente o que a gente quer numa migração

Próximo passo pra hoje: escolhe o script mais CURTO que você tem, roda o /init pra ter o CLAUDE.md, gera os arquivos de entrada e saída de referência e converte a primeira função

Uma função só. Compara. Sente o método funcionando

Depois disso, o script grande vira só repetição…

até o próximo post! 😀

Perguntas frequentes

Como desfazer uma conversão de script que o Claude Code aplicou errada?

O checkpointing tira um snapshot automático do código antes de cada prompt seu, então dá pra voltar atrás. Abre o menu com /rewind ou apertando Esc duas vezes com o campo de prompt vazio (se tiver texto digitado, o Esc duplo só limpa o texto). Dá pra escolher restaurar código e conversa, só a conversa, só o código, resumir a partir daquele ponto ou resumir até aquele ponto. Como o Claude Code guarda snapshots dos 100 checkpoints mais recentes de cada sessão, vale manter o commit em git como rede de segurança de longo prazo.

Dá pra rodar a conversão de script em lote, sem abrir a interface interativa?

Dá sim, usando a flag -p (ou –print) no comando claude, que roda em modo headless. Isso é útil pra plugar a conversão numa etapa de script maior ou de CI, sem ficar respondendo prompt na mão. Continua valendo a mesma lógica de comparar a saída contra a referência congelada no passo 1.

Vale a pena usar subagentes pra revisar a conversão do script?

Sim, principalmente pra não poluir o contexto da sessão principal com uma revisão longa. Subagentes são arquivos .md dentro de .claude/agents/, com frontmatter YAML definindo nome e descrição, e rodam numa janela de contexto própria. Só a mensagem final deles volta pra sessão principal, então dá pra pedir uma auditoria completa da fatia convertida sem inflar o histórico da conversa.

Dá pra testar a versão convertida do script em paralelo com o script original ainda rodando?

Dá, usando sessões isoladas em git worktrees. Pelo CLI é só usar claude –worktree (ou claude –worktree nome), e o recomendado é adicionar .claude/worktrees/ ao .gitignore. Se o script depende de arquivo ignorado pelo git, como .env, um arquivo .worktreeinclude leva ele pra cada novo worktree.

Convertendo um script de JavaScript pra TypeScript, o Claude Code também confere os tipos?

A conferência de tipos depende das flags do próprio compilador TypeScript, que você pode pedir pro Claude configurar junto da conversão. allowJs permite importar arquivos .js no projeto além de .ts, e checkJs (que depende de allowJs) reporta erro dentro dos arquivos JavaScript, tipo um // @ts-check em todos eles. noImplicitAny emite erro quando o tipo seria any implícito, e strict liga toda essa família de checagem de uma vez.



Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares