A Vercel demonstrou que AGENTS.md superou as skills em suas avaliações de agentes. O AGENTS.md atingiu 100% de taxa de aprovação em conhecimento geral de framework. Skills com instruções explícitas chegaram a 79%. Em 56% dos casos, o agente tinha acesso a uma skill, mas nunca a invocou. A conclusão deles: skills funcionam para fluxos de trabalho verticais e específicos de ações, não para melhores práticas gerais.
As avaliações deles foram de tiro único (single-shot), no entanto. Um prompt, uma resposta, e pronto. Skills dependem de contexto para serem chamadas. O modelo vê um nome e uma descrição de uma linha e precisa decidir, em um único disparo a frio, se deve invocar. Em uma sessão real, há idas e vindas, o contexto se acumula e o modelo capta padrões. O tiro único penaliza as skills ao testá-las em condições que ninguém realmente utiliza.
Depois temos o Superpowers. As pessoas instalam e o Claude Code começa a seguir TDD, escrever planos antes de codificar e depurar sistematicamente. Ele agrupa as melhores práticas como skills e as pessoas juram que funciona. Se as skills deveriam perder para o AGENTS.md, por que o Superpowers funciona tão bem?
Eu executei 51 avaliações de múltiplos turnos em 4 configurações, repliquei o experimento da Vercel em sessões realistas de múltiplos turnos e li o código-fonte do Claude Code para entender a mecânica. Skills e CLAUDE.md são ambos apenas prompts. Mesmo markdown, mesmo modelo. A única diferença é se o prompt chega ao modelo. O CLAUDE.md chega todas as vezes. As skills dependem de uma cadeia de decisões que falha de 34% a 94% das vezes. E o Superpowers funciona não por causa das skills, mas porque seu hook ignora completamente o sistema de skills, aproximando-se do que o CLAUDE.md faz nativamente.
TL;DR: Skills e CLAUDE.md são ambos apenas prompt. Quando as skills são invocadas, elas funcionam tão bem quanto. O problema é que elas só são invocadas de 6% a 66% das vezes. O CLAUDE.md está sempre no contexto. Coloque diretrizes no CLAUDE.md, use skills para receitas sob demanda.
Conteúdo:
- Como as skills realmente funcionam no Claude Code
- A lacuna de ativação
- A avaliação de múltiplos turnos
- Resultados
- Por que isso acontece
- Skills são receitas, CLAUDE.md é o código sanitário
- Resultados completos turno a turno
- Metodologia
- O que fazer com isso
Como as skills realmente funcionam no Claude Code
Antes dos dados, como as skills funcionam nos bastidores. Primeiro descobri isso lendo o código do OpenCode, depois confirmei com o código vazado do Claude Code. Referencio caminhos de arquivos dessa base de código em toda esta seção. Pesquise no GitHub e você os encontrará.
Descoberta: nome e descrição
Quando o Claude Code inicia uma sessão, ele varre skills em três níveis ((src/skills/loadSkillsDir.ts):
- Managed –
/etc/claude-code/.claude/skills/(organizacional) - User –
~/.claude/skills/(suas skills pessoais) - Project –
.claude/skills/(incluído no repositório)
Para cada diretório de skill, ele lê o frontmatter do SKILL.md – name, description e campos opcionais como context, allowed-tools, arguments. O corpo completo do markdown permanece no disco.
Na inicialização da sessão, apenas o nome e a descrição chegam ao modelo. formatCommandDescription() em produz uma linha por skill: - {name}: {description}. A listagem é construída por getSkillListingAttachments() em , que formata essas linhas dentro de um orçamento de tokens (1% da janela de contexto, máximo de 250 caracteres por descrição) e as envia como uma mensagem de usuário <system-reminder>:
The following skills are available for use with the Skill tool:
- test-driven-development: Use when implementing any feature or bugfix
- systematic-debugging: Use when encountering any bug or test failure
Duas strings curtas. O modelo sabe que as skills existem, mas não as leu. Este é o gargalo. O modelo vê o que está disponível, não como aplicar. Ele precisa decidir, a partir de um nome e uma frase, se deve gastar uma chamada de ferramenta para carregar o conteúdo completo. Nas minhas avaliações, ele quase nunca faz isso.
Invocação: conteúdo completo sob demanda
Quando o modelo decide que uma skill é relevante, ele chama a ferramenta Skill ():
{ "tool": "Skill", "input": { "skill": "test-driven-development" } }
A SkillTool carrega o conteúdo completo do SKILL.md via getPromptForCommand(), substitui variáveis como $ARGUMENTS e ${CLAUDE_SKILL_DIR} e o injeta na conversa. Dois modos de execução:
- Inline (padrão) - o conteúdo vai diretamente para a conversa atual como uma mensagem de usuário. O modelo lê as instruções e as segue no mesmo contexto.
- Fork (
context: forkno frontmatter) - cria um sub-agente viaexecuteForkedSkill()com contexto isolado e seu próprio orçamento de tokens. O resultado retorna sem inflar a conversa principal.
Mesmo mecanismo que permite ao modelo ler arquivos ou executar comandos bash. Ele pede, o runtime lê um arquivo markdown e o conteúdo retorna.
CLAUDE.md: sempre no contexto
O CLAUDE.md segue um caminho diferente. No início da sessão, o Claude Code percorre do seu diretório de trabalho até a raiz, coletando cada CLAUDE.md, .claude/CLAUDE.md e .claude/rules/*.md que encontrar (). Ele suporta diretrizes @include - um arquivo puxando outros, com até 5 níveis de profundidade.
Tudo isso alimenta getUserContext() em , que é prefixado à conversa como uma mensagem de usuário <system-reminder> antes que o modelo veja qualquer outra coisa ().
| Conteúdo | Quando carrega | Como carrega |
|---|---|---|
CLAUDE.md | Toda sessão, automaticamente | Prefixado como primeira mensagem de usuário |
| Listagens de skills | Toda sessão, automaticamente | Apenas nome + descrição |
| Conteúdo de skills | Sob demanda, quando o modelo chama a ferramenta Skill | Markdown completo injetado na conversa |
O CLAUDE.md está sempre lá. O conteúdo da skill espera o modelo decidir que é relevante e chamar a ferramenta.
O que o Superpowers realmente faz
O Superpowers registra um hook SessionStart. Quando uma sessão começa, o hook executa um script de shell que lê a skill using-superpowers do disco e a entrega como additionalContext na resposta do hook. O Claude Code injeta isso na conversa como uma mensagem <system-reminder>.
O conteúdo é agressivo. A skill envolve as instruções em tags <EXTREMELY_IMPORTANT>:
IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.
This is not negotiable. This is not optional. You cannot rationalize your way out of this.
Inclui até uma tabela de "Bandeiras Vermelhas" listando pensamentos que o modelo possa ter para ignorar skills ("Isso é apenas uma pergunta simples", "Preciso de mais contexto primeiro", "A skill é exagero") e rotula cada um como racionalização.
Portanto, o Superpowers não espera o modelo descobrir as skills. Ele carrega as instruções no início de cada sessão via hook, dizendo ao modelo para invocar as skills antes de fazer qualquer outra coisa. Esta é basicamente a mesma ideia de ter um CLAUDE.md com uma dica ("invoque a skill relevante antes de codificar"), apenas mais alta. Melhor que skills puras, mas ainda não é o mesmo que ter as diretrizes reais no CLAUDE.md desde o início. O modelo ainda precisa invocar a skill, ler o conteúdo e segui-lo. Três etapas que podem falhar. O CLAUDE.md pula as três.
A lacuna de ativação
Eu chamo isso de lacuna de ativação. A distância entre "a skill está instalada" e "o modelo realmente usa a skill".
Executei avaliações de tiro único primeiro para confirmar os números da Vercel. 31 tarefas em react e next.js (react-best-practices-eval, nextjs-agents-md-eval) e um benchmark de 10 tarefas do Superpowers (superpowers-eval). Resultados semelhantes. Skills puras: 0% de invocação. O modelo nunca abre a gaveta por conta própria. AGENTS.md: taxa de aprovação de 76-90%.
Mas, como mencionei, o tiro único não é como as pessoas trabalham. Então, construí um conjunto de avaliações de múltiplos turnos.
A avaliação de múltiplos turnos
5 cenários, 3-4 turnos cada. Node.js/TypeScript simples para que o conhecimento do framework não seja uma variável confusa. Os prompts são do tipo que você realmente digitaria.
Cenário 1: TDD - Validador de Email (4 turnos)
| Turno | Prompt | Fluxo esperado |
|---|---|---|
| 1 | "Construa uma função que valide endereços de email. Ela deve lidar com formatos básicos como user@domain.com e rejeitar os obviamente inválidos, como falta de @ ou strings vazias." | TDD: escrever testes primeiro |
| 2 | "Agora adicione suporte para emails internacionais - endereços com caracteres unicode na parte local e domínios IDN como user@münchen.de." | TDD: estender testes primeiro |
| 3 | "Encontrei um bug - aliases com sinal de mais como user+tag@gmail.com estão sendo rejeitados. Corrija isso." | Debug: reproduzir com teste falho |
| 4 | "Refatore para separar a lógica de parsing da lógica de validação." | Refatoração: garantir que os testes passem depois |
Cenário 2: Debugging - Cache LRU Quebrado (3 turnos)
Começa com uma implementação de cache LRU com bug (a verificação de expulsão usa >= em vez de >, fazendo com que itens "desapareçam").
| Turno | Prompt | Fluxo esperado |
|---|---|---|
| 1 | "Este cache LRU está quebrado - itens parecem desaparecer mesmo quando o cache não está cheio. Você pode descobrir o que está errado e corrigir?" | Debug: reproduzir, encontrar a causa raiz |
| 2 | "Agora funciona, mas está muito lento quando o tamanho do cache é grande - como 10.000 entradas. Você pode melhorar o desempenho?" | Debug: raciocinar sobre complexidade |
| 3 | "Adicione testes para garantir que esses bugs não voltem." | TDD: escrever testes de regressão |
Cenário 3: Planejamento - Rate Limiter (3 turnos)
| Turno | Prompt | Fluxo esperado |
|---|---|---|
| 1 | "Preciso de um rate limiter para uma API. Limite cada cliente a 100 requisições por minuto. Me dê um plano antes de codificar." | Plano: apresentar a abordagem primeiro |
| 2 | "Na verdade, janela fixa não funcionará para o meu caso - requisições se agrupam nos limites da janela e explodem. Preciso de janela deslizante no lugar." | Plano: revisar, explicar trade-offs |
| 3 | "Implemente e adicione testes." | TDD: escrever testes, depois implementar |
Cenário 4: Refatoração - Middleware Express (4 turnos)
Começa com um middleware monolítico de 160 linhas lidando com auth, logging, rate limiting e tratamento de erros.
| Turno | Prompt | Fluxo esperado |
|---|---|---|
| 1 | "Este arquivo de middleware tem 300 linhas e lida com auth, logging, rate limiting e tratamento de erros, tudo em um só. Me ajude a entender o que ele faz." | Análise: ler e explicar |
| 2 | "Divida-o em arquivos de middleware separados e focados." | Refatoração: reestruturar com segurança |
| 3 | "O middleware de auth quebrou após a divisão - requisições que deveriam exigir auth estão passando sem token." | Debug: reproduzir, identificar regressão |
| 4 | "Adicione testes para cada middleware para que possamos capturar esse tipo de coisa." | TDD: escrever testes isolados |
Cenário 5: Misto - Retry de Cliente HTTP (3 turnos)
Começa com um cliente HTTP básico sem lógica de retry.
| Turno | Prompt | Fluxo esperado |
|---|---|---|
| 1 | "Adicione retry com backoff exponencial a este cliente HTTP. Ele deve tentar novamente em erros 5xx e falhas de rede, até 3 tentativas." | TDD ou plano primeiro |
| 2 | "Ele está tentando novamente em erros 400 Bad Request também. Isso está errado - 4xx deve falhar imediatamente sem tentar novamente." | Debug: identificar bug de código de status |
| 3 | "Adicione testes cobrindo a lógica de retry - sucesso na primeira tentativa, retry em 5xx, sem retry em 4xx, máximo de tentativas excedido." | TDD: conjunto de testes abrangente |
Cada cenário cruza fronteiras de fluxo de trabalho. TDD leva ao debugging, debugging termina com testes, planejamento leva à implementação. É aqui que as skills deveriam brilhar, já que têm fluxos dedicados para cada fase.
Quatro configurações:
| Configuração | O que o modelo recebe |
|---|---|
| Superpowers | Hook SessionStart + skills (a experiência real do plugin) |
| Skills puras | Mesmas skills instaladas, sem hook, sem dica |
| CLAUDE.md | Diretrizes equivalentes escritas como regras estáticas, sempre no contexto |
| CLAUDE.md + dica | Uma linha no CLAUDE.md dizendo "invoque a skill relevante antes de codificar" + skills instaladas |
Mesmo modelo (claude-opus-4-6), mesmas tarefas, mesma configuração de workspace. Todas as execuções foram feitas em um ambiente limpo com ~/.claude/plugins, ~/.claude/skills, ~/.claude/settings.json e ~/.claude/CLAUDE.md temporariamente desativados. Apenas a config Superpowers teve plugins restaurados (ela precisa deles para o hook). Cada turno foi limitado a 15 turnos agenticos.
Resultados
Invocações de skills
| Configuração | Invocações | Taxa |
|---|---|---|
| Superpowers (hook) | 10/15 | 66% |
| CLAUDE.md + dica | 5/15 | 33% |
| Skills puras | 1/15 | 6% |
| CLAUDE.md (diretrizes) | n/a | n/a |
8 de 68 turnos totais atingiram o limite de 15 turnos máximos. Isso apenas significa que o modelo ficou sem etapas agenticas antes de terminar, não que não estivesse fazendo um trabalho útil. Na maioria dos turnos MT, o modelo estava ativamente escrevendo testes e implementação, apenas precisava de mais etapas para concluir. As invocações de skill nesses turnos são válidas (ocorreram antes do corte).
Múltiplos turnos ajudam muito o Superpowers. De 10% no tiro único para 66% aqui. O hook dispara no início da sessão e, ao longo dos turnos, o modelo ganha impulso. Uma vez que ele invoca TDD no turno 1, ele sabe que a skill existe e recorre ao debugging quando a tarefa muda no turno 3.
A dica no CLAUDE.md funciona, mas apenas em um ambiente limpo. Esta foi a configuração estilo Vercel. Na minha execução anterior com plugins globais contaminando as coisas, ela marcou 6% (1/16, skill errada). Execução limpa: 33% (5/15, skills corretas). A dica é sensível ao ruído. Skills e plugins globais concorrentes diluem seu efeito.
Skills puras tiveram uma invocação espontânea em 15 turnos. O modelo invocou systematic-debugging sem solicitação no cenário 04, turno 3, após dois turnos de contexto de conversa. Portanto, múltiplos turnos podem disparar a invocação sem um hook, mas é raro.
O ambiente limpo importa mais do que eu esperava. Cada config se saiu melhor na execução limpa. As execuções locais anteriores (com plugins globais presentes, mas renomeados) mostraram o Superpowers em 41%, CLAUDE.md+dica em 6%, skills puras em 0%. Execução limpa: 66%, 33%, 6%. Plugins e skills globais criam um ruído que suprime a invocação de skills.
Quando o Superpowers invoca skills
O padrão é consistente em todas as execuções (local, Docker e limpa):
| Cenário | Turno 1 | Turno 2 | Turno 3 | Turno 4 |
|---|---|---|---|---|
| 01 email | TDD | - | debugging | - |
| 02 LRU cache | debugging | - | TDD | |
| 03 rate limiter | brainstorming | - | TDD | |
| 04 middleware | - | - | debugging | TDD |
| 05 HTTP retry | brainstorming | - | verification |
As skills disparam em transições, quando o fluxo de trabalho muda (codificação para debugging, debugging para testes). Em turnos de continuação, o modelo não reinvoca. Ele mantém o impulso da invocação anterior. O que faz sentido. Você não relê o manual de TDD toda vez que escreve um novo teste.
Conformidade com TDD
Invocações de skill são uma métrica. O agente realmente seguiu o fluxo? Verifiquei se os arquivos de teste foram escritos antes dos arquivos de implementação nos turnos principais de TDD.
| Cenário | Superpowers | Skills Puras | CLAUDE.md | CLAUDE.md + dica |
|---|---|---|---|---|
| 01 email t1 | teste primeiro | impl primeiro | teste primeiro | teste primeiro |
| 02 LRU t1 | teste primeiro | teste primeiro | teste primeiro | teste primeiro |
| 03 rate limiter t3 | teste primeiro | impl primeiro | teste primeiro MT | impl primeiro |
| 05 HTTP retry | teste primeiro (t2) | apenas teste (t3) | teste primeiro (t1) | teste primeiro (t1) |
A questão é a seguinte: Superpowers e CLAUDE.md estão basicamente empatados. Ambos escreveram testes primeiro em 4 de 4 cenários medidos. CLAUDE.md + dica obteve 3/4. Skills puras obtiveram 1/4.
Ter diretrizes no CLAUDE.md não foi necessariamente melhor para fazer o modelo seguir o TDD. Quando o Superpowers dispara, a qualidade do fluxo é igualmente boa. São todos prompt. Mesmo markdown, mesmas instruções, mesmo modelo. A única diferença é se o prompt chega ao modelo. O CLAUDE.md chega todas as vezes. O Superpowers chega 66% das vezes.
O caso interessante é o cenário 04 (refatorar middleware, turno 2). Nenhuma config escreveu testes antes da refatoração. Todos pularam direto para a divisão do middleware em arquivos. A diretriz "escreva testes antes de reestruturar" precisa ser mais forte, independentemente do mecanismo de entrega.
Por que isso acontece
Tanto o CLAUDE.md quanto as listagens de skills chegam pelo mesmo canal: mensagens de usuário encapsuladas em <system-reminder>. Não há diferença de confiança arquitetônica. A diferença é apenas a presença.
O conteúdo do CLAUDE.md está sempre na janela de contexto. A cada turno, a cada decisão, as diretrizes estão logo ali. O conteúdo da skill exige que o modelo leia a listagem de nome+descrição, decida que a skill é relevante, chame a ferramenta Skill, espere pelo conteúdo e então o siga. Cada etapa pode falhar.
Portanto, a lacuna de ativação não é um problema de qualidade. É um problema de confiabilidade. Quando as skills são invocadas, elas funcionam. Elas apenas não são sempre invocadas. Superpowers chega a 66% em múltiplos turnos limpos. A dica no CLAUDE.md chega a 33%. Nenhum dos dois chega a 100%.
O CLAUDE.md atinge 100% de presença. Nenhuma invocação é necessária.
Skills são receitas, CLAUDE.md é o código sanitário
Pense nisso como uma cozinha.
O CLAUDE.md é o código sanitário. Lave as mãos, sanitize as superfícies, verifique as temperaturas. Todo cozinheiro segue essas regras em todos os turnos. Elas são inegociáveis e sempre visíveis, postadas na parede. Você não espera que alguém pergunte "devo lavar as mãos antes de tocar na comida?". É a base.
Skills são receitas. Você pega a receita de bouillabaisse quando alguém pede bouillabaisse. Você não cola todas as receitas na parede ao lado do código sanitário. Isso seria ruído. As receitas têm seu momento. O código sanitário é constante.
O Superpowers tenta transformar receitas em código sanitário fazendo com que um hook grite "LEIA AS RECEITAS" no início de cada turno. Funciona na maioria das vezes. Mas você poderia apenas colocar as regras importantes na parede.
O CLAUDE.md é para diretrizes. Convenções, padrões de codificação, regras de fluxo de trabalho, processos de TDD, protocolos de debugging. Qualquer coisa que o agente deva seguir em todas as sessões. "Escreva testes antes da implementação" é uma regra de código sanitário. Vai para o CLAUDE.md.
Skills são para receitas. Procedimentos específicos, sob demanda, que você invoca quando o momento pede. "Gerar uma migração de banco de dados", "criar a estrutura de um componente", "executar o checklist de lançamento". Estas não precisam estar no contexto o tempo todo. Precisam estar lá quando você as solicita. Use context: fork para receitas pesadas que inflariam o contexto principal.
Hooks servem para automação, não para entrega de instruções. Validação de pré-commit, linting, notificações. Se você está usando um hook para injetar diretrizes (como o Superpowers faz), ele funciona com 66% em múltiplos turnos limpos, mas o CLAUDE.md faria o mesmo trabalho com 100% e zero lacuna de ativação.
| Mecanismo | Presença | Invocação necessária | Taxa de multi-turno limpo |
|---|---|---|---|
CLAUDE.md (código sanitário) | 100% | Não | n/a, sempre presente |
| Superpowers (hook + receitas) | Hook: 100%, Conteúdo: 66% | Sim | 66% |
| CLAUDE.md + dica + skills | 100% (dica), 33% (conteúdo) | Sim | 33% |
| Skills puras (receitas na prateleira) | Apenas listagem | Sim | 6% |
Diretrizes gerais não pertencem a skills. Skills não são a forma de dizer "sempre faça X". Elas são a forma de dizer "quando precisar fazer Y, aqui está como".
Resultados completos turno a turno
Cada turno, cada configuração. MT marca turnos que atingiram o limite de 15 turnos máximos.
Superpowers (hook + skills) - 10/15 invocações (66%)
| Cenário | Turno | Skill invocada | Primeiro arquivo escrito |
|---|---|---|---|
| 01 email | t1 (tdd) | test-driven-development | validateEmail.test.ts (teste primeiro) |
| 01 email | t2 (tdd) | - | - (usou Edit) |
| 01 email | t3 (debug) | systematic-debugging | - |
| 01 email | t4 (refactor) | - | validateEmail.ts |
| 02 LRU | t1 (debug) | systematic-debugging | lru-cache.test.ts (teste primeiro) |
| 02 LRU | t2 (debug) | - | lru-cache.ts |
| 02 LRU | t3 (tdd) | test-driven-development | - |
| 03 rate limiter | t1 (plan) | brainstorming | - (planejamento, sem código) |
| 03 rate limiter | t2 (plan) | - | - |
| 03 rate limiter | t3 (tdd) | test-driven-development | rate-limiter.test.ts (teste primeiro) MT |
| 04 middleware | t1 (analysis) | - | - (lendo código) |
| 04 middleware | t2 (refactor) | - | logging.ts (impl primeiro) |
| 04 middleware | t3 (debug) | systematic-debugging | middleware.test.ts |
| 04 middleware | t4 (tdd) | test-driven-development | logging.test.ts (teste primeiro) MT |
| 05 HTTP retry | t1 (tdd) | brainstorming | - |
| 05 HTTP retry | t2 (debug) | - | http-client.test.ts (teste primeiro) |
| 05 HTTP retry | t3 (tdd) | verification-before-completion | - |
Skills puras (sem hook, sem dica) - 1/15 invocações (6%)
| Cenário | Turno | Skill invocada | Primeiro arquivo escrito |
|---|---|---|---|
| 01 email | t1 (tdd) | - | validateEmail.ts (impl primeiro) |
| 01 email | t2 (tdd) | - | - |
| 01 email | t3 (debug) | - | - |
| 01 email | t4 (refactor) | - | validateEmail.ts |
| 02 LRU | t1 (debug) | - | lru-cache.test.ts (teste primeiro) |
| 02 LRU | t2 (debug) | - | lru-cache.ts |
| 02 LRU | t3 (tdd) | - | - |
| 03 rate limiter | t1 (plan) | - | scalable-bubbling-lagoon.md |
| 03 rate limiter | t2 (plan) | - | types.ts (impl primeiro) MT |
| 03 rate limiter | t3 (tdd) | - | - |
| 04 middleware | t1 (analysis) | - | - |
| 04 middleware | t2 (refactor) | - | logging.ts (impl primeiro) |
| 04 middleware | t3 (debug) | systematic-debugging | middleware.test.ts |
| 04 middleware | t4 (tdd) | - | logging.test.ts |
| 05 HTTP retry | t1 (tdd) | - | - |
| 05 HTTP retry | t2 (debug) | - | - |
| 05 HTTP retry | t3 (tdd) | - | http-client.test.ts |
CLAUDE.md (diretrizes, sem skills) - 0/14 invocações (n/a)
| Cenário | Turno | Primeiro arquivo escrito |
|---|---|---|
| 01 email | t1 (tdd) | validateEmail.test.ts (teste primeiro) |
| 01 email | t2 (tdd) | - |
| 01 email | t3 (debug) | - |
| 01 email | t4 (refactor) | - |
| 02 LRU | t1 (debug) | lru-cache.test.ts (teste primeiro) |
| 02 LRU | t2 (debug) | bench.ts |
| 02 LRU | t3 (tdd) | - |
| 03 rate limiter | t1 (plan) | - |
| 03 rate limiter | t2 (plan) | - |
| 03 rate limiter | t3 (tdd) | rate-limiter.test.ts (teste primeiro) MT |
| 04 middleware | t1 (analysis) | - |
| 04 middleware | t2 (refactor) | testes primeiro (4 arquivos de teste antes da impl) MT |
| 04 middleware | t3 (debug) | - |
| 04 middleware | t4 (tdd) | - |
| 05 HTTP retry | t1 (tdd) | http-client.test.ts (teste primeiro) |
| 05 HTTP retry | t2 (debug) | - |
| 05 HTTP retry | t3 (tdd) | - |
CLAUDE.md + dica (skills instaladas) - 5/15 invocações (33%)
| Cenário | Turno | Skill invocada | Primeiro arquivo escrito |
|---|---|---|---|
| 01 email | t1 (tdd) | test-driven-development | validateEmail.test.ts (teste primeiro) |
| 01 email | t2 (tdd) | - | - |
| 01 email | t3 (debug) | - | - |
| 01 email | t4 (refactor) | - | validateEmail.ts |
| 02 LRU | t1 (debug) | systematic-debugging | lru-cache.test.ts (teste primeiro) |
| 02 LRU | t2 (debug) | - | lru-cache.ts |
| 02 LRU | t3 (tdd) | - | - |
| 03 rate limiter | t1 (plan) | - | snazzy-juggling-glacier.md |
| 03 rate limiter | t2 (plan) | - | rate-limiter.ts (impl primeiro) |
| 03 rate limiter | t3 (tdd) | - | types.ts (impl primeiro) MT |
| 04 middleware | t1 (analysis) | - | - |
| 04 middleware | t2 (refactor) | - | - |
| 04 middleware | t3 (debug) | systematic-debugging | - |
| 04 middleware | t4 (tdd) | test-driven-development | logging.test.ts (teste primeiro) MT |
| 05 HTTP retry | t1 (tdd) | test-driven-development | http-client.test.ts (teste primeiro) MT |
| 05 HTTP retry | t2 (debug) | - | - |
| 05 HTTP retry | t3 (tdd) | - | - |
Metodologia
Execução
Cada cenário é executado como uma sessão de múltiplos turnos claude -p:
# Turno 1: sessão nova
claude -p --model claude-opus-4-6 --output-format stream-json
--verbose --dangerously-skip-permissions --max-turns 15
"$PROMPT" > turn-1.jsonl
# Extrair ID da sessão
sid=$(grep -o '"session_id":"[^"]*"' turn-1.jsonl | head -1 | cut -d'"' -f4)
# Turno 2+: retomar mesma sessão
claude -p --model claude-opus-4-6 --output-format stream-json
--verbose --dangerously-skip-permissions --max-turns 15
--resume "$sid" "$PROMPT" > turn-2.jsonl
Isolamento do ambiente
Todas as execuções desativaram a configuração de nível de usuário para evitar contaminação:
# Desativado no início, restaurado na saída (trap)
~/.claude/plugins -> ~/.claude/plugins.eval-disabled
~/.claude/skills -> ~/.claude/skills.eval-disabled
~/.claude/settings.json -> ~/.claude/settings.json.eval-disabled
~/.claude/CLAUDE.md -> ~/.claude/CLAUDE.md.eval-disabled
Apenas a config Superpowers reativou ~/.claude/plugins (o hook + skills vêm do plugin). A autenticação OAuth permanece no keychain do macOS, não afetada pela renomeação.
Configuração por workspace
Cada cenário recebe um workspace novo em /tmp com package.json, tsconfig.json, arquivos semente (se houver) e npm install. Então:
- Superpowers: plugin fornece o hook SessionStart + skills via
.claude/settings.json - Skills puras: skills copiadas para
.claude/skills/do workspace, sem hook - CLAUDE.md:
CLAUDE.mdcom diretrizes equivalentes de TDD/debugging/planejamento - CLAUDE.md + dica:
CLAUDE.mdcom "Antes de escrever código, primeiro explore a estrutura do projeto e, em seguida, invoque a skill relevante para a tarefa em questão." + skills copiadas para.claude/skills/do workspace
Turnos máximos
Cada turno foi limitado a 15 etapas agenticas (--max-turns 15). 8 de 68 turnos atingiram esse limite. Os turnos afetados estão marcados com MT nas tabelas de resultados. Na maioria dos turnos MT, o modelo estava ativamente escrevendo testes e código, apenas precisava de mais etapas para terminar. A flag || true evita que o truncamento mate o script executor.
Medição
Invocações de skill são extraídas de transcrições stream-json procurando por "name":"Skill" em mensagens do assistente. A conformidade com TDD é medida pela ordem das chamadas da ferramenta Write - se os arquivos de teste (.test.ts, .spec.ts) aparecem antes dos arquivos de implementação.
Reprodutibilidade
Um Dockerfile está incluso para execuções totalmente isoladas (requer ANTHROPIC_API_KEY):
docker build -t multiturn-eval .
docker run -d -e ANTHROPIC_API_KEY=$KEY
-v ./results:/home/evaluser/eval/results
multiturn-eval
Validei a avaliação em três ambientes: local com renomeação de plugin, Docker com zero configuração de usuário e local com configuração total desativada. Os padrões de invocação do Superpowers foram idênticos nos três.
Os repositórios estão abertos se você quiser reproduzir ou analisar os dados:
- react-best-practices-eval - 10 tarefas React de tiro único
- nextjs-agents-md-eval - 21 tarefas Next.js de tiro único
- superpowers-eval - Benchmark de invocação do Superpowers
- multiturn-eval - 20 cenários de múltiplos turnos em 4 configs (este post)
O que fazer com isso
Se você está configurando o Claude Code para um projeto:
- TDD, protocolos de debugging, estilo de código, convenções de nomenclatura vão para o
CLAUDE.md. Estas são regras que você quer que sejam seguidas em toda sessão. Sem invocação, sem lacuna de ativação, 100% de presença. - "Criar estrutura de serviço", "gerar migração", "executar checklist de lançamento" vão para skills. Estes são procedimentos que você chama quando precisa. Use
context: forkse forem pesados. - Se você precisar que o
CLAUDE.mdreferencie documentação extra, transforme-o em um índice. Aponte para arquivos. Mesmo padrão que o Claude Code usa para sua própria memória: um arquivo raiz que linka para as especificidades. - Se você usa o Superpowers e ele funciona para você, continue usando. Agora você sabe por que funciona (o hook) e onde ele falha (34% dos turnos em múltiplos turnos, mais no tiro único). Mover suas diretrizes para o
CLAUDE.mdfecharia essa lacuna.
As skills não estão quebradas. Elas apenas não servem para diretrizes.
We want to work with you. Check out our Services page!

