Mods en Claude Code: qué son y cómo crear el tuyo
Los mods son funciones de JavaScript o TypeScript que cambian cómo se ve y cómo se comporta Claude Code: reescriben prompts, bloquean comandos o dibujan paneles. Te explico qué son, en qué se diferencian de los hooks y cómo crear uno.
- Javi Mata
- 11 min de lectura
Tabla de contenido
- Mods y hooks: la diferencia
- Requisitos y dónde funcionan
- Cómo es un mod por dentro
- Crea tu primer mod
- Los tres argumentos de cada hook
- Un caso práctico: bloquear un git push --force
- Pídele a Claude que escriba el mod
- Valida y prueba tu mod
- Instalar mods de otros (y la advertencia de seguridad)
- Mods integrados y uso en equipos
- Mi recomendación para empezar
- Fuentes
Anthropic presentó los mods de Claude Code el 1 de octubre de 2026. Un mod es un conjunto de funciones en JavaScript o TypeScript que Claude Code ejecuta cuando ocurre un evento (una llamada a una herramienta, un prompt enviado o una parte de la interfaz que se dibuja) y que pueden observar el evento, cambiarlo o resolverlo por su cuenta. Con eso puedes añadir funciones propias, como un panel, un comando nuevo o una regla que filtre llamadas a herramientas.
Si todavía no usas Claude Code, empieza por la guía de inicio. Si ya conoces los hooks, los mods te van a sonar parecidos, pero hacen cosas que los hooks no pueden.
Mods y hooks: la diferencia
Los hooks de siempre son comandos de shell, peticiones HTTP o prompts que configuras en un archivo de ajustes. Los mods son funciones que corren dentro de Claude Code. La documentación oficial llama “hook” a ambos tipos, y para distinguirlos usa “settings hook” para el de siempre. Yo hago lo mismo en este artículo.
Según la documentación, un mod puede:
- Dibujar una interfaz que puedes usar: un panel junto a la conversación o una banda sobre el prompt, con pestañas, botones y campos de texto.
- Redibujar partes de la interfaz de Claude Code, como la fila de una llamada a herramienta, el spinner o el diálogo de preguntas.
- Intervenir en una llamada a herramienta o en una petición: pausarla para preguntarte algo, responderla sin ejecutar la herramienta o enviar una petición a otro modelo.
- Ejecutar tu código con un
/comandopropio, sin pasar por un turno de Claude. - Compartir datos entre hooks: lo que registra un hook lo puede mostrar otro.
Esta tabla resume la comparación que hace la documentación oficial:
| Mod | Settings hook | Skill | Servidor MCP | |
|---|---|---|---|---|
| Qué es | Funciones en un plugin que Claude Code llama en su propio proceso | Un comando, petición HTTP o prompt que se ejecuta en un evento del ciclo de vida | Un archivo SKILL.md con instrucciones que Claude lee | Un proceso o servicio externo que da herramientas a Claude |
| Puede dibujar en la interfaz | Sí | No | No | No |
| Qué escribes | JavaScript o TypeScript | Un script y una entrada en settings.json | Markdown | Un servidor en cualquier lenguaje |
| Elígelo cuando | Quieres un panel, una banda sobre el prompt, un comando propio o reescribir un evento | Quieres bloquear, permitir o registrar un evento con un script que ya tienes | Pegas siempre las mismas instrucciones en el chat | Claude necesita llegar a un sistema externo |
Si un settings hook, un skill o un servidor MCP ya hacen lo que necesitas, la documentación recomienda compararlos antes de escribir un mod. Mi lectura: si lo tuyo es “ejecutar un script cuando pase X”, sigue con los hooks; si quieres cambiar o dibujar algo dentro de Claude Code, es un mod. Para dar instrucciones a Claude, un skill; para conectarlo a un sistema externo, un servidor MCP.
Requisitos y dónde funcionan
Los mods requieren Claude Code v2.1.287 o posterior y vienen activados por defecto. Revisa tu versión con:
claude --version
Los hooks de un mod se ejecutan en cualquier tipo de sesión que cargue el plugin, pero dibujar es más limitado: solo la terminal y la app de escritorio (pestaña Code) muestran los paneles, bandas y filas reemplazadas de un mod. En el panel de chat de la extensión de VS Code, en claude -p y en sesiones en la nube, los hooks corren pero lo que dibuja el mod no aparece.
Cómo es un mod por dentro
Un mod es un plugin con un archivo de entrada llamado hooks module. La versión más pequeña tiene tres archivos:
first-mod/
├── .claude-plugin/
│ └── plugin.json
└── hooks/
├── hooks.json
└── register.js
plugin.json: el manifiesto del plugin.hooks.json: apunta a tu archivo de código con la clavemodules.register.js: tu código. Exporta una funciónregister.
No necesitas Node.js, un bundler ni un paso de compilación: Claude Code carga los archivos .js y .ts directamente.
Crea tu primer mod
Este es el ejemplo de la documentación oficial. Cuenta las llamadas a herramientas que hace Claude, muestra el número junto al spinner y añade un comando /tally que lo imprime.
1. Crea las carpetas:
mkdir -p first-mod/.claude-plugin first-mod/hooks
2. Escribe el manifiesto en first-mod/.claude-plugin/plugin.json:
{
"name": "first-mod",
"version": "0.1.0",
"description": "Counts Claude's tool calls, shows the count beside the spinner, and adds a /tally command",
"author": { "name": "Your Name" }
}
3. Dile a Claude Code dónde está tu código en first-mod/hooks/hooks.json. Tener la clave modules es lo que convierte el plugin en un mod:
{
"description": "The first-mod hooks module",
"modules": ["./register.js"]
}
4. Escribe el código en first-mod/hooks/register.js:
// The count, shared by the hooks below
let calls = 0
// Claude Code calls this once when the mod loads
export function register(on) {
// Runs when the session starts, before your first prompt
on('session.start', async ($, e, next) => {
// Add the /tally command
await $.command.register({
name: 'tally',
description: 'Show how many tool calls Claude has made',
})
// Let the session start as usual
return next(e)
})
// Runs each time Claude is about to use a tool
on('tool.call', async ($, e, next) => {
calls += 1
// Ask Claude Code to draw the interface again, so the new count shows
$.ui.invalidate('ui.render')
// Let the tool run as usual
return next(e)
})
// Runs when you type /tally, and only then, because of the matcher
on('command.run', { command: 'tally' }, async () => {
// The text to print in the transcript
return { text: 'Claude has made ' + calls + ' tool calls since this mod loaded' }
})
// Runs each time Claude Code draws the spinner
on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
// Keep Claude Code's spinner, with the count added after its word
return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
})
}
5. Cárgalo durante una sesión, sin instalarlo, con --plugin-dir:
claude --plugin-dir ./first-mod
Pídele a Claude algo que requiera varias herramientas, por ejemplo list the files here and read the README. El spinner mostrará algo como Thinking · tool calls: 2…, y al terminar puedes escribir /tally. Si cambias el código mientras la sesión está abierta, Claude Code recarga el módulo (al recargar, el contador vuelve a 0).
Los tres argumentos de cada hook
Cada función que pasas a on recibe los mismos tres argumentos:
$: la API de mods, con los métodos para salir de tu propio código ($.ui,$.command, etc.).e: el evento, como datos planos (por ejemplo, el nombre de una herramienta y sus argumentos).next: pasa el evento a los demás mods y luego al comportamiento de Claude Code, y devuelve el resultado.
Con eso, un hook puede hacer tres cosas: observar (llama a next(e) sin cambios), reescribir (llama a next con una copia modificada, como hace el hook del spinner) o responder (devuelve su propio resultado sin llamar a next, como hace el comando /tally).
Un caso práctico: bloquear un git push --force
La documentación incluye este ejemplo de un hook tool.call que rechaza un push forzado y le explica a Claude por qué. El segundo argumento de on, { tool: 'Bash' }, es un filtro: el hook solo corre para llamadas a Bash.
// The matcher limits the hook to Bash calls, so e.command is the shell command
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
if (/git push .*--force/.test(e.command)) {
// Returning without calling next answers the event, so the command never runs
return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }
}
// Every other command goes on to the permission check and then to Bash
return next(e)
})
Claude lee el texto de deny como el resultado de la herramienta, así que conviene escribirlo como una instrucción que pueda seguir. Si quieres un ejemplo con pausa y botones, la documentación incluye uno que usa $.ui.ask para preguntarte antes de ejecutar comandos como rm -rf.
Para avisos, la API tiene $.ui.toast(text), que muestra una notificación arriba a la derecha durante 4 segundos por defecto, y $.ui.status(text), una línea bajo el prompt que se queda hasta que la cambies.
Pídele a Claude que escriba el mod
No tienes que escribirlo a mano. Según la documentación, puedes describir el mod en una sesión interactiva (por ejemplo, make a mod that shows the current git branch above the prompt) y Claude lo escribe usando un skill integrado llamado plugin-authoring. También puedes cargarlo tú con /plugin-authoring.
Algunos detalles que conviene conocer:
- Claude escribe el mod en
~/.claude/dev-mods/seguido del ID de la sesión. En los modos de permisodefaultyacceptEditste pide aprobar cada archivo, porque~/.claudees una ruta protegida. - Al guardar el primer archivo, Claude Code pregunta si activas la recarga en caliente para esa sesión. Si aceptas, el mod carga al terminar el turno y se recarga en cada turno que lo cambie.
- Ese mod solo carga en la sesión que lo creó, y Claude Code borra la carpeta cuando es más vieja que
cleanupPeriodDays. Para conservarlo, copia su carpeta a otro lugar (por ejemplo~/mods/git-branch) y cárgalo conclaude --plugin-dir ~/mods/git-branch.
Si quieres entender mejor cómo se aprueban las acciones de Claude, mira el artículo de permisos y modos de permiso.
Valida y prueba tu mod
La documentación ofrece dos comandos para revisar un mod:
claude plugin validate ./first-mod
Revisa el manifiesto y analiza el código sin ejecutarlo. En su salida, la línea hooks: lista los eventos que maneja el mod y la línea calls: lista los métodos de la API que llama. También sirve para revisar un mod ajeno antes de instalarlo.
claude plugin test
Ejecuta, desde la carpeta del mod, los archivos que terminan en .test.ts o .test.tsx, sin sesión, sin iniciar sesión y sin red. El tutorial oficial incluye un test de ejemplo para first-mod.
Además, cada vez que cargas un mod desde --plugin-dir, Claude Code escribe archivos de tipos .d.ts en .claude-plugin/types/ con los eventos y métodos exactos de tu versión, para que tu editor autocomplete. La propia documentación advierte que los eventos y métodos pueden cambiar entre versiones, y que ante cualquier diferencia debes confiar en esos archivos antes que en la página.
Instalar mods de otros (y la advertencia de seguridad)
Un mod se instala como cualquier plugin, con el nombre del plugin, una @ y el nombre del marketplace:
/plugin install token-chart@your-org
Ese ejemplo es el de la documentación, con nombres de muestra. Para ver los mods activos de una sesión, ejecuta /plugin.
Un mod es código que corre con tus permisos. Puede leer y escribir tus archivos, lanzar procesos, hacer peticiones de red, leer variables de entorno (incluida una API key), ver cada prompt y cada llamada a herramienta, y aprobar una llamada antes de que te pregunten. No corre en un sandbox, y un proceso que lance un mod queda fuera del sandbox de Claude Code. Instala solo mods de autores y marketplaces en los que confíes.
Anthropic comparte tres mods de muestra, sin soporte, en el repositorio claude-code-playground:
token-weather: dibuja un pronóstico de tu ventana de contexto sobre el prompt.blast-radius: detiene un comando de shell riesgoso, comorm -rfo un force push, y muestra qué cambiaría, con botones para continuar o cancelar.replay-theater: añade un comando/replayque recorre las ediciones de archivos del último turno.
Para probar uno, clona el repositorio y cárgalo con --plugin-dir.
Mods integrados y uso en equipos
Algunas funciones de Claude Code ya son mods. El ejemplo que menciona Anthropic es /diff: como ahora es un mod, puedes desactivarlo en /plugin o reemplazarlo por tu propia versión. Anthropic indica que planea mover más funciones integradas a mods con el tiempo.
Para equipos, los mods viajan en plugins, así que aplican los controles de plugins que ya existen. En planes Team y Enterprise, y en cualquier máquina con managed settings, carga primero un mod integrado llamado sec-default que impide que los mods instalados por los usuarios hagan cosas riesgosas, como saltarse tus reglas deny. La administración detallada está en Manage mods for your organization.
Mi recomendación para empezar
Esto es opinión mía, no de la documentación:
- Actualiza Claude Code y confirma que tienes la v2.1.287 o posterior.
- Haz el tutorial de
first-modtal cual: toma pocos minutos y te enseña observar, reescribir y responder. - Antes de instalar cualquier mod ajeno, corre
claude plugin validatey lee las líneashooks:ycalls:. - Si lo tuyo es solo “ejecutar un script cuando pase algo”, los hooks de siempre siguen siendo la opción más simple.
Fuentes
Etiquetas:
Compartir: