AIDive

Pack de vídeo

Mods do Claude Code: o experimento da falha aberta, medições, checklist e fontes

10 min de leitura

TL;DR

  • Um Mod do Claude Code são três arquivos: .claude-plugin/plugin.json, hooks/hooks.json com {"modules":["./index.ts"]}, e um módulo TypeScript que exporta register(on). Não é preciso mais nada para carregá-lo.
  • Na build 2.1.272, a superfície tipada que o /plugin-types escreve tem 11,783 linhas de claude-code.d.ts: 84 nomes de eventos ou chamadas distribuídos em 23 substantivos. fs.readFile sumiu, o substantivo é fs.read e fs.write.
  • Um hook tool.call de 42 linhas fez o modelo ler API_KEY=[REDACTED] no lugar da chave real, tanto na ferramenta Read quanto na Bash, a 27.9 ms por salto saudável e cerca de 0 token adicionado à sessão.
  • Um hook que dorme além do orçamento de 10 s ou lança uma exceção é ignorado e o comando logo abaixo roda. O log avisa, mas o efeito é um bypass: um Mod de guarda falha aberto.
  • O caminho gerado funciona: uma frase produziu um Mod de 190 linhas mais 53 linhas de testes em cerca de 4 minutos e $1.23, passando em claude plugin validate sem avisos e em claude plugin test com 4 pass / 0 fail.
  • Uma coisa não se reproduziu: o Mod carregou com claude -p, mas ficou mudo em um REPL interativo conduzido por pty, em duas tentativas. Trate o carregamento no REPL como não verificado até testar em um terminal de verdade.

O que as medições dizem

Tudo abaixo foi executado no Claude Code 2.1.272 com CLAUDE_CODE_ENABLE_FUNCTION_HOOKS definido, em um Mod escrito à mão chamado redact-secrets e em três Mods descartáveis criados para quebrá-lo. A funcionalidade é acompanhada na issue de proposta de Function Hooks, que continua sendo o mais próximo de uma especificação oficial s3.

As ferramentas existem antes da documentação. A build 2.1.272 traz claude plugin validate, test, eval e details; o test funciona mesmo que plugin --help não o liste no bloco de comandos s3. Rodar /plugin-types dentro de uma sessão escreveu 11,783 linhas em .claude/types/claude-code.d.ts, mais um claude-code-mcp.d.ts de 3,438 linhas cobrindo 150 ferramentas MCP de 7 servidores s3. Contando os tipos gerados, são 84 nomes de eventos ou chamadas em 23 substantivos, e o arquivo renomeia algo que você pode ter lido em posts de setembro: fs.readFile não existe mais, a superfície é fs.read e fs.write s9. Os mesmos tipos dizem que um hook tool.call retorna { result, context? } ou { deny }; text e ref vêm do core e não fazem parte da resposta do próprio hook, então você reescreve result, não text s3.

O claude plugin validate imprime uma pegada antes de o Mod rodar: ./index.ts hooks: tool.call e ./index.ts calls: $.ui.toast, ou calls: nothing on $ quando o módulo não toca em nenhuma capacidade do host s4. Essa linha estática é a única checagem que um diretório como o awesome-claude-code-mods consegue automatizar hoje, o que importa para o próximo parágrafo.

A redação funciona no modo -p. O hook de 42 linhas interceptou tool.call, e o modelo recebeu API_KEY=[REDACTED] onde o arquivo e a saída do shell continham sk-test1234567890abcdef, tanto na ferramenta Read quanto na Bash s3. O log de debug cronometrou um salto saudável em 27.9 ms de ida e volta, incluindo o salto ao worker e o next() s3. O claude plugin details precificou o Mod em cerca de 0 token adicionado a cada sessão: um Mod é código no processo, não texto de prompt, que é o principal argumento de quem o defende contra hooks de shell e skills s7.

A guarda falha aberta. Um Mod slow-guard que dorme 15 s foi cortado no orçamento de 10 s com hook failed: slow-guard: exceeded 10000ms budget (tool.call; skipped; what is below it ran in its place), e o echo hi rodou mesmo assim s3. Um Mod throw-guard que lança exceção foi ignorado do mesmo jeito, hook failed: throw-guard: boom (tool.call; skipped; what is below it ran in its place), com 574.2 ms reportados s3. Barulhento no log, contornado na prática. Qualquer Mod cujo trabalho seja bloquear algo deve ser lido com isso em mente: um bug na guarda é um buraco, não um crash.

