Mapa da trilha
🧬 O que é um mod por dentro
Três arquivos e uma função
🗂️ Estrutura de arquivos e manifesto
plugin.json manda
🔄 Carregar, recarregar e instalar
Pasta vigiada, mod vivo
🚀 Seu primeiro mod: comando e contador
readcount funcionando
Conteúdo detalhado
🧬 O que é um mod por dentro
O que um mod é por dentro, onde ele roda e como ele se separa do hook clássico, da skill e do MCP.
Quando o Claude Code carrega um mod, ele importa o módulo, chama register(on, options) e passa a chamar os hooks registrados a cada evento.
Entender esse momento explica por que um mod pode mudar o que o Claude vê, desenha e faz sem tocar no código do Claude Code.
mod, plugin, function hook, register, carregamento.
Mod roda dentro do processo, em um ambiente próprio; hook clássico é um comando de shell do settings.json; skill é instrução para o modelo; MCP é um servidor de ferramentas.
Escolher a forma errada custa caro: muita coisa que parece mod se resolve com uma skill, e vice-versa.
mod, hook clássico, skill, MCP, settings.json.
A função exportada recebe on, para registrar hooks, e options, com os valores dos campos que o manifesto declara em userConfig.
É a única porta de entrada do mod: tudo o que ele faz começa nessa função.
register, on(evento, matcher?, hook), options, userConfig.
Todo hook tem a forma ($, e, next): $ é a interface do engine, e é a entrada do evento e next(e) passa adiante na cadeia.
Esses três nomes aparecem em todo exemplo do curso; dominá-los é ler qualquer mod.
$, e, next, cadeia, resultado do evento.
O módulo é um ES module que roda num ambiente próprio, sem DOM e sem Node; tudo fora dele é alcançado pelo $.
Evita o erro mais comum de quem chega: importar fs do Node ou usar import() dinâmico, que não carregam.
ES module, ambiente isolado, $ como única saída, import estático.
O caminho do curso, do primeiro mod ao marketplace, e os dois kits usados: o Claude Mods Starter Kit (Prompt Advisers, MIT) e o inema-mods.
Você sabe de onde vem cada exemplo e em que versão foi conferido: Claude Code 2.1.289.
starter kit, inema-mods, versão 2.1.289, acesso antecipado.
🗂️ Estrutura de arquivos e manifesto
A árvore mínima: .claude-plugin/plugin.json, hooks/hooks.json e o módulo. Opções com userConfig e validação antes de carregar.
A pasta do mod com .claude-plugin/plugin.json, hooks/hooks.json e o módulo de hooks, mais tests/ quando houver teste.
Com a árvore certa o Claude Code acha o mod; com um nome trocado, nada carrega e nada avisa alto.
pasta do plugin, .claude-plugin, hooks/, tests/.
O manifesto do plugin: name, version, description e, quando houver, userConfig e types.
O name vira o prefixo de comandos, ferramentas e estado; mudar depois quebra quem já usa.
plugin.json, name, version, manifesto.
O hooks.json lista em modules o caminho do módulo, relativo ao próprio hooks.json, como {"modules":["./starter.mjs"]}.
É o elo entre o manifesto e o código; o validate mostra se ele aponta para o lugar certo.
hooks.json, modules, caminho relativo.
O módulo pode ser .ts, .tsx, .jsx, .js, .mjs, .cjs, .mts ou .cts, e é sempre ES module; outro sufixo não carrega.
O kit começa em .mjs sem compilação; a partir da trilha 2 o curso usa .tsx tipado.
extensão, ES module, TypeScript, JSX com h.
Campos declarados em userConfig no plugin.json viram linhas do menu de configuração e chegam ao mod em options.
Deixa o usuário ajustar o mod sem editar código, e cada mudança recarrega o módulo.
userConfig, options, pluginConfigs, /config.
O comando lê o manifesto e o código do módulo como o engine leria e lista os hooks, as chamadas e o que seria recusado.
Pega o erro antes de abrir uma sessão: é o primeiro passo de todo ciclo de mudança.
claude plugin validate, hooks listados, calls, Validation passed.
🔄 Carregar, recarregar e instalar
Do --plugin-dir com hot-reload à instalação por marketplace, com escopo certo e desinstalação limpa.
A flag carrega o mod de uma pasta do disco só para aquela sessão; repita a flag para carregar vários.
É o jeito de desenvolver: nada fica instalado, e fechar a sessão desfaz tudo.
--plugin-dir, sessão, pasta local.
Numa sessão interativa a pasta é vigiada: salvar um arquivo roda o register de novo num ambiente novo, e os timers antigos caem.
Você ajusta e vê na hora, sem reiniciar o Claude Code.
hot-reload, pasta vigiada, ambiente novo, timers.
A variável de ambiente nomeia as mesmas pastas, com caminho absoluto, para sessões abertas pelo app desktop ou por um SDK.
No desktop não existe linha de comando para pôr a flag; a variável resolve.
CLAUDE_CODE_PLUGIN_DIRS, desktop, SDK, settings env.
Registrar uma pasta ou repositório como marketplace e instalar o plugin dele com claude plugin install.
É como o mod chega às sessões de todo dia sem flag nenhuma.
marketplace, claude plugin marketplace add, claude plugin install.
O escopo diz onde a instalação vale: para você em todo projeto, para o projeto inteiro ou só na sua cópia local.
Instalar no escopo errado espalha o mod onde não devia ou esconde de quem precisa.
--scope user, project, local.
Desligar com claude plugin disable e remover a instalação sem deixar marketplace ou config esquecidos.
Mod que não sai direito vira suspeito de todo comportamento estranho depois.
claude plugin disable, remover a instalação, claude plugin list.
🚀 Seu primeiro mod: comando e contador
O starter-mod do kit da Prompt Advisers: o comando /readcount, o contador de leituras, validate, test e claude -p.
Copiar o modelo do kit da Prompt Advisers, que já traz manifesto, hooks.json, starter.mjs e um teste.
Começar de um mod que passa no validate e no test tira o atrito do primeiro dia.
starter-mod, cópia, read-counter-example.
O starter.mjs registra o comando em session.start, conta leituras bem-sucedidas em tool.call com matcher Read e responde em command.run.
São três dos eventos mais usados, num arquivo curto que você lê inteiro.
session.start, tool.call, matcher, command.run, $.command.register.
Rodar claude plugin validate e claude plugin test na pasta copiada e ler as duas saídas.
Você confirma que a cópia está íntegra antes de mudar uma linha.
Validation passed, 1 pass, 0 fail.
Chamar /readcount com claude -p e --plugin-dir: o próprio mod responde, sem turno do modelo.
É o teste de fumaça mais barato que existe e vale para qualquer comando de mod.
claude -p, comando de barra, resposta sem modelo.
Trocar o matcher do tool.call para contar outra ferramenta, como Edit ou Write, e rodar o teste de novo.
É a primeira mudança real: você vê o teste quebrar e sabe consertar.
matcher, tool, teste que falha, ajuste.
Trocar o name do manifesto, o nome do comando e as mensagens para o mod virar seu.
Nome repetido colide com outros mods; seu nome é o prefixo de tudo o que o mod registra.
name, prefixo, colisão, README.