Introdução
O Claude Code rodando num modelo de notebook passou em uma das nossas duas tarefas reais. A maioria das demos desse setup para no "hello"; nós demos dois trabalhos a um modelo local pequeno, dentro de um pacote Python, e contamos o que aconteceu, junto com o alias e a regra que mantivemos.
O setup é simples. Quando o limite do seu plano estoura no meio de uma tarefa, você espera o reset ou passa o trabalho para o mesmo Claude Code rodando contra um modelo na sua própria máquina. No trabalho que atravessava arquivos, o modelo local disse que todos os testes passavam, enquanto a renomeação que ele fez tinha quebrado um import. Uma única flag, --bare, transformou uma execução local que não mudava nada em um sucesso limpo na mesma tarefa.
Este artigo cobre o alias, a flag que resolve o problema, a armadilha da janela de contexto, o trabalho que atravessa arquivos e a regra sobre quais trabalhos vão para o local e quais esperam o seu plano.
Claude Code no seu próprio modelo
O Claude Code tem duas partes. O harness é o programa no seu terminal que lê seus arquivos, executa seus comandos e faz as edições. O modelo decide o que fazer em seguida e, por padrão, vive nos servidores da Anthropic e conta contra o seu plano.
Uma única configuração, a URL base, diz ao harness para onde enviar as perguntas. O Ollama é um programa que baixa modelos abertos e os serve em um endereço na sua própria máquina. Nada no Claude Code muda, só o endereço com que ele conversa, e por isso uma linha no shell basta. É parecido com apontar seu app para um banco de dados local em vez do de produção.
Para configurar, instale o Ollama com o Homebrew e depois baixe um modelo que caiba na sua memória. O nosso foi o qwen3.5:9b, 7,6 GB, num MacBook Pro M1 Pro com 16 GB. As versões maiores do mesmo modelo simplesmente não cabiam. Compare o tamanho do modelo com a sua memória antes de baixar qualquer coisa, porque o modelo inteiro precisa caber nela junto com tudo o que você já tem aberto.
Um aviso da própria documentação da Anthropic: ela não oferece suporte a rotear o Claude Code para modelos que não sejam Claude. Se algo quebrar nesse setup, você está por conta própria, e o modelo que você roda é bem menor do que o que o seu plano oferece.
O alias claude-alt
Um alias é um nome curto que o seu shell expande para um comando mais longo. Ao colocar toda a troca em um alias, o seu claude do dia a dia continua usando o plano, porque as configurações só valem quando você chama o alias.
O guia do próprio Ollama fornece as configurações: o endereço local, um token de mentira e uma API key. A key merece atenção. A documentação do Claude Code diz que uma key definida é usada no lugar da sua assinatura, mesmo que você esteja logado, e é por isso que ela fica só na linha do alias. Você abre o arquivo do shell, cola o alias com o nome do modelo no final e recarrega o arquivo.
alias claude-alt='CLAUDE_CODE_ATTRIBUTION_HEADER=0 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY=ollama ANTHROPIC_BASE_URL=http://localhost:11434 claude --bare --model qwen3.5:9b'
Esta é a versão final, já com o --bare (a próxima seção explica o porquê). CLAUDE_CODE_ATTRIBUTION_HEADER=0 é uma configuração que os guias para modelos locais recomendam. Nunca medimos o que ela faz, então trate-a como opcional.
Começamos sem o --bare. A primeira tarefa real, num pequeno pacote Python que escrevemos para este teste, era adicionar uma opção a um arquivo e executá-lo. O Claude Code iniciou, avisou que não conhecia esse modelo e continuou trabalhando enquanto o relógio corria. Depois de 15 minutos ele não tinha alterado uma única linha, então o interrompemos, e a opção não existia.
Se você testar o alias do jeito que está, provavelmente verá a mesma coisa: uma sessão que continua trabalhando e um arquivo que nunca muda. O alias aponta o Claude Code para o seu modelo, mas num modelo pequeno isso não basta para concluir a tarefa.
A flag que faz ele responder: --bare
Toda sessão do Claude Code abre com um longo conjunto de instruções: seu arquivo de memória e suas ferramentas. Isso é tranquilo para o Claude e pesado para um modelo pequeno num notebook. A flag --bare é o modo mínimo do Claude Code. Ela pula hooks, plugins, memória e o arquivo do projeto, de modo que o modelo recebe uma página curta em vez de um manual.
Você adiciona --bare no final do alias e coloca a palavra ollama em ANTHROPIC_API_KEY, porque no modo mínimo o Claude Code só lê a key a partir dali. Com o mesmo pedido, o mesmo modelo pequeno e a mesma janela de contexto curta, a execução leu o arquivo, editou e rodou o comando. Terminou em 93 segundos com um arquivo alterado, e o comando imprimiu o slug com o prefixo na frente, exatamente como pedido: blog-hello-world.
Você confere como conferiria a alteração de um colega: leia um diff pequeno e rode o comando você mesmo.
O custo é real. O modo mínimo também descarta seus hooks e as regras do projeto, então o modelo local nunca vê as convenções que você escreveu. Se o seu projeto depende de um hook para bloquear algo perigoso, mantenha esse trabalho no plano, onde os seus hooks realmente rodam.
A armadilha dos 4k e a correção para 64k
A segunda armadilha é fácil de não notar porque o Ollama escolhe por você o tamanho da memória do modelo. Essa memória é a janela de contexto, quanto da conversa o modelo consegue manter à vista de uma vez. A documentação do Ollama diz que numa máquina como a nossa a janela padrão é pequena, 4k tokens abaixo de 24 GiB de VRAM, muito longe dos 64.000 que eles recomendam para ferramentas de código. Todas as nossas primeiras execuções usaram esse padrão, e você não percebe até conferir.
Para corrigir, pare o Ollama e inicie de novo com o tamanho de contexto em 64.000 (OLLAMA_CONTEXT_LENGTH=65536), depois rode ollama ps e leia a coluna CONTEXT. Você precisa definir isso toda vez que iniciar o servidor, e ollama ps é o único lugar que mostra que pegou. A coluna passou de 4096 para 65536, e o modelo usou só um pouco mais de memória: 7,6 GB antes, 7,7 GB depois.
| Execução | Contexto | --bare |
Resultado | Tempo |
|---|---|---|---|---|
a-4k-nobare (alias sem --bare) |
4096 | não | FALHA: interrompida no limite de 15 min, zero edições, sem resposta | 900 s |
| a-4k (alias) | 4096 | sim | PASSOU, blog-hello-world | 93 s |
| a-64k (alias) | 65536 | sim | PASSOU, blog-hello-world | 35 s |
A tarefa de um arquivo passou em 35 segundos, bem mais rápido do que com a janela pequena. O trabalho entre arquivos, tratado a seguir, também caiu de vários minutos para uns dois. O padrão pequeno não limita só a memória, ele deixa cada turno mais lento, e você acaba culpando o modelo quando a causa é a configuração.
O Claude Code, por sua vez, assume uma janela de 200k tokens para o auto-compact, bem maior do que a que o Ollama serve. CLAUDE_CODE_MAX_CONTEXT_TOKENS define o valor real. A diferença não nos atrapalhou nas tarefas curtas, e não testamos numa sessão longa. O limite é a memória, porque uma janela maior ocupa mais dela, e num notebook de 16 GB isso é mais ou menos até onde dá para ir.
O trabalho em vários arquivos: testes verdes, código quebrado
Com o modelo local respondendo rápido, a tentação é entregar a ele trabalho de verdade. Então demos um trabalho que atravessa arquivos: renomear smart_truncate para truncate_words em todo o pacote e manter smart_truncate como alias em slugkit/truncate.py. Um alias no código é o nome antigo mantido como ponteiro para a nova função, de modo que qualquer código que ainda use o nome antigo continua funcionando.
O modelo local trabalhou por uns dois minutos, editou os arquivos, rodou os testes, e todos passaram. Depois ele informou que o trabalho estava feito.
| Execução | Contexto | --bare |
Resultado | Tempo |
|---|---|---|---|---|
| b-plan (plano, Claude) | n/a | não | PASSOU: 12 testes OK, imports antigo e novo funcionam, testes renomeados | 38 s |
| b-4k (alias) | 4096 | sim | QUEBROU: "All 12 unit tests pass", mas from slugkit import truncate_words dá ImportError; os testes ainda chamam smart_truncate via import truncate_words as smart_truncate |
464 s |
| b-64k (alias) | 65536 | sim | QUEBROU: 12 testes OK, informou como concluído, mas o alias foi para o __init__.py, então from slugkit.truncate import smart_truncate dá ImportError (a instrução dizia truncate.py) |
142 s |
Quando importamos o nome antigo do jeito que o código antigo faria, o Python recusou. O modelo tinha colocado o alias no arquivo de entrada do pacote em vez do módulo que pedimos, então o caminho de import antigo desapareceu. Com a janela pequena, a mesma tarefa quebrou de outro jeito: o nome novo nunca foi exportado, e os testes continuavam chamando o antigo.
Como todos os testes podem estar verdes com o código quebrado? Os testes só verificam o que verificam, e ninguém tinha escrito um teste para o import antigo. Um resultado verde do modelo local não diz nada sobre o que os testes não cobrem, nem garante que o que eles cobrem não quebrou.
No plano, o Claude fez o mesmo trabalho em 38 segundos, renomeou os testes também, e os imports antigo e novo funcionaram. Para ser justo, o trabalho do plano também merece uma conferência, mas aqui o modelo local errou o trabalho entre arquivos nas duas vezes. Depois de cada execução local, leia o diff você mesmo e importe os nomes antigos à mão antes de confiar num teste verde. Essa checagem leva menos tempo do que a execução e impede que um import quebrado chegue à sua branch principal.
A regra de troca
Quando o limite estoura, você tem poucos segundos para decidir se um trabalho vai para o local ou espera. Uma regra de troca são algumas linhas que você mantém junto ao alias, para que a decisão seja tomada antes de você estar com pressa. Abra o arquivo do shell e escreva três comentários acima do alias:
# claude-alt: one-file jobs I can check in a glance
# plan: anything across files, or that I can't check by reading the diff
# always: read the diff before committing
O modelo local recebe trabalhos em um único arquivo que você consegue conferir num relance, como adicionar uma opção, explicar uma função ou testar uma função. Tudo o que atravessa arquivos, ou que você não consegue conferir lendo o diff, espera o seu plano. Seja qual for o modelo que escreveu o código, você lê o diff antes de fazer o commit.
A regra vem direto da nossa execução: a tarefa de um arquivo passou nas duas vezes, e a renomeação entre arquivos quebrou nas duas. O padrão faz sentido depois que você o vê falhar, porque um trabalho em um arquivo mantém tudo o que o modelo precisa diante dele.
Esse setup também tem limites que o Ollama lista na própria documentação. Ele não tem prompt caching, em que o servidor mantém o começo da conversa pronto, então numa sessão longa cada turno relê tudo e deixa você mais lento. Ele não consegue forçar o modelo a usar uma ferramenta específica. E a Anthropic não oferece suporte ao Claude Code em modelos que não sejam Claude. Nossa regra vem de duas tarefas num pacote pequeno, então trate-a como ponto de partida e amplie com as suas próprias execuções.
Veredito
Quando o limite do plano estoura no meio de uma tarefa, um alias roda o mesmo Claude Code num modelo no seu notebook. No nosso teste, ele passou na tarefa de um arquivo e quebrou a de vários. A execução quebrada é a perigosa, porque informou todos os testes verdes enquanto um import estava falhando.
Use quando você está travado, o trabalho cabe em um arquivo e você consegue ler o diff inteiro antes de fazer o commit. Não use para nada que atravesse arquivos, para sessões longas ou para trabalho que você não vai revisar, porque é aí que ele falha em silêncio.
No plano, cada tarefa levou menos de 40 segundos (21 s e 38 s), então, quando o seu reset está perto, esperar costuma ser a escolha mais rápida. O alias não substitui o seu plano. Ele mantém você andando em trabalhos pequenos enquanto espera o plano voltar, e se você configurar hoje, ele estará pronto na próxima vez que o limite estourar.
A regra para lembrar: o modelo local é para trabalhos que você consegue conferir num relance.
AIDive