Gerar é barato. A partir de uma única frase, o modelo escreveu um Mod funcional de 190 linhas mais 53 linhas de testes em cerca de 4 minutos, 34 turnos e $1.23 (19,053 tokens de saída, 497,282 de leitura de cache, 8,357 de raciocínio) s3. Esse Mod passou em claude plugin validate sem avisos e em claude plugin test com 4 pass / 0 fail em 0.31 s, e escondeu as chaves ao vivo s3. No Mod escrito à mão, o claude plugin test rodou sem chave de API e sem chamada ao modelo: 1 pass em 0.25 s s3. Já existe um skill que ensina agentes a escrever Mods, se você quiser repetir isso com um template s12.

O que não se reproduziu: o $.ui.toast nunca apareceu porque o Mod não carregou no REPL conduzido por pty em 2 tentativas; no -p, o equivalente só surgiu como uma linha de debug. Observou-se o oposto da afirmação "só no REPL" que circula no X, e a causa raiz não foi isolada s8. O heartbeat de 5 s do worker travado também não foi testado; só o orçamento de espera de 10 s e o caminho da exceção foram medidos.

Medições

Caso O que o Mod faz Resultado Tempo
redact-secrets, ferramenta Read Reescreve result em tool.call O modelo vê API_KEY=[REDACTED] 27.9 ms por salto
redact-secrets, ferramenta Bash Mesmo hook, saída do shell O modelo vê API_KEY=[REDACTED] 27.9 ms por salto
slow-guard Dorme 15 s dentro de tool.call Ignorado, echo hi rodou cortado em 10000 ms
throw-guard Lança boom dentro de tool.call Ignorado, comando rodou 574.2 ms
Mod gerado 190 linhas + 53 linhas de testes a partir de uma frase validate: sem avisos; test: 4 pass / 0 fail ~4 min, 34 turnos, $1.23
claude plugin test no redact-secrets Sem chave de API, sem chamada ao modelo 1 pass 0.25 s
claude plugin details Custo do Mod por sessão ~0 token adicionado n/a

Protocolo: Claude Code 2.1.272, function hooks ativados por variável de ambiente. Cada Mod é um diretório de plugin com plugin.json, hooks/hooks.json e um único index.ts. As execuções passaram por claude -p com log de debug ligado; um arquivo plantado e um comando de shell continham sk-test1234567890abcdef. Os casos de falha aberta foram conduzidos por um Mod que dorme 15 s e um Mod que lança exceção, com echo hi como comando sob guarda. O REPL interativo foi conduzido por um pty e não carregou o Mod em duas tentativas.

Faça isto na segunda-feira

  • Rode /plugin-types em uma sessão e abra .claude/types/claude-code.d.ts: procure fs.read e tool.call antes de confiar em qualquer snippet de um post de setembro.
  • Escreva o esqueleto de Mod de três arquivos (plugin.json, hooks/hooks.json com {"modules":["./index.ts"]}, index.ts exportando register(on)) e rode claude plugin validate nele: leia as linhas de pegada hooks: e calls:.
  • Porte seu hook de shell mais usado para um handler tool.call que reescreve result, e compare o tempo de salto no log de debug com a versão em shell.
  • Adicione um arquivo claude plugin test ao lado do Mod para que a guarda rode sem chave de API no CI.
  • Envolva cada handler de guarda em um try/catch que retorne { deny } em caso de falha: nesta build, uma exceção ou uma parada de 10 s ignora você e deixa o comando passar.
  • Teste o Mod com claude -p e no seu terminal interativo de verdade separadamente, e anote qual deles o carregou.
  • Antes de instalar um Mod de terceiros, rode claude plugin validate nele e rejeite qualquer um cuja linha calls: cite capacidades do host que o Mod não tem motivo para usar.

