Skip to content

Tutorial de Claude Code Mods: como criar, testar e instalar seu primeiro mod, com 15 exemplos da comunidade

Atualizado em

Tutorial de Claude Code mods (v2.1.287+), os plugins de funções TypeScript que desenham painéis, adicionam slash commands instantâneos e protegem chamadas de ferramenta. Veja como criar e testar três mods funcionais, conheça 15 mods da comunidade e faça as checagens de segurança antes de instalar um.

Um mod do Claude Code é um plugin feito de funções JavaScript ou TypeScript que rodam dentro do Claude Code. Um mod pode desenhar um painel ou uma linha acima do prompt, adicionar um slash command que roda na hora e barrar ou reescrever uma chamada de ferramenta antes que ela rode. Os mods chegaram no Claude Code 2.1.287, em 1º de outubro de 2026, e vêm ativados por padrão.

Escolha o caminho mais rápido:

Você querFaça isto
Ter um mod sem escrever códigoDescreva o mod numa sessão, por exemplo "crie um mod que mostre quanto tempo cada turno levou". O Claude escreve o código e pergunta uma vez se pode ativar o hot reload
Instalar o mod de outra pessoa/plugin install <name>@<marketplace> numa sessão no terminal, ou claude plugin install <name>@<marketplace> no seu shell
Carregar uma pasta enquanto desenvolveclaude --plugin-dir ./my-mod
Testar o agente lateral embutido/plugin enable cc-plugin-you-should-know@builtin

Antes de tudo, confira sua versão. O claude --version deve mostrar 2.1.287 ou mais recente. O app Desktop traz a própria cópia do Claude Code, e nele os mods funcionam a partir da 2.1.286. Digite /status na aba Code para ver qual versão você tem.

O que eu testei. Em 7 de outubro de 2026, criei três mods no Claude Code 2.1.293, na aba Code do app Desktop no macOS: um guard de comandos, um medidor de turno acima do prompt e um comando /pyenv para trabalho com Python. Os três passam no claude plugin validate e em 8 testes automatizados rodados com claude plugin test. Também rodei o guard ao vivo numa sessão com hot reload ativado. As seções sobre a comunidade se baseiam em cerca de 50 posts em japonês publicados no Zenn, no Qiita e no note.com entre 1º e 7 de outubro, na documentação oficial de mods (opens in a new tab) e nos dados de varredura do catálogo awesome-claude-code-mods (opens in a new tab) de 6 de outubro.

O que é um mod e quando usar outra coisa

Antes dos mods, você estendia o Claude Code por fora, com settings hooks, skills, um script de status line ou um servidor MCP. A diferença está em onde o código roda. Um settings hook é um script que o Claude Code inicia por fora. As funções de um mod rodam dentro do próprio processo do Claude Code. Por isso um mod consegue desenhar na interface, e nenhuma das outras opções consegue.

A visão geral oficial compara as opções mais ou menos assim:

ModSettings hookSkillServidor MCP
O que éFunções JS ou TS num pluginUm comando de shell, uma chamada HTTP ou um prompt no settings.jsonUm arquivo SKILL.md com instruçõesUm processo externo que dá ferramentas ao Claude
Pode desenhar na UISimNãoNãoNão
O que pode mudarChamadas de ferramenta, prompts, comandos, turnos, a UISe uma chamada segue adiante, seus argumentos e seu resultado, contexto extraO que o Claude sabe e fazQuais ferramentas o Claude tem
Escolha quandoVocê quer um painel, uma faixa, um comando instantâneo ou reescrever um eventoVocê já tem um script que bloqueia ou registra logsVocê vive colando as mesmas instruçõesO Claude precisa acessar um sistema externo

Uma armadilha de nomes. Nas páginas sobre mods, "hook" quer dizer uma função de um mod, e o tipo antigo se chama "settings hook". Os settings hooks continuam funcionando e não foram descontinuados. Um mesmo plugin pode reunir um mod, uma skill e um servidor MCP.

Onde os mods funcionam

Os hooks rodam em quase todo lugar. Já o desenho só acontece no terminal e no app Desktop.

Onde você roda o Claude CodeOs hooks rodamA UI do mod aparece
claude num terminal, incluindo terminais de editores e JetBrainsSimSim
App Desktop, aba CodeSimSim, exceto elementos exclusivos do terminal
App Desktop, sessão WSLNãoNão
Painel de chat da extensão do VS CodeSimNão
claude -p e o Agent SDKSimNão
Sessões na nuvemSim, se o plugin chegar à sessãoNão

Essa tabela vem da visão geral oficial. Na prática, um mod de guard continua protegendo você no VS Code e no claude -p, enquanto um medidor não tem onde desenhar.

Cuidado com duas cópias do Claude Code. Vários autores japoneses viram erros confusos no validate porque um CLI antigo do Homebrew no terminal, nas versões 2.1.226 e 2.1.234 segundo os relatos, convivia com a 2.1.286 embutida no app Desktop. Confira a versão em cada lugar onde você usa o Claude Code.

Como um mod é organizado

Um mod pequeno tem três arquivos:

safe-shell/
├── .claude-plugin/
│   └── plugin.json      name, version, description
└── hooks/
    ├── hooks.json       { "modules": ["./register.ts"] }
    └── register.ts      your code

O register.ts exporta uma função, register(on). Cada chamada on(event, matcher, hook) adiciona um hook, e todo hook recebe os mesmos três argumentos.

  • $ é a engine. Tudo o que fica fora do seu código passa por ela: $.ui.toast, $.process.run, $.state, $.model.complete.
  • e é o evento, por exemplo o comando Bash que o Claude está prestes a rodar.
  • next(e) entrega o evento aos outros mods e depois ao Claude Code. Se você retornar sem chamá-lo, seu hook responde sozinho. Se chamar next({ ...e, command }), você muda o que acontece.

O módulo não tem Node nem DOM. É esse limite que permite ao Claude Code listar tudo o que um mod chama antes de ele rodar. Teste em qualquer pasta de mod:

claude plugin validate ./safe-shell

Mod 1: um guard que bloqueia comandos destrutivos

Se você roda o Claude em auto mode ou com bypass permissions, nada o impede antes de um git reset --hard. Este mod recusa três tipos de comando de shell e mantém os arquivos .env fora da conversa.

import type { Register } from 'claude-code'
 
// Shell commands an agent should never run without a human typing them.
const BLOCKED: { pattern: RegExp; reason: string }[] = [
  {
    pattern: /\brm\s+-[a-zA-Z]*[rR][a-zA-Z]*\s+(\/|~|\$HOME)\/?\*?(\s|$)/,
    reason: 'recursive delete of / or the home folder',
  },
  {
    pattern: /\bgit\s+push\b.*(--force\b|--force-with-lease\b|\s-f\b).*\b(main|master)\b/,
    reason: 'force push to main or master',
  },
  {
    pattern: /\bgit\s+reset\s+--hard\b/,
    reason: 'git reset --hard throws away uncommitted work',
  },
]
 
// .env, .env.local, config/.env.production ... but not .env.example.
const isSecretEnvFile = (path: string) =>
  /(^|\/)\.env(\.[^/]+)?$/.test(path) && !/\.(example|sample|template)$/.test(path)
 
export const register: Register = on => {
  on('tool.call', { tool: 'Bash' }, ($, e, next) => {
    const hit = BLOCKED.find(rule => rule.pattern.test(e.command))
    if (hit === undefined) {
      return next(e)
    }
    $.ui.toast(`safe-shell blocked: ${hit.reason}`)
 
    return { deny: `safe-shell: blocked (${hit.reason}). Ask the user to run it themselves.` }
  }).catch(($, e, next) =>
    // Fail closed: if the guard itself breaks, refuse instead of letting the command through.
    next.called ? next(e) : { deny: 'safe-shell: the guard failed, so the command was not run.' },
  )
 
  for (const tool of ['Read', 'Edit', 'Write'] as const) {
    on('tool.call', { tool }, ($, e, next) =>
      isSecretEnvFile(e.file_path)
        ? { deny: `safe-shell: ${e.file_path} holds secrets and stays out of the conversation.` }
        : next(e),
    ).catch(($, e, next) =>
      next.called ? next(e) : { deny: 'safe-shell: the guard failed, so the file was not touched.' },
    )
  }
}

