TL;DR Con la 2.1.287 o posterior, pide
make a mod that shows the current git branch above the prompt, elige Enable for this session y lo tienes al acabar el turno. Antes de instalar uno ajeno,claude plugin validatete dice qué toca.
Un mod es un plugin de Claude Code escrito en JavaScript o TypeScript cuyas funciones corren dentro de Claude Code. Puede dibujar una línea encima del prompt o un panel junto a la conversación, añadir un comando que responde al momento sin gastar un turno de Claude, y frenar, reescribir o responder una tool call antes de que se ejecute. Funciona en el terminal desde la 2.1.287 y en la pestaña Code de Desktop desde la 2.1.286.
Para cualquiera con curiosidad que use Claude Code como harness, esto es un sueño: con TypeScript puedes añadir botones, paneles, vistas y animaciones, y capturar comandos y subagentes. La documentación es extensa y algo abstracta, y sus ejemplos son sencillos a propósito. Por eso lo he probado con algo real: una barra de estado para craft, mi plugin de desarrollo.
Dónde encaja un mod
| Qué es | Dónde corre | |
|---|---|---|
| Hook de settings | Un comando de shell, una petición HTTP o un prompt que se dispara en un evento | Fuera de Claude Code |
| Skill | Un markdown con instrucciones | En lo que Claude lee |
| MCP | Un servidor que le da herramientas a Claude | Fuera, como proceso o servicio aparte |
| Mod | Funciones que Claude Code llama en cada evento | Dentro de Claude Code |
Como vive dentro, cada hook de un mod decide qué pasa con su evento: lo observa y lo deja pasar, lo reescribe antes de que siga, o lo responde él y el comportamiento normal no llega a ejecutarse. Si dudas entre el resto de mecanismos, los 6 mecanismos de extensión los separa por la pregunta que responde cada uno.
Pídele un mod a Claude
1. Comprueba la versión
claude --version
2. Descríbelo en una frase
make a mod that shows the current git branch above the prompt
Claude trabaja con la skill integrada plugin-authoring (también la puedes cargar tú con /plugin-authoring) y escribe el mod en ~/.claude/dev-mods/<id-de-sesión>/. En los modos default y acceptEdits te pide aprobar cada archivo, porque ~/.claude es una ruta protegida.
3. Activa la recarga en caliente
Cuando Claude guarda el primer archivo, Claude Code pregunta si activa la recarga para la sesión. Elige Enable for this session: el mod se carga al acabar el turno y se recarga cada vez que Claude lo cambia. Lo ves en /plugin, pestaña Installed.
4. Consérvalo
La carpeta de la sesión se borra con el tiempo. Copia el mod fuera y cárgalo donde quieras:
claude --plugin-dir ~/mods/git-branch
Este flujo es interactivo y no lo he capturado aquí: los pasos y los nombres salen de la guía oficial.
Un caso real: la barra de craft
Craft lanza subagentes que construyen por fases y yo los dejo trabajando. Quería saber de un vistazo si algo se mueve, sin preguntarle a Claude y sin gastar un turno. El diseño es una línea encima del prompt con la tarea, su fase, un cuadrado por slice y el agente que corre ahora:
craft retry · implement · ■■■▣▣□ 3/6 · ⠋ draw 2:14 +1
Son cinco hooks en un solo archivo, hooks/register.ts, que hooks/hooks.json declara con { "modules": ["./register.ts"] }:
command.runcon/^craft:/apunta la fase cuando lanzo/craft:implementy deja que la skill siga como siempre.agent.spawncon/^craft:/añade el agente a la línea, yturn.completecon el mismoagentIdlo quita y marca su slice como construida.ui.renderenAbovePromptdibuja la línea conBoxyText, encima de lo que Claude Code ya pinta ahí./craft:bar offlo responde el propio mod, sin turno de Claude, y guarda la elección en$.storepara todas las sesiones.session.endvacía el estado al cerrar la sesión.
on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
const line = pieces(state, await $.clock.now())
if (e.props.hasSurvey || line.length === 0 || (await hidden($))) return next(e)
const { Box, Text } = $.ui.resolve(e)
const below = await next(e)
const texts = line.map(piece => Text({ ...STYLES[piece.tone], children: piece.text }))
return Box({ flexDirection: 'column', children: [Box({ key: BAR, children: Text({ children: texts }) }), below] })
})
El primer try real, en la 2.1.292, mostró esto mientras craft construía cuatro slices:
craft gamma · implement · □□□□ 0/4
Pasaron la tarea, la fase, los cuatro cuadrados, /craft:bar off y on, y que la barra no dibuje encima de la encuesta de Claude Code. Fallaron tres cosas: todos los agentes salían como build, porque el nombre de la slice va más abajo en su prompt; dos agentes lanzados en la misma décima de segundo se pisaban y no aparecía el +1; y los cuadrados nunca se ponían verdes, porque la primera versión los marcaba por el comando de su check y craft reescribe esos comandos. La lección: los eventos te dicen con certeza cuándo empieza y acaba un subagente; lo que va dentro de su prompt, no. La barra todavía vive en una rama de trabajo, no en la versión publicada de craft.
Antes de instalar uno ajeno
Un mod no tiene sandbox: corre con tus permisos, puede leer tus secretos, ver cada prompt y aprobar tool calls por ti. claude plugin validate lista qué eventos maneja y qué llamadas hace, sin ejecutarlo. Esta es la salida real sobre la barra de craft:
❯ ./register.ts hooks: command.run{command=/"^craft:"/}, agent.spawn{subagentType=/"^craft:"/}, turn.complete, session.end, ui.render{component=AbovePrompt}
❯ ./register.ts calls: $.clock.every (via tick), $.clock.now, $.fs.list (via folders), $.fs.read (via readSlices), $.session.root (via folders, readSlices), $.store.get (via hidden), $.store.set (via answerBar), $.ui.invalidate, $.ui.resolve
✔ Validation passed
Dos datos más: en el panel de chat de la extensión de VS Code y en claude -p los hooks corren, pero no se dibuja nada. Y /diff, que quizá ya usas, es un mod integrado: cc-plugin-diff.
Documentación oficial: Mods overview