Para ir além

  • Leia a issue de proposta de ponta a ponta, incluindo o PDF de arquitetura anexado nos comentários: é o único contrato escrito para register(on), os orçamentos e o salto ao worker s3.
  • Compare com o design dos Mods do Command Code, que executa TypeScript contra um ModApi no processo host: os dois sistemas compartilham o formato e o acesso antecipado restrito s2.
  • O preview do claudefa.st foi escrito enquanto a funcionalidade ainda era uma proposta: útil para ver o que mudou entre o texto de 3 de setembro e o binário 2.1.272 s9.
  • A nota do Prathkum é a declaração curta mais clara de por que hooks no processo vencem hooks de shell em tokens e latência s7.
  • O cc-mod-waitwhat é um bom primeiro Mod para ler: UI acima do prompt, nada escrito na transcrição s11.
  • O cc-arcade mostra até onde o $.ui chega: jogos renderizados acima do prompt a partir de um Mod s5.
  • A referência de hooks ainda descreve o modelo de shell; deixe-a aberta para mapear cada evento antigo para o novo nome noun.event s1.
  • Céticos no X argumentam que os plugins já cobrem isso e que a superfície vai quebrar a cada release; o substantivo fs renomeado é um ponto a favor deles s23.

Fontes

  • Function Hooks proposal (issue #91870), GitHub, anthropics/claude-code. Por que ler: o único texto parecido com uma especificação para Mods, com o PDF de arquitetura e o histórico de entrega nos comentários.
  • Hooks reference, Claude Code docs. Por que ler: o modelo de hooks de shell do qual você está migrando, evento por evento.
  • Command Code Mods documentation, Command Code. Por que ler: precedente com o mesmo formato de TypeScript no processo, útil para ver o que a Anthropic copiou ou evitou.
  • awesome-claude-code-mods, GitHub, karanb192. Por que ler: diretório de Mods públicos escaneado automaticamente, com a pegada do validate como única checagem.
  • cc-arcade, GitHub, sezaakgun. Por que ler: a demo que tornou a funcionalidade visível e um tour pelo $.ui.
  • Boris Cherny announcement tweet, X, Boris Cherny. Por que ler: o anúncio de lançamento por um engenheiro da Anthropic, já que não existe post de blog.
  • Prathkum: Function Hooks explained, X, Prathkum. Por que ler: a melhor explicação curta de hooks versus Mods para quem já escreve hooks de shell.
  • shipnotesai reaction thread, X, shipnotesai. Por que ler: onde a afirmação "só no REPL" circulou, e que o nosso teste contradisse.
  • Claude Code Function Hooks: Preview Behind a Flag, claudefa.st. Por que ler: explicação pré-lançamento, boa para comparar a proposta com o binário.
  • cc-mod-waitwhat, GitHub, GGGODLIN. Por que ler: um Mod pequeno e legível que escreve na UI e não na transcrição.
  • claude-mods-skill, GitHub, BeLazy167. Por que ler: um skill para gerar Mods, se você quiser repetir o experimento de uma frase.
  • AxialisSoftware reaction, X, AxialisSoftware. Por que ler: o caso cético, em um único tweet.

FAQ

Um Mod substitui meus hooks de shell hoje?

Ainda não para nada que precise bloquear. Na 2.1.272, um hook que lança exceção ou trava por mais de 10 s é ignorado e o comando roda. Os hooks de shell continuam funcionando, então mantenha neles os que bloqueiam até chegar um catch declarado ou uma opção de falha fechada.

Por que o validate importa se o Mod roda bem?

Porque as linhas hooks: e calls: são a única visão estática do que um Mod toca em $. No seu próprio Mod, confirmam a pegada; num Mod de terceiros, são toda a revisão que você tem antes de o código rodar no seu processo.

Quanto um Mod custa por sessão?

O claude plugin details reportou cerca de 0 token adicionado. O Mod é código rodando no motor, não texto no prompt, que é a principal vantagem sobre um skill ou uma regra de CLAUDE.md.

Por que o Mod carregou no -p mas não no REPL?

Desconhecido. Duas tentativas conduzidas por pty ficaram mudas enquanto o claude -p carregava e aplicava o hook. A causa provável é o ambiente pty e não a funcionalidade, então teste no seu próprio terminal antes de confiar em qualquer um dos lados.