Dois detalhes importam mais do que as regexes.

O guard decide antes de chamar next. Depois que o next roda, o comando já rodou. Um deny retornado depois disso não desfaz nada.

O .catch faz o guard falhar fechado. Quando um hook lança um erro ou estoura o limite de 10 segundos, o Claude Code pula esse hook, e um guard pulado deixa o comando passar. O handler next.called ? next(e) : deny recusa o comando nesse caso. O validate lista cada hook que decide se uma chamada segue e diz se ele tem um .catch. É a primeira coisa a conferir no guard de outra pessoa:

❯ ./register.ts hooks: tool.call{tool=Bash}, tool.call{tool=Read|Edit|Write}
❯ ./register.ts gating hook with .catch: tool.call{tool=Bash}
❯ ./register.ts gating hook with .catch: tool.call{tool=Read|Edit|Write}
❯ ./register.ts calls: $.ui.toast
✔ Validation passed

Teste sem abrir uma sessão

O claude plugin test roda os arquivos *.test.ts de um mod contra a engine, sem sessão, sem login e sem rede. O kit de testes não tem nada abaixo do seu mod, então cada teste registra hooks substitutos para tudo o que o mod repassa:

import { expect, test } from 'claude-code/testing'
 
const ran = { stdout: 'ran', stderr: '', interrupted: false }
 
test('blocks rm -rf on the home folder', async ($, on) => {
  on('tool.call', { tool: 'Bash' }, () => ({ result: ran }))
  const answer = await $.tool.call({ tool: 'Bash', command: 'rm -rf ~' })
  expect(answer.deny).toContain('recursive delete')
})
 
test('lets ordinary commands through', async ($, on) => {
  on('tool.call', { tool: 'Bash' }, () => ({ result: ran }))
  const answer = await $.tool.call({ tool: 'Bash', command: 'rm -rf ./build && python -m pytest -q' })
  expect(answer.deny).toBeUndefined()
})

O arquivo completo tem quatro testes:

(pass) blocks rm -rf on the home folder [16.23ms]
(pass) blocks a force push to main [7.73ms]
(pass) lets ordinary commands through [7.22ms]
(pass) keeps .env out of Read but allows .env.example [9.40ms]

 4 pass
 0 fail

Minha primeira execução falhou com on("tool.call") after the test first called $. Registre os substitutos no começo de cada teste, antes da primeira chamada a $.

O que aconteceu numa sessão ao vivo

Com o hot reload ativado, pedi para o Claude rodar echo "the words git reset --hard inside an echo". O guard recusou com "blocked (git reset --hard throws away uncommitted work)", e apareceu um toast. Esse echo era inofensivo. A comparação por padrões não distingue um comando de um texto que só o menciona, e também deixa passar um comando escondido numa variável, num script ou num alias. Autores japoneses que publicaram guards parecidos, como rafi-guard, delete-guard e board-guard, relatam os dois problemas.

Trate um mod de guard como uma segunda rede de proteção. O que nunca pode acontecer também deve estar numa regra de permissão deny. Fique atento ao sentido contrário também. A documentação oficial diz que, numa máquina pessoal sem configurações gerenciadas, um mod pode aprovar uma chamada que uma regra deny recusa. Os mods não rodam em sandbox. Eles rodam com as suas permissões.

Mod 2: um medidor acima do prompt

A faixa acima do prompt e o painel lateral são onde os mods mais desenham. Na varredura do catálogo de 6 de outubro, 41% dos mods desenham na faixa e 40% abrem um painel. Este mod mostra o tempo, as chamadas de ferramenta e os tokens do último turno, com um botão Hide.

Os valores que um desenho lê ficam em $.state, e você declara cada um num pequeno arquivo de tipos:

// types/index.d.ts, named in plugin.json as "types": "./types/index.d.ts"
export type TurnStats = {
  seconds: number
  tools: number
  inputTokens: number
  outputTokens: number
  model: string | null
}
 
declare module 'claude-code' {
  interface PluginState {
    'turn-meter': { last: TurnStats | null; isHidden: boolean }
  }
}

Os hooks contam as chamadas de ferramenta, leem durationMs e usage de turn.complete e desenham a faixa:

import { atom, read, update } from 'claude-code'
import type { Register } from 'claude-code'
 
import type { TurnStats } from '../types'
 
const last = atom({ plugin: 'turn-meter', key: 'last' } as const, null)
const isHidden = atom({ plugin: 'turn-meter', key: 'isHidden' } as const, false)
 
const formatTokens = (n: number) => (n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n))
 
export const register: Register = on => {
  let tools = 0
 
  on('prompt.submit', ($, e, next) => {
    tools = 0
    return next(e)
  })
 
  on('tool.call', ($, e, next) => {
    // Count the main conversation's calls; subagents carry an agentId.
    if (e.agentId === undefined) tools += 1
    return next(e)
  })
 
  on('turn.complete', async ($, e, next) => {
    if (e.agentId !== undefined) return next(e)
    const usage = e.usage
    const stats: TurnStats = {
      seconds: Math.round(e.durationMs / 1000),
      tools,
      inputTokens: usage
        ? usage.input_tokens + usage.cache_read_input_tokens + usage.cache_creation_input_tokens
        : 0,
      outputTokens: usage?.output_tokens ?? 0,
      model: usage?.model ?? null,
    }
    await update($, last, () => stats)
    if (stats.seconds > 120) $.ui.toast(`That turn took ${stats.seconds}s`)
    return next(e)
  })
 
  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
    const stats = await read($, last)
    if (e.props.hasSurvey || stats === null || (await read($, isHidden))) return next(e)
 
    const { Box, Button, Text } = $.ui.resolve(e)
    const model = stats.model === null ? '' : ` · ${stats.model}`
    // The band is shared by every mod: keep what the mods beneath drew, then add a row.
    const below = await next(e)
 
    return (
      <Box flexDirection="column">
        {below}
        <Box>
          <Text dimColor>
            {`Last turn: ${stats.seconds}s · ${stats.tools} tool calls · ${formatTokens(stats.inputTokens)} in / ${formatTokens(stats.outputTokens)} out${model} `}
          </Text>
          <Button key="hide" label="Hide" onPress={() => update($, isHidden, () => true)} />
        </Box>
      </Box>
    )
  })
}

No teste, tanto no terminal quanto no Desktop, a faixa mostra:

Last turn: 42s · 0 tool calls · 18.2k in / 800 out · claude-opus-5-5 [ Hide ]

Três coisas que aprendi construindo este mod:

  • Guarde os valores desenhados em $.state, não em variáveis do módulo. Um hot reload roda o register de novo e zera suas variáveis, mas o $.state sobrevive. O /clear recomeça do zero, então grave em $.store no session.end se um valor precisar durar mais do que isso.
  • A faixa é compartilhada. Chame next(e) e coloque o resultado dentro do seu Box, senão você esconde a linha de todos os outros mods. Um autor do note.com perdeu uma faixa para outro mod antes de descobrir isso.
  • Elementos Text não guardam key. Nos testes, encontre-os pelo texto que exibem: ui.find({ type: 'Text', text: /Last turn/ }).

Mod 3: /pyenv, para quando o Claude roda o Python errado

Fui atrás de mods para ciência de dados e encontrei uma lacuna. Dos 2.690 mods da varredura de 6 de outubro, nenhum menciona Jupyter, pandas, DataFrames, Polars, venv ou conda no nome ou na descrição.

O problema por trás deste mod é comum em trabalho com dados. A ferramenta Bash do Claude roda o python3 que aparecer primeiro no seu PATH, e muitas vezes esse não é o ambiente do seu projeto. Veja o que a verificação imprimiu na minha máquina:

python: /Users/<you>/.local/bin/python3 (3.14.2)
env: none (system or tool-managed Python)
pandas: 3.0.1
numpy: 2.4.2
polars: not installed
matplotlib: 3.11.0
pygwalker: not installed

Nenhum ambiente virtual estava ativo, então um pip install feito pelo Claude teria ido para um interpretador global.

