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

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.mdno projeto (esse aqui você monta já dentro do Claude Code, é o primeiro item da lista que precisa do terminal aberto)
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
diffde 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.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
Bateu o limite de uso do Claude Code? Como retomar a tarefa sem refazer tudo
Bateu o limite de uso do Claude Code? Veja como retomar a tarefa de onde parou com /usage, CLAUDE.md e --continue, sem refazer nada.
Como pagar o Claude Code no Brasil: cartão, dólar, IOF e quanto fica em reais
Claude Code preço Brasil na prática: câmbio, IOF de 3,5% e quanto fica na fatura. Planos Pro e Max convertidos em reais e como pagar com cartão.
Como instalar uma skill no Claude Code: passo a passo
Saiba como instalar skill no Claude Code: use a pasta pessoal para todas as sessões ou a pasta de projeto para versionar. Frontmatter YAML é obrigatório.
