Karpathy Skills para Claude Code 🧭
Conjunto de 4 princípios em um único CLAUDE.md para melhorar o comportamento do Claude Code em
tarefas de coding. Derivados das observações de Andrej Karpathy sobre armadilhas comuns de LLMs. Mantido por
forrestchang no GitHub como projeto open-source (MIT).
"LLMs são excepcionalmente bons em loopear até atingir metas específicas... Não diga o que fazer — dê critérios de sucesso e observe." — Andrej Karpathy
Os problemas identificados por Karpathy
"Os modelos fazem suposições erradas em seu nome e seguem em frente sem checar. Não gerenciam sua confusão, não buscam esclarecimentos, não surfaceiam inconsistências, não apresentam tradeoffs, não dão pushback quando deveriam."
"Eles gostam de complicar código e APIs, inflar abstrações, não limpar código morto... implementam uma construção inflada em 1000 linhas quando 100 seriam suficientes."
"Às vezes ainda alteram/removem comentários e código que não entendem suficientemente como efeito colateral, mesmo que ortogonais à tarefa."
Os 4 princípios
| Princípio | Problema que resolve |
|---|---|
| Think Before Coding | Suposições erradas, confusão escondida, tradeoffs não apresentados |
| Simplicity First | Supercomplexidade, abstrações infladas |
| Surgical Changes | Edições ortogonais, tocar código que não deveria |
| Goal-Driven Execution | Execução sem critério de sucesso verificável |
1. Think Before Coding
Não assuma. Não esconda confusão. Surfaceie tradeoffs.
- Enunciar suposições explicitamente — se incerto, perguntar em vez de adivinhar
- Apresentar múltiplas interpretações quando há ambiguidade — não escolher silenciosamente
- Dar pushback quando pertinente — se existe abordagem mais simples, dizer
- Parar quando confuso — nomear o que está obscuro e pedir esclarecimento
2. Simplicity First
Código mínimo que resolve o problema. Nada especulativo.
- Sem features além do que foi pedido
- Sem abstrações para código de uso único
- Sem "flexibilidade" ou "configurabilidade" não solicitada
- Sem error handling para cenários impossíveis
- Se 200 linhas podem ser 50, reescrever
Teste: um engenheiro sênior diria que está complicado demais? Se sim, simplificar.
3. Surgical Changes
Tocar apenas no necessário. Limpar apenas o próprio mess.
Ao editar código existente:
- Não "melhorar" código adjacente, comentários ou formatação
- Não refatorar coisas que não estão quebradas
- Manter o estilo existente, mesmo que você faria diferente
- Se notar código morto não relacionado: mencionar — não deletar
Quando suas mudanças criam órfãos:
- Remover imports/variáveis/funções que suas mudanças tornaram unused
- Não remover código morto pré-existente a menos que solicitado
Teste: toda linha alterada deve rastrear diretamente para o pedido do usuário.
4. Goal-Driven Execution
Definir critérios de sucesso. Loopar até verificar.
| Em vez de... | Transformar em... |
|---|---|
| "Add validation" | "Write tests for invalid inputs, then make them pass" |
| "Fix the bug" | "Write a test that reproduces it, then make it pass" |
| "Refactor X" | "Ensure tests pass before and after" |
Para tarefas multi-step, enunciar plano breve antes de executar:
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
Critérios de sucesso fortes permitem o LLM loopar independentemente. Critérios fracos ("make it work") exigem constante esclarecimento.
Instalação
Via plugin Claude Code (recomendado):
/plugin marketplace add forrestchang/andrej-karpathy-skills
/plugin install andrej-karpathy-skills@karpathy-skills
Via CLAUDE.md por projeto:
curl -o CLAUDE.md https://raw.githubusercontent.com/forrestchang/andrej-karpathy-skills/main/CLAUDE.md
Como saber que está funcionando
- Menos mudanças desnecessárias nos diffs — apenas o solicitado
- Menos rewrites por supercomplexidade — código simples na primeira vez
- Perguntas de esclarecimento vêm antes da implementação, não depois de erros
- PRs limpos e mínimos — sem "melhorias" drive-by
Nota sobre tradeoffs
Estes princípios biasam para cautela em vez de velocidade. Para tarefas triviais (typos óbvios, one-liners simples), usar julgamento — nem toda mudança precisa do rigor completo. O objetivo é reduzir erros custosos em trabalho não-trivial, não desacelerar tarefas simples.
Exemplos práticos (anti-patterns vs. correto)
Think Before Coding — suposições ocultas
Pedido: "Add a feature to export user data"
❌ LLM assume formato, caminho, campos, paginação sem perguntar — implementa 40 linhas direto.
✅ Correto: listar as suposições antes de codar:
Preciso esclarecer:
1. Escopo: todos os usuários ou subset filtrado?
2. Formato: download no browser, job em background, ou endpoint?
3. Campos: quais incluir? (alguns podem ser sensíveis)
4. Volume: quantos usuários? (afeta a abordagem)
Abordagem mais simples: endpoint paginado em JSON. Mais info para export baseado em arquivo.
Pedido: "Make the search faster"
❌ LLM escolhe silenciosamente uma interpretação e adiciona cache + async + 200 linhas.
✅ Correto: nomear as 3 interpretações com estimativas de esforço antes de pedir escolha:
- "Faster response time" → indexes + cache (2h)
- "More concurrent searches" → async + connection pooling (4h)
- "Faster perceived speed" → resultados parciais + progressive loading (3h)
Simplicity First — over-abstraction
Pedido: "Add a function to calculate discount"
❌ LLM cria DiscountStrategy ABC + PercentageDiscount + FixedDiscount
+ DiscountConfig dataclass + DiscountCalculator — 60+ linhas para um cálculo simples.
✅ Correto:
def calculate_discount(amount: float, percent: float) -> float:
"""Calculate discount amount. percent should be 0-100."""
return amount * (percent / 100)
Adicionar complexidade só quando o requisito de múltiplos tipos de desconto aparecer de fato.
Pedido: "Save user preferences to database"
❌ LLM cria PreferenceManager com cache, validator, merge flag, notify flag — features que
ninguém pediu.
✅ Correto:
def save_preferences(db, user_id: int, preferences: dict):
db.execute("UPDATE users SET preferences = ? WHERE id = ?",
(json.dumps(preferences), user_id))
Surgical Changes — drive-by refactoring
Pedido: "Fix the bug where empty emails crash the validator"
❌ LLM melhora a validação de email além do bug, adiciona validação de username que ninguém pediu, altera comentários e adiciona docstring.
✅ Correto: tocar apenas as linhas do bug de email vazio — user_data['email'] →
email = user_data.get('email', '') + checar strip(). Tudo mais permanece intocado.
Pedido: "Add logging to the upload function"
❌ LLM adiciona type hints, muda aspas simples para duplas, reformata whitespace, adiciona docstring — tudo além do logging.
✅ Correto: adicionar import logging, logger = logging.getLogger(__name__), e os
3 logger.info/error/exception — mantendo aspas simples, sem type hints, sem tocar no resto.
Teste: toda linha alterada deve rastrear diretamente para o pedido do usuário.
Goal-Driven Execution — critérios verificáveis
Pedido: "Fix the authentication system"
❌ LLM: "I'll review the code, identify issues, make improvements, test." — sem critério de sucesso.
✅ Correto: definir o critério antes de codar:
Se o problema é "usuário continua logado após trocar senha":
1. Escrever teste: trocar senha → verificar que sessão antiga é invalidada
Verificar: teste falha (reproduz o bug)
2. Implementar: invalidar sessões no password change
Verificar: teste passa
3. Checar edge cases: múltiplas sessões ativas, mudanças concorrentes
4. Verificar sem regressão: suite completa de auth ainda verde
Pedido: "Add rate limiting to the API"
❌ LLM implementa Redis + múltiplas estratégias + sistema de configuração + monitoring em 300 linhas de uma vez.
✅ Correto: 4 steps incrementais, cada um com critério de verificação próprio:
- In-memory básico em 1 endpoint → teste: 11 requests, os 10 primeiros passam, o 11º retorna 429
- Extrair para middleware → testes existentes ainda passam
- Backend Redis → rate limit persiste entre restarts
- Configuração por endpoint →
/searchpermite 10/min,/users100/min
Insight chave: critérios de sucesso fortes permitem o LLM loopar independentemente. Critérios fracos ("make it work") exigem esclarecimento constante.
| Princípio | Anti-pattern | Fix |
|---|---|---|
| Think Before Coding | Assume formato, campos e escopo silenciosamente | Listar suposições e pedir esclarecimento |
| Simplicity First | Strategy pattern para um único cálculo de desconto | Uma função — refatorar quando a complexidade for realmente necessária |
| Surgical Changes | Reformata aspas e adiciona type hints ao corrigir bug | Alterar só as linhas que corrigem o problema reportado |
| Goal-Driven | "Vou revisar e melhorar o código" | "Escrever teste para bug X → fazê-lo passar → verificar sem regressões" |
Good code is code that solves today's problem simply, not tomorrow's problem prematurely.
Baseado em forrestchang, "andrej-karpathy-skills", GitHub (MIT) — github.com/forrestchang/andrej-karpathy-skills, e observações públicas de Andrej Karpathy sobre armadilhas comuns de LLMs em coding.