O comando /pyenv roda essa verificação e responde em duas partes. text é a linha que você vê. context é uma nota que só o modelo lê, assim as próximas chamadas Bash do Claude já sabem qual interpretador está em uso, sem você precisar escrever outro prompt.

import type { Register } from 'claude-code'
 
// Reads package versions from metadata instead of importing them, so it stays fast.
const PROBE = `
import os, sys
from importlib.metadata import PackageNotFoundError, version
env = os.environ.get("VIRTUAL_ENV") or os.environ.get("CONDA_PREFIX") or "none (system or tool-managed Python)"
print(f"python: {sys.executable} ({sys.version.split()[0]})")
print(f"env: {env}")
for name in ("pandas", "numpy", "polars", "matplotlib", "pygwalker"):
    try:
        print(f"{name}: {version(name)}")
    except PackageNotFoundError:
        print(f"{name}: not installed")
`
 
export const register: Register = on => {
  on('session.start', async ($, e, next) => {
    await $.command.register({
      name: 'pyenv',
      description: "Show which Python, environment and data packages this session's shell uses",
    })
    return next(e)
  })
 
  on('command.run', { command: 'pyenv' }, async $ => {
    try {
      const probe = await $.process.run(['python3', '-c', PROBE], { timeoutMs: 15_000 })
      if (probe.exitCode !== 0) {
        return { text: `pyenv: python3 exited with ${probe.exitCode}: ${probe.stderr.trim().slice(0, 300)}` }
      }
      const report = probe.stdout.trim()
      // `text` is the row you see; `context` is a note only the model reads.
      return {
        text: report,
        context: [`Python environment of this session's shell, from /pyenv:\n${report}`],
      }
    } catch (error) {
      return { text: `pyenv: could not run python3 (${String(error).slice(0, 200)})` }
    }
  })
}

O slash command de um mod roda sua função na hora, sem turno do modelo, mesmo com o Claude ocupado. O $.process.run recebe uma lista de argumentos, sem shell, e expira depois de 30 segundos, a menos que você defina timeoutMs.

O $.process.run enxerga o mesmo PATH da ferramenta Bash do Claude? Um autor da comunidade notou que o node do nvm não aparecia nos processos de um mod, então conferi com um mod temporário de verificação. Na minha sessão do Desktop, um $.process.run simples recebeu exatamente o PATH da ferramenta Bash e o mesmo python3. Rodar a verificação por um login shell, com zsh -lc, deu a resposta errada. Ele encontrou o 3.10.9 do python.org, porque um login shell não interativo pula o ~/.zshrc, onde fica a maior parte das adições ao PATH. Fique com a chamada simples. Se o resultado parecer estranho na sua máquina, compare com !which python3 digitado no prompt do Claude Code.

Testar esse mod revelou mais uma armadilha. As chamadas em $, como $.process.run e $.command.register, também precisam de substitutos, e um substituto para uma chamada a $ responde { value: ... }. Se você retornar o resultado puro, o kit recusa.

Se a maior parte da sua análise acontece em notebooks, e não em scripts, isso só ajuda até certo ponto, porque o Claude Code edita arquivos .ipynb como JSON e nunca vê o kernel em execução. O RunCell (opens in a new tab) é um agente para notebooks que roda células e lê a saída delas diretamente, por isso serve melhor para esse tipo de trabalho.

Deixe o Claude escrever o mod

Você não precisa escrever nada disso à mão. Peça numa sessão, por exemplo "crie um mod que mostre meu uso de 5 horas acima do prompt". O Claude carrega a skill embutida plugin-authoring e grava os arquivos em ~/.claude/dev-mods/<session-id>/. O primeiro arquivo dispara uma única pergunta, "Enable hot reloading for this session?". Depois que você aceita, o Claude Code recarrega cada edição quando o turno do Claude termina. Foi assim que criei e carreguei os três mods acima.

