TL;DR
- Un Mod de Claude Code son tres archivos:
.claude-plugin/plugin.json,hooks/hooks.jsoncon{"modules":["./index.ts"]}, y un módulo TypeScript que exportaregister(on). No hace falta nada más para cargarlo. - En la build 2.1.272, la superficie tipada que escribe
/plugin-typesson 11,783 líneas declaude-code.d.ts: 84 nombres de eventos o llamadas repartidos en 23 sustantivos.fs.readFileya no existe, el sustantivo esfs.readyfs.write. - Un hook
tool.callde 42 líneas hizo que el modelo leyeraAPI_KEY=[REDACTED]en lugar de la clave real, tanto con la herramienta Read como con Bash, a 27.9 ms por salto sano y unos 0 tokens añadidos a la sesión. - Un hook que duerme más allá del presupuesto de 10 s o lanza una excepción se omite y se ejecuta el comando que hay debajo. El log lo dice, pero el efecto es un bypass: un Mod de guardia falla en abierto.
- El camino generado funciona: una frase produjo un Mod de 190 líneas más 53 líneas de tests en unos 4 minutos y $1.23, y pasó
claude plugin validatesin avisos yclaude plugin testcon 4 pass / 0 fail. - Una cosa no se reprodujo: el Mod cargó con
claude -ppero se quedó mudo en un REPL interactivo manejado por pty, en dos intentos. Considera la carga en REPL como no verificada hasta que la pruebes en una terminal real.
Qué dicen las mediciones
Todo lo siguiente se ejecutó en Claude Code 2.1.272 con CLAUDE_CODE_ENABLE_FUNCTION_HOOKS activado, sobre un Mod escrito a mano llamado redact-secrets y sobre tres Mods desechables construidos para romperlo. La funcionalidad se sigue en el issue de propuesta de Function Hooks, que sigue siendo lo más parecido a una especificación oficial s3.
Las herramientas existen antes que la documentación. La build 2.1.272 incluye claude plugin validate, test, eval y details; test funciona aunque plugin --help no lo liste en su bloque de comandos s3. Ejecutar /plugin-types dentro de una sesión escribió 11,783 líneas en .claude/types/claude-code.d.ts, más un claude-code-mcp.d.ts de 3,438 líneas que cubre 150 herramientas MCP de 7 servidores s3. Al contar los tipos generados salen 84 nombres de eventos o llamadas repartidos en 23 sustantivos, y el archivo renombra algo de lo que quizá leíste en posts de septiembre: fs.readFile ya no existe, la superficie es fs.read y fs.write s9. Los mismos tipos dicen que un hook tool.call devuelve { result, context? } o { deny }; text y ref vienen del core y no forman parte de la respuesta propia del hook, así que se reescribe result, no text s3.
claude plugin validate imprime una huella antes de que el Mod llegue a ejecutarse: ./index.ts hooks: tool.call y ./index.ts calls: $.ui.toast, o calls: nothing on $ cuando el módulo no toca ninguna capacidad del host s4. Esta línea estática es la única revisión que un directorio como awesome-claude-code-mods puede automatizar hoy, algo que importa para el siguiente párrafo.
La redacción funciona en modo -p. El hook de 42 líneas interceptó tool.call, y el modelo recibió API_KEY=[REDACTED] donde el archivo y la salida del shell contenían sk-test1234567890abcdef, tanto con la herramienta Read como con Bash s3. El log de debug midió un salto sano en 27.9 ms de ida y vuelta, incluidos el salto al worker y next() s3. claude plugin details valoró el Mod en unos 0 tokens añadidos a cada sesión: un Mod es código en el proceso, no texto de prompt, que es el principal argumento de sus promotores frente a los hooks de shell y los skills s7.
La guardia falla en abierto. Un Mod slow-guard que duerme 15 s se cortó al llegar al presupuesto de 10 s con hook failed: slow-guard: exceeded 10000ms budget (tool.call; skipped; what is below it ran in its place), y echo hi se ejecutó igualmente s3. Un Mod throw-guard que lanza una excepción se omitió de la misma forma, hook failed: throw-guard: boom (tool.call; skipped; what is below it ran in its place), con 574.2 ms reportados s3. Ruidoso en el log, esquivado en la práctica. Cualquier Mod cuyo trabajo sea bloquear algo debe leerse con esto en mente: un bug en la guardia es un agujero, no un crash.
Generar es barato. A partir de una sola frase, el modelo escribió un Mod funcional de 190 líneas más 53 líneas de tests en unos 4 minutos, 34 turnos y $1.23 (19,053 tokens de salida, 497,282 de lectura de caché, 8,357 de razonamiento) s3. Ese Mod pasó claude plugin validate sin avisos y claude plugin test con 4 pass / 0 fail en 0.31 s, y ocultó las claves en vivo s3. En el Mod escrito a mano, claude plugin test corrió sin clave de API y sin llamada al modelo: 1 pass en 0.25 s s3. Ya existe un skill que enseña a los agentes a escribir Mods si quieres repetir esto con una plantilla s12.
Lo que no se reprodujo: $.ui.toast nunca se mostró porque el Mod no cargó en el REPL manejado por pty en 2 intentos; en -p el equivalente solo apareció como una línea de debug. Se observó lo contrario de la afirmación "solo en REPL" que circula en X, y no se aisló la causa raíz s8. Tampoco se probó el heartbeat de 5 s del worker bloqueado; solo se midieron el presupuesto de espera de 10 s y el camino de la excepción.
Mediciones
| Caso | Qué hace el Mod | Resultado | Tiempo |
|---|---|---|---|
| redact-secrets, herramienta Read | Reescribe result en tool.call |
El modelo ve API_KEY=[REDACTED] |
27.9 ms por salto |
| redact-secrets, herramienta Bash | Mismo hook, salida del shell | El modelo ve API_KEY=[REDACTED] |
27.9 ms por salto |
| slow-guard | Duerme 15 s dentro de tool.call |
Omitido, echo hi se ejecutó |
cortado a 10000 ms |
| throw-guard | Lanza boom dentro de tool.call |
Omitido, el comando se ejecutó | 574.2 ms |
| Mod generado | 190 líneas + 53 líneas de tests a partir de una frase | validate: sin avisos; test: 4 pass / 0 fail | ~4 min, 34 turnos, $1.23 |
claude plugin test en redact-secrets |
Sin clave de API, sin llamada al modelo | 1 pass | 0.25 s |
claude plugin details |
Coste del Mod por sesión | ~0 tokens añadidos | n/a |
Protocolo: Claude Code 2.1.272, function hooks activados por variable de entorno. Cada Mod es un directorio de plugin con plugin.json, hooks/hooks.json y un único index.ts. Las ejecuciones pasaron por claude -p con el log de debug activado; un archivo plantado y un comando de shell contenían sk-test1234567890abcdef. Los casos de fallo en abierto se hicieron con un Mod que duerme 15 s y un Mod que lanza una excepción, con echo hi como comando bajo guardia. El REPL interactivo se manejó mediante un pty y no cargó el Mod en dos intentos.
Haz esto el lunes
- Ejecuta
/plugin-typesen una sesión y abre.claude/types/claude-code.d.ts: buscafs.readytool.callantes de fiarte de cualquier snippet de un post de septiembre. - Escribe el esqueleto de Mod de tres archivos (
plugin.json,hooks/hooks.jsoncon{"modules":["./index.ts"]},index.tsexportandoregister(on)) y ejecutaclaude plugin validate: lee las líneas de huellahooks:ycalls:. - Porta tu hook de shell más usado a un handler
tool.callque reescribaresult, y compara el tiempo de salto en el log de debug con la versión de shell. - Añade un archivo
claude plugin testjunto al Mod para que la guardia corra sin clave de API en CI. - Envuelve cada handler de guardia en un try/catch que devuelva
{ deny }ante un fallo: en esta build una excepción o un bloqueo de 10 s te omite y deja pasar el comando. - Prueba el Mod con
claude -py en tu terminal interactiva real por separado, y anota cuál lo cargó. - Antes de instalar un Mod de terceros, ejecuta
claude plugin validatesobre él y rechaza cualquiera cuya líneacalls:nombre capacidades del host que el Mod no tiene motivo para usar.
Para ir más lejos
- Lee el issue de propuesta de principio a fin, incluido el PDF de arquitectura adjunto en los comentarios: es el único contrato escrito para
register(on), los presupuestos y el salto al worker s3. - Compáralo con el diseño de los Mods de Command Code, que ejecuta TypeScript contra un
ModApien el proceso host: los dos sistemas comparten forma y acceso anticipado restringido s2. - El preview de claudefa.st se escribió cuando la funcionalidad aún era una propuesta: sirve para ver qué cambió entre el texto del 3 de septiembre y el binario 2.1.272 s9.
- La nota de Prathkum es la explicación corta más clara de por qué los hooks en proceso superan a los de shell en tokens y latencia s7.
- cc-mod-waitwhat es un buen primer Mod para leer: UI sobre el prompt, nada escrito en la transcripción s11.
- cc-arcade muestra hasta dónde llega
$.ui: juegos dibujados sobre el prompt desde un Mod s5. - La referencia de hooks sigue describiendo el modelo de shell; tenla abierta para mapear cada evento antiguo a su nuevo nombre
noun.events1. - Los escépticos en X sostienen que los plugins ya cubren esto y que la superficie se romperá en cada release; el sustantivo
fsrenombrado es un dato a su favor s23.
Fuentes
- Function Hooks proposal (issue #91870), GitHub, anthropics/claude-code. Por qué leerlo: el único texto parecido a una especificación para los Mods, con el PDF de arquitectura y el rastro de lanzamiento en los comentarios.
- Hooks reference, Claude Code docs. Por qué leerlo: el modelo de hooks de shell del que migras, evento por evento.
- Command Code Mods documentation, Command Code. Por qué leerlo: antecedente con la misma forma de TypeScript en proceso, útil para ver qué copió o evitó Anthropic.
- awesome-claude-code-mods, GitHub, karanb192. Por qué leerlo: directorio de Mods públicos escaneado automáticamente, con la huella de validate como única revisión.
- cc-arcade, GitHub, sezaakgun. Por qué leerlo: la demo que hizo visible la funcionalidad y un recorrido por
$.ui. - Boris Cherny announcement tweet, X, Boris Cherny. Por qué leerlo: el anuncio de lanzamiento de un ingeniero de Anthropic, ya que no existe post de blog.
- Prathkum: Function Hooks explained, X, Prathkum. Por qué leerlo: la mejor explicación corta de hooks frente a Mods para quien ya escribe hooks de shell.
- shipnotesai reaction thread, X, shipnotesai. Por qué leerlo: donde circuló la afirmación "solo en REPL", que nuestra prueba contradijo.
- Claude Code Function Hooks: Preview Behind a Flag, claudefa.st. Por qué leerlo: explicación previa al lanzamiento, buena para comparar la propuesta con el binario.
- cc-mod-waitwhat, GitHub, GGGODLIN. Por qué leerlo: un Mod pequeño y legible que escribe en la UI y no en la transcripción.
- claude-mods-skill, GitHub, BeLazy167. Por qué leerlo: un skill para generar Mods, si quieres repetir el experimento de una sola frase.
- AxialisSoftware reaction, X, AxialisSoftware. Por qué leerlo: el caso escéptico, en un solo tweet.
FAQ
¿Un Mod reemplaza hoy mis hooks de shell?
Todavía no para nada que deba bloquear. En 2.1.272 un hook que lanza una excepción o se queda parado más de 10 s se omite y el comando se ejecuta. Los hooks de shell siguen funcionando, así que deja ahí los que bloquean hasta que llegue un catch declarado o una opción de fallo en cerrado.
¿Por qué importa validate si el Mod funciona bien?
Porque sus líneas hooks: y calls: son la única vista estática de lo que un Mod toca en $. En tu propio Mod confirma la huella; en un Mod de terceros es toda la revisión que tienes antes de que el código corra en tu proceso.
¿Cuánto cuesta un Mod por sesión?
claude plugin details reportó unos 0 tokens añadidos. El Mod es código que corre en el motor, no texto en el prompt, que es su principal ventaja frente a un skill o una regla de CLAUDE.md.
¿Por qué el Mod cargó en -p pero no en el REPL?
Se desconoce. Dos intentos manejados por pty se quedaron mudos mientras claude -p cargaba y aplicaba el hook. La causa probable es el entorno pty y no la funcionalidad, así que prueba en tu propia terminal antes de fiarte en un sentido u otro.
AIDive