O que a documentação e a comunidade acrescentam:

  • Copie a pasta para um lugar permanente. Autores no Qiita e no Zenn relatam que as pastas de dev-mods são apagadas junto com as sessões antigas depois de cerca de 30 dias.
  • Desenvolva com claude --plugin-dir ./my-mod. Um mod instalado roda uma cópia em cache, então editar a pasta dele não muda nada até você atualizar o plugin.
  • O app Desktop não aceita flags. Defina CLAUDE_CODE_PLUGIN_DIRS no bloco env do ~/.claude/settings.json. As configurações de projeto não valem para isso.
  • Rode /plugin. Uma linha esmaecida como 1 mod active · safe-shell confirma que o mod carregou.
  • Comece com claude --debug enquanto desenvolve. O log de debug aponta cada hook pulado e cada desenho que a engine recusou.

15 mods da comunidade que vale a pena estudar

O catálogo awesome-claude-code-mods (opens in a new tab), com 316 estrelas, varreu 2.690 mods públicos em 1.265 repositórios no dia 6 de outubro, cinco dias depois do lançamento. Os dados da varredura mostram o que as pessoas constroem:

  • 68% adicionam um slash command
  • 53% interceptam chamadas de ferramenta
  • 41% desenham acima do prompt, 40% abrem um painel
  • 40% iniciam processos, 12% chamam um modelo, 11% usam a rede

Estes 15 mostram a variedade. As estrelas são de 7 de outubro de 2026.

ModO que fazEstrelasPor que ler
terminal-browser (opens in a new tab)Um navegador web ao lado da conversa para sites, previews de HTML local e pull requests3.695O painel mais ambicioso até agora
claude-image-view (opens in a new tab)Miniaturas das imagens coladas acima do prompt, no lugar de [Image #1]160Desenhar imagens no terminal
hamzafer/claude-code-mods (opens in a new tab)Um conjunto com barra de contexto, guard de blast radius, preview de Markdown e painel de subagents138Vários tipos de mod num só repositório
claude-auto-handoff (opens in a new tab)Passa uma sessão longa para uma sessão nova com um resumo estruturado60Gerenciamento de contexto
prismantis (opens in a new tab)Respostas com tema: tabelas, código, gráficos em arte de caracteres, texto da direita para a esquerda49Mudar o visual das próprias mensagens do Claude
cc-arcade (opens in a new tab)Nove jogos acima do prompt que pausam quando o Claude termina41Animação com um relógio de quadros
jev-permission-gate (opens in a new tab)Um modelo de decisão Jev julga as chamadas de ferramenta no auto mode28Uma seção de privacidade cuidadosa: ele envia suas três últimas mensagens, com até 1.500 caracteres cada, para a API da TypeSafe
prompt-rail (opens in a new tab)Uma barra com seus prompts anteriores; passe o mouse para ler, clique para ir até ele22Destaque da análise de mods em japonês mais curtida no Zenn
claude-paste-view (opens in a new tab)Prévia de imagens coladas e de textos longos colados18Código pequeno e fácil de ler
claude-gfm-render (opens in a new tab)Alertas do GitHub, listas de tarefas e Mermaid nas respostas, em arte de caracteres ou SVG14Desenhar de um jeito diferente em cada superfície
claude_qamods (opens in a new tab)O qa-guide explica as perguntas e as opções do Claude num painel lateral10Melhorar um diálogo nativo
CC-Usage-Band (opens in a new tab)Limites de 5 horas e de 7 dias, contexto e taxa de acerto do cache acima do prompt10O tipo de mod mais comum: um medidor
harness-scope (opens in a new tab)Perfis por repositório que escondem skills, agents e regras globais1O autor mediu a lista de skills caindo de 98 para 49 entradas
touch-map (opens in a new tab)Mostra quais arquivos o Claude listou, leu, editou ou criou0O autor viu que o Claude mexeu em 125 de 304 arquivos durante um único levantamento para refatoração
claude-mods-router (opens in a new tab)Encaminha cada prompt para um nível de esforço com $.model.classify0O artigo no Qiita, com 26 curtidas, observa que trocar de modelo quebra o cache de prompt

A Anthropic também publica três exemplos no claude-code-playground (opens in a new tab): token-weather, blast-radius e replay-theater. O código-fonte dos mods embutidos, entre eles o /diff, está no repositório claude-code (opens in a new tab).

Boas práticas que a comunidade adotou

Na primeira semana, só os autores japoneses publicaram cerca de 50 posts com mods funcionando, medições e relatos de falhas. Estes são os hábitos que mais se repetiram.

  1. Leia um mod antes de instalar. Clone o repositório, rode claude plugin validate e leia as linhas hooks: e calls:. Leia o código-fonte onde aparecer $.process, $.http, $.fs.write, $.env.get ou $.model. Rode a validação de novo a cada atualização. Passar na validação significa que a engine consegue carregar o código, não que o código é seguro.
  2. Guards decidem antes do next e falham fechados. Mods que só observam devem falhar abertos, com .catch(($, e, next) => next(e)), para que um bug num medidor nunca bloqueie seu trabalho.
  3. Espere dentro das chamadas a $. Um hook tem 10 segundos de tempo próprio. Um $.process.run ou um $.ui.ask em andamento não conta nesse limite, mas as suas próprias promises contam.
  4. Nunca guarde nem desestruture $. Passe o $ só para funções declaradas no nível superior do arquivo. Vários autores tinham mods que falhavam ao carregar sem nenhum aviso até corrigirem isso.
  5. Cuidado com o cache de prompt. Trocar de modelo no meio da sessão, ou mudar o system prompt entre requisições, joga o cache fora.
  6. Trate cada e.surface separadamente. Svg só desenha no app Desktop. Raster e Image só desenham no terminal.
  7. Fixe uma versão para uso em equipe. A API está em acesso antecipado e muda entre versões. Cinco das seis versões lançadas depois da estreia, da 2.1.288 à 2.1.293, mudaram ou corrigiram o comportamento dos mods.

Mascarar segredos é a história que serve de alerta. Um autor do note.com criou um mod que trocava as chaves de API na saída das ferramentas antes que o Claude as visse. Mesmo assim, o Claude imprimiu os valores reais ao depurar com od -c uma edição que falhou, e um Write do arquivo inteiro gravou os placeholders por cima das chaves verdadeiras. Só uma regra de permissão deny no arquivo resistiu. Um mod que muda o que aparece na tela não esconde nada do modelo.

Problemas comuns

SintomaCausa provávelSolução
O /plugin não lista o modPasta não confiável, --safe-mode, --bare ou disableAllHooksMarque a pasta como confiável e reinicie sem a flag
hooks modules are turned off in this processA Anthropic desligou remotamente os mods instaladosNão há nada para mudar na sua máquina. Atualize, porque a 2.1.289 e a 2.1.290 corrigiram dois casos em que os mods continuavam desligados
O validate falha com "expected record, received undefined"Um CLI antigo aparece antes no seu PATHRode claude --version e atualize
Um hook é pulado sem erro visívelEle lançou um erro, por exemplo ao chamar $.plugin.name(), que é uma propriedadeRode claude --debug e leia a linha do hook pulado
Um painel nunca abreUm painel que abre sem você pedir espera a janela ter 144 colunas, só fica ao lado da transcrição no layout em tela cheia, e o /diff pode cobri-loAumente a largura da janela, teste o layout em tela cheia, feche o /diff
Funciona no terminal, mas não no DesktopO Desktop traz a própria versão, e alguns elementos só existem no terminalConfira o /status na aba Code e trate cada e.surface separadamente
Nenhuma UI de mod no VS Code ou no claude -pEssas superfícies não desenhamUse como alternativa uma linha na transcrição ou o texto de um comando
Um teste falha com "nothing beneath the plugins answers"O kit de testes não tem engineAdicione hooks substitutos e responda às chamadas a $ com { value }

Compartilhe seu mod

Coloque um marketplace.json ao lado do plugin.json, dentro de .claude-plugin/:

{
  "name": "my-mods",
  "owner": { "name": "you" },
  "plugins": [{ "name": "safe-shell", "source": "./" }]
}

Faça push da pasta para o GitHub. Depois disso, qualquer pessoa pode instalar o mod numa sessão no terminal:

/plugin install safe-shell --marketplace you/safe-shell

No app Desktop, em sessões locais e SSH, o caminho é +, depois Plugins, depois Add plugin. Se você adicionar o tópico claude-code-mod ao repositório, o catálogo da comunidade costuma incluir o mod poucas horas depois do seu próximo push.

FAQ

Guias relacionados