4 4
5# Crear un mod5# Crear un mod
6 6
7> Haga que Claude escriba un mod de Claude Code a partir de una descripción, o escriba uno usted mismo que cuente llamadas de herramientas y agregue un comando. Aprenda el ciclo de recarga y validación.7> Pídele a Claude que escriba un mod de Claude Code a partir de una descripción, o escribe tú mismo uno que cuente las llamadas a herramientas y agregue un comando. Aprende el ciclo de recarga y validación.
8 8
9Un mod es un [plugin](/docs/es/plugins/overview) de Claude Code con un archivo de entrada, llamado el módulo de hooks: un archivo JavaScript o TypeScript cuyas funciones Claude Code llama cuando ocurren eventos. Hay dos formas de hacer uno:9Un mod es un [plugin](/docs/es/plugins/overview) de Claude Code con un archivo de entrada, llamado módulo de hooks: un archivo JavaScript o TypeScript cuyas funciones Claude Code llama cuando ocurren eventos. Para crear uno:
10 10
11* **Pida a Claude que lo escriba**: [describa lo que desea](#ask-claude-for-a-mod) en una sesión de Claude Code11* **Pídele a Claude que lo escriba**: [describe lo que quieres](#ask-claude-for-a-mod) en una sesión de Claude Code
12* **Escríbalo usted mismo**: [siga el tutorial](#write-a-mod-yourself) para aprender cómo funciona el código de un mod. No necesita Node.js, un empaquetador o un paso de compilación, porque Claude Code carga archivos `.js` y `.ts` directamente.12* **Escríbelo tú mismo**: [sigue el tutorial](#write-a-mod-yourself) para aprender cómo funciona el código de un mod. No necesitas Node.js, un bundler ni un paso de compilación, porque Claude Code carga los archivos `.js` y `.ts` directamente.
13 13
14Si aún no ha decidido si un mod es la herramienta adecuada, lea primero la [comparación en la descripción general](/docs/es/plugins/mods/overview#compare-mods-settings-hooks-skills-and-mcp-servers).14Si aún no has decidido si un mod es la herramienta adecuada, lee primero la [comparación en la descripción general](/docs/es/plugins/mods/overview#compare-mods-settings-hooks-skills-and-mcp-servers).
15 15
16<Note>16<Note>
17 Los mods requieren Claude Code v2.1.287 o posterior. En su shell, ejecute `claude --version` para verificar. Para ver si los mods pueden cargarse para usted, consulte [Verificar si los mods pueden cargarse](/docs/es/plugins/mods/troubleshoot#check-whether-mods-can-load).17 Los mods requieren Claude Code v2.1.287 o posterior. En tu shell, ejecuta `claude --version` para comprobarlo. Para ver si los mods pueden cargarse en tu caso, consulta [Comprobar si los mods pueden cargarse](/docs/es/plugins/mods/troubleshoot#check-whether-mods-can-load).
18</Note>18</Note>
19 19
20<h2 id="ask-claude-for-a-mod">20<h2 id="ask-claude-for-a-mod">
21 Pida a Claude un mod21 Pídele un mod a Claude
22</h2>22</h2>
23 23
24Describa el mod que desea en una sesión interactiva de Claude Code, y Claude lo escribe. Claude trabaja a partir de una [skill](/docs/es/skills) integrada llamada `plugin-authoring`, que le dice dónde escribir el mod, qué eventos y métodos tiene su versión, y cómo se carga el mod. Claude puede cargar la skill cuando le pide un mod, o puede cargarla usted mismo ejecutando `/plugin-authoring` en el símbolo del sistema de Claude Code.24Describe el mod que quieres en una sesión interactiva de Claude Code y Claude lo escribe. Claude trabaja a partir de un [skill](/docs/es/skills) integrado llamado `plugin-authoring`, que le indica dónde escribir el mod, qué eventos y métodos tiene tu versión y cómo se carga el mod. Claude puede cargar el skill cuando pides un mod, o puedes cargarlo tú mismo ejecutando `/plugin-authoring` en el prompt de Claude Code.
25 25
26El mod se ejecuta una vez que lo aprueba, excepto en [sesiones donde un mod que Claude escribe no puede cargarse](#sessions-that-skip-the-approval).26El mod se ejecuta una vez que lo apruebas, excepto en [sesiones donde un mod que escribe Claude no puede cargarse](#sessions-that-skip-the-approval).
27 27
28<Steps>28<Steps>
29 <Step title="Describa el mod">29 <Step title="Describe el mod">
30 Pida el mod con sus propias palabras, por ejemplo `make a mod that shows the current git branch above the prompt`. Claude escribe el mod en un directorio propio en la carpeta de mods de la sesión, que es `~/.claude/dev-mods/` seguido del ID de la sesión. La ruta completa de un mod se ve como `~/.claude/dev-mods/3f2a9c1e-5b7d-4e8a-9c21-6d0f4b8a7e13/git-branch/`.30 Pide el mod con tus propias palabras, por ejemplo `make a mod that shows the current git branch above the prompt`. Claude escribe el mod en un directorio propio dentro de la carpeta de mods de la sesión, que es `~/.claude/dev-mods/` seguido del ID de la sesión. La ruta completa de un mod se ve así: `~/.claude/dev-mods/3f2a9c1e-5b7d-4e8a-9c21-6d0f4b8a7e13/git-branch/`.
31 31
32 <Note>32 <Note>
33 En los [modos de permiso](/docs/es/permission-modes#protected-paths) `default` y `acceptEdits`, Claude Code pregunta antes de que Claude cree cada uno de los archivos del mod, porque `~/.claude` es una ruta protegida. Apruebe cada archivo cuando aparezca.33 En los [modos de permisos](/docs/es/permission-modes#protected-paths) `default` y `acceptEdits`, Claude Code pregunta antes de que Claude cree cada uno de los archivos del mod, porque `~/.claude` es una ruta protegida. Aprueba cada archivo a medida que aparezca.
34 </Note>34 </Note>
35 </Step>35 </Step>
36 36
37 <Step title="Apruebe el mod">37 <Step title="Aprueba el mod">
38 Cuando Claude guarda el primer archivo, Claude Code pregunta si desea habilitar la recarga en caliente para la sesión. La recarga en caliente ejecuta los mods que Claude escribe en esta sesión y recoge cada cambio posterior.38 Cuando Claude guarda el primer archivo, Claude Code pregunta si quieres habilitar la recarga en caliente para la sesión. La recarga en caliente ejecuta los mods que Claude escribe en esta sesión y aplica cada cambio posterior.
39 39
40 Elija una de estas respuestas:40 Elige una de estas respuestas:
41 41
42 * **Habilitar para esta sesión**: los mods en la carpeta de mods de la sesión se cargan cuando termina el turno, y se recargan al final de cada turno que los cambia. Su respuesta dura para la sesión, incluso después de reanudarla.42 * **Enable for this session**: los mods de la carpeta de mods de la sesión se cargan cuando termina el turno y se recargan al final de cada turno que los modifique. Tu respuesta dura toda la sesión, incluso después de reanudarla.
43 * **Ahora no**: nada se carga por ahora. Los archivos permanecen donde Claude los escribió, y los mods se cargan la próxima vez que esa sesión comienza. Para evitar que un mod se cargue nunca, elimine su directorio.43 * **Not now**: por ahora no se carga nada. Los archivos permanecen donde Claude los escribió y los mods se cargan la próxima vez que se inicie esa sesión. Para evitar que un mod se cargue alguna vez, elimina su directorio.
44 </Step>44 </Step>
45 45
46 <Step title="Verifique que el mod se cargó">46 <Step title="Comprueba que el mod se cargó">
47 Ejecute `/plugin` en el símbolo del sistema de Claude Code y presione Tab hasta que se seleccione la pestaña **Installed**. Enumera el mod, y puede desactivarlo allí.47 Ejecuta `/plugin` en el prompt de Claude Code y presiona Tab hasta que quede seleccionada la pestaña **Installed**. Ahí aparece el mod, y puedes desactivarlo desde allí.
48 </Step>48 </Step>
49 49
50 <Step title="Pruebe el mod">50 <Step title="Prueba el mod">
51 Use lo que pidió. Para el ejemplo de símbolo del sistema, el nombre de la rama actual aparece encima del cuadro de símbolo del sistema. Si el mod no hace lo que deseaba, dígale a Claude qué cambiar. El mod se recarga al final de cada turno que cambia sus archivos, por lo que puede probar el cambio tan pronto como Claude termine.51 Usa lo que pediste. Para el prompt de ejemplo, el nombre de la rama actual aparece encima del cuadro del prompt. Si el mod no hace lo que querías, dile a Claude qué cambiar. El mod se recarga al final de cada turno que modifique sus archivos, así que puedes probar el cambio en cuanto Claude termine.
52 </Step>52 </Step>
53</Steps>53</Steps>
54 54
55<h3 id="use-the-mod-in-other-sessions">55<h3 id="use-the-mod-in-other-sessions">
56 Use el mod en otras sesiones56 Usa el mod en otras sesiones
57</h3>57</h3>
58 58
59Un mod que Claude escribió se carga solo en la sesión que lo creó, y Claude Code elimina la carpeta de mods de esa sesión una vez que es más antigua que [`cleanupPeriodDays`](/docs/es/settings-reference#cleanupperioddays). Para mantener el mod, copie su directorio fuera de la carpeta de mods a un lugar de su elección, como `~/mods/git-branch`. Luego elija cómo cargarlo:59Un mod que escribió Claude solo se carga en la sesión que lo creó, y Claude Code elimina la carpeta de mods de esa sesión una vez que supera la antigüedad de [`cleanupPeriodDays`](/docs/es/settings-reference#cleanupperioddays). Para conservar el mod, copia su directorio fuera de la carpeta de mods a un lugar propio, como `~/mods/git-branch`. Luego elige cómo cargarlo:
60 60
61* **En una sesión que inicia**: en su shell, ejecute `claude --plugin-dir ~/mods/git-branch`61* **En una sesión que inicies**: en tu shell, ejecuta `claude --plugin-dir ~/mods/git-branch`
62* **Para otras personas**: [agréguelo a un marketplace](#share-your-mod) para que puedan instalarlo62* **Para otras personas**: [agrégalo a un marketplace](#share-your-mod) para que puedan instalarlo
63 63
64<h3 id="sessions-that-skip-the-approval">64<h3 id="sessions-that-skip-the-approval">
65 Sesiones donde un mod que Claude escribe no puede cargarse65 Sesiones donde un mod que escribe Claude no puede cargarse
66</h3>66</h3>
67 67
68Un mod que Claude escribe se carga solo después de que lo aprueba, en un espacio de trabajo de confianza donde se permite que los mods se ejecuten. En estas sesiones no se carga:68Un mod que escribe Claude solo se carga después de que lo apruebas, en un espacio de trabajo de confianza donde se permite ejecutar mods. En estas sesiones no se carga:
69 69
70* **Nadie está allí para aprobar**: la sesión no puede mostrarle un símbolo del sistema, como en una ejecución `claude -p` o [modo `dontAsk`](/docs/es/permission-modes)70* **No hay nadie para aprobarlo**: la sesión no puede mostrarte una solicitud, como en una ejecución de `claude -p` o en el [modo `dontAsk`](/docs/es/permission-modes)
71* **El espacio de trabajo no es de confianza**: no ha aceptado el símbolo del sistema de confianza para el directorio71* **El espacio de trabajo no es de confianza**: no has aceptado la solicitud de confianza para el directorio
72* **Los mods están detenidos**: comenzó con `--safe-mode` o `--bare`, estableció `disableAllHooks`, o la [configuración administrada](/docs/es/plugins/mods/admin#choose-how-much-to-allow) de su organización lo bloquea72* **Los mods están deshabilitados**: iniciaste con `--safe-mode` o `--bare`, configuraste `disableAllHooks`, o la [configuración administrada de tu organización lo bloquea](/docs/es/plugins/mods/admin#choose-how-much-to-allow)
73 73
74<h2 id="write-a-mod-yourself">74<h2 id="write-a-mod-yourself">
75 Escriba un mod usted mismo75 Escribe un mod tú mismo
76</h2>76</h2>
77 77
78En este tutorial construye un mod llamado `first-mod` que cuenta las llamadas de herramientas que Claude hace, muestra el recuento junto al spinner mientras Claude trabaja, y agrega un comando `/tally` que lo imprime. Luego lee las declaraciones de tipo que Claude Code escribe junto a su mod y ejecuta `claude plugin validate`. Juntos muestran los eventos y métodos que su versión ofrece y qué Claude Code lee de su código.78En este tutorial creas un mod llamado `first-mod` que cuenta las llamadas a herramientas que hace Claude, muestra el conteo junto al spinner mientras Claude trabaja y agrega un comando `/tally` que lo imprime. Luego lees las declaraciones de tipos que Claude Code escribe junto a tu mod y ejecutas `claude plugin validate`. Juntos te muestran los eventos y métodos que ofrece tu versión y lo que Claude Code lee de tu código.
79 79
80Esta grabación muestra el mod terminado. El spinner cuenta llamadas de herramientas, `/tally` imprime el recuento, y una edición del código toma efecto mientras la sesión se ejecuta:80Esta grabación muestra el mod terminado. El spinner cuenta las llamadas a herramientas, `/tally` imprime el conteo y una edición al código surte efecto mientras la sesión se ejecuta:
81 81
82<Frame>82<Frame>
83 <video autoPlay muted loop playsInline controls className="w-full dark:hidden" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-first-mod-light.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=eb561134afa90375777408453ba51c77" aria-label="En una sesión de Claude Code, se escribe y envía el símbolo del sistema 'list the files here and read the README'. El spinner lee 'Thinking · tool calls: 1' y el recuento sube mientras Claude trabaja. El comando /tally imprime 'first-mod: Claude has made 3 tool calls since this mod loaded'. Una línea dice que first-mod se recargó y enumera sus cuatro hooks. En el siguiente símbolo del sistema, el spinner lee 'Thinking · tools used: 1'." data-path="images/mods-first-mod-light.mp4" />83 <video autoPlay muted loop playsInline controls className="w-full dark:hidden" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-first-mod-light.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=eb561134afa90375777408453ba51c77" aria-label="En una sesión de Claude Code, se escribe y envía el prompt 'list the files here and read the README'. El spinner muestra 'Thinking · tool calls: 1' y el conteo aumenta mientras Claude trabaja. El comando /tally imprime 'first-mod: Claude has made 3 tool calls since this mod loaded'. Una línea indica que first-mod se recargó y enumera sus cuatro hooks. En el siguiente prompt el spinner muestra 'Thinking · tools used: 1'." data-path="images/mods-first-mod-light.mp4" />
84 84
85 <video autoPlay muted loop playsInline controls className="w-full hidden dark:block" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-first-mod-dark.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=09779dadc7ef66c2b1e2da0c2e31ac72" aria-label="En una sesión de Claude Code, se escribe y envía el símbolo del sistema 'list the files here and read the README'. El spinner lee 'Thinking · tool calls: 1' y el recuento sube mientras Claude trabaja. El comando /tally imprime 'first-mod: Claude has made 3 tool calls since this mod loaded'. Una línea dice que first-mod se recargó y enumera sus cuatro hooks. En el siguiente símbolo del sistema, el spinner lee 'Thinking · tools used: 1'." data-path="images/mods-first-mod-dark.mp4" />85 <video autoPlay muted loop playsInline controls className="w-full hidden dark:block" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-first-mod-dark.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=09779dadc7ef66c2b1e2da0c2e31ac72" aria-label="En una sesión de Claude Code, se escribe y envía el prompt 'list the files here and read the README'. El spinner muestra 'Thinking · tool calls: 1' y el conteo aumenta mientras Claude trabaja. El comando /tally imprime 'first-mod: Claude has made 3 tool calls since this mod loaded'. Una línea indica que first-mod se recargó y enumera sus cuatro hooks. En el siguiente prompt el spinner muestra 'Thinking · tools used: 1'." data-path="images/mods-first-mod-dark.mp4" />
86</Frame>86</Frame>
87 87
88Escribe tres archivos:88Escribes tres archivos:
89 89
90```text theme={null}90```text theme={null}
91first-mod/91first-mod/
97```97```
98 98
99* **`plugin.json`**: el [manifiesto](/docs/es/plugins/manifest-reference) del plugin99* **`plugin.json`**: el [manifiesto](/docs/es/plugins/manifest-reference) del plugin
100* **`hooks.json`**: [apunta a su archivo de código](/docs/es/plugins/mods/reference#files)100* **`hooks.json`**: [apunta a tu archivo de código](/docs/es/plugins/mods/reference#files)
101* **`register.js`**: su código, llamado el módulo de hooks101* **`register.js`**: tu código, llamado módulo de hooks
102 102
103<Steps>103<Steps>
104 <Step title="Cree el directorio del plugin">104 <Step title="Crea el directorio del plugin">
105 Cree los dos directorios que contienen los archivos:105 Crea los dos directorios que contienen los archivos:
106 106
107 <Tabs>107 <Tabs>
108 <Tab title="Bash o Zsh">108 <Tab title="Bash o Zsh">
119 </Tabs>119 </Tabs>
120 </Step>120 </Step>
121 121
122 <Step title="Escriba el manifiesto">122 <Step title="Escribe el manifiesto">
123 Un mod es un plugin, y un mod necesita un [manifiesto](/docs/es/plugins/manifest-reference). El manifiesto de este mod no tiene campos especiales. Guarde esto como `first-mod/.claude-plugin/plugin.json`:123 Un mod es un plugin, y un mod necesita un [manifiesto](/docs/es/plugins/manifest-reference). El manifiesto de este mod no tiene campos especiales. Guarda esto como `first-mod/.claude-plugin/plugin.json`:
124 124
125 ```json first-mod/.claude-plugin/plugin.json theme={null}125 ```json first-mod/.claude-plugin/plugin.json theme={null}
126 {126 {
132 ```132 ```
133 </Step>133 </Step>
134 134
135 <Step title="Dígale a Claude Code dónde está su código">135 <Step title="Indícale a Claude Code dónde está tu código">
136 Cuando Claude Code carga un plugin, lee el `hooks/hooks.json` del plugin. La clave `modules` en ese archivo da la ruta a su código, y tenerla es lo que hace que el plugin sea un mod. Enumere una ruta, relativa a `hooks.json`. Aquí apunta a `register.js`, que escribe en el siguiente paso.136 Cuando Claude Code carga un plugin, lee el archivo `hooks/hooks.json` del plugin. La clave `modules` de ese archivo indica la ruta a tu código, y tenerla es lo que convierte al plugin en un mod. Enumera una ruta, relativa a `hooks.json`. Aquí apunta a `register.js`, que escribes en el siguiente paso.
137 137
138 Guarde esto como `first-mod/hooks/hooks.json`:138 Guarda esto como `first-mod/hooks/hooks.json`:
139 139
140 ```json first-mod/hooks/hooks.json theme={null}140 ```json first-mod/hooks/hooks.json theme={null}
141 {141 {
145 ```145 ```
146 </Step>146 </Step>
147 147
148 <Step title="Escriba el código">148 <Step title="Escribe el código">
149 Este archivo es el código del mod, llamado el módulo de hooks. Cuando el mod se carga, Claude Code llama a la función `register` que el archivo exporta y le pasa una función llamada [`on`](/docs/es/plugins/mods/reference#the-hook-function). Cada llamada a `on` registra un controlador de eventos, llamado un hook, para el evento que nombra.149 Este archivo es el código del mod, llamado módulo de hooks. Cuando el mod se carga, Claude Code llama a la función `register` que exporta el archivo y le pasa una función llamada [`on`](/docs/es/plugins/mods/reference#the-hook-function). Cada llamada a `on` registra un manejador de eventos, llamado hook, para el evento que nombra.
150 150
151 Guarde esto como `first-mod/hooks/register.js`:151 Guarda esto como `first-mod/hooks/register.js`:
152 152
153 ```javascript first-mod/hooks/register.js theme={null}153 ```javascript first-mod/hooks/register.js theme={null}
154 // The count, shared by the hooks below154 // The count, shared by the hooks below
190 }190 }
191 ```191 ```
192 192
193 El archivo mantiene un recuento en `calls` y registra cuatro hooks:193 El archivo mantiene un conteo en `calls` y registra cuatro hooks:
194 194
195 * **[`session.start`](/docs/es/plugins/mods/reference#session)** se ejecuta cuando la sesión comienza, antes de su primer símbolo del sistema, y nuevamente cada vez que el mod se recarga. Agrega el comando `/tally` a Claude Code.195 * **[`session.start`](/docs/es/plugins/mods/reference#session)** se ejecuta cuando empieza la sesión, antes de tu primer prompt, y de nuevo cada vez que el mod se recarga. Agrega el comando `/tally` a Claude Code.
196 * **[`tool.call`](/docs/es/plugins/mods/reference#tools)** se ejecuta cada vez que Claude está a punto de usar una herramienta. Suma uno a `calls` y pide a Claude Code que dibuje la interfaz nuevamente.196 * **[`tool.call`](/docs/es/plugins/mods/reference#tools)** se ejecuta cada vez que Claude está a punto de usar una herramienta. Suma uno a `calls` y le pide a Claude Code que vuelva a dibujar la interfaz.
197 * **[`command.run`](/docs/es/plugins/mods/reference#commands-and-configuration)** se ejecuta cuando escribe `/tally`. Devuelve el texto a imprimir.197 * **[`command.run`](/docs/es/plugins/mods/reference#commands-and-configuration)** se ejecuta cuando escribes `/tally`. Devuelve el texto que se imprimirá.
198 * **[`ui.render`](/docs/es/plugins/mods/reference#interface)** se ejecuta cada vez que Claude Code dibuja el spinner. Agrega el recuento después de la palabra del spinner.198 * **[`ui.render`](/docs/es/plugins/mods/reference#interface)** se ejecuta cada vez que Claude Code dibuja el spinner. Agrega el conteo después de la palabra del spinner.
199 199
200 [Cómo funciona el mod de ejemplo](#how-the-example-mod-works) explica los tres argumentos que cada hook toma y qué devuelve cada uno.200 [Cómo funciona el mod de ejemplo](#how-the-example-mod-works) explica los tres argumentos que recibe cada hook y lo que devuelve cada uno.
201 </Step>201 </Step>
202 202
203 <Step title="Cargue el mod">203 <Step title="Carga el mod">
204 Inicie Claude Code con la bandera `--plugin-dir`, que carga un directorio de plugin para una sesión sin instalarlo:204 Inicia Claude Code con el flag `--plugin-dir`, que carga un directorio de plugin durante una sesión sin instalarlo:
205 205
206 ```bash theme={null}206 ```bash theme={null}
207 claude --plugin-dir ./first-mod207 claude --plugin-dir ./first-mod
208 ```208 ```
209 </Step>209 </Step>
210 210
211 <Step title="Pruebe el mod">211 <Step title="Prueba el mod">
212 Pida a Claude que haga algo que requiera algunas llamadas de herramientas, como `list the files here and read the README`. Mientras Claude trabaja, la palabra del spinner va seguida de un recuento que sube, como en `Thinking · tool calls: 2…`. Cuando Claude termina, escriba `/tally` y presione Enter. La transcripción muestra `first-mod: Claude has made 2 tool calls since this mod loaded`, con su propio recuento. Claude Code pone el nombre del plugin delante del texto del comando.212 Pídele a Claude que haga algo que requiera algunas llamadas a herramientas, como `list the files here and read the README`. Mientras Claude trabaja, la palabra del spinner va seguida de un conteo que aumenta, como en `Thinking · tool calls: 2…`. Cuando Claude termine, escribe `/tally` y presiona Enter. La transcripción muestra `first-mod: Claude has made 2 tool calls since this mod loaded`, con tu propio conteo. Claude Code antepone el nombre del plugin al texto del comando.
213 213
214 Para verificar el comando sin una sesión interactiva, ejecútelo en modo no interactivo:214 Para comprobar el comando sin una sesión interactiva, ejecútalo en modo no interactivo:
215 215
216 ```bash theme={null}216 ```bash theme={null}
217 claude -p "/tally" --plugin-dir ./first-mod217 claude -p "/tally" --plugin-dir ./first-mod
221 first-mod: Claude has made 0 tool calls since this mod loaded221 first-mod: Claude has made 0 tool calls since this mod loaded
222 ```222 ```
223 223
224 Si `/tally` no está en la lista de comandos, el módulo no se cargó. Consulte [Descubra por qué un mod no hace nada](/docs/es/plugins/mods/troubleshoot#find-out-why-a-mod-does-nothing).224 Si `/tally` no está en la lista de comandos, el módulo no se cargó. Consulta [Averigua por qué un mod no hace nada](/docs/es/plugins/mods/troubleshoot#find-out-why-a-mod-does-nothing).
225 </Step>225 </Step>
226 226
227 <Step title="Cambie el código mientras la sesión se ejecuta">227 <Step title="Cambia el código mientras la sesión se ejecuta">
228 Deje la sesión abierta. En `register.js`, cambie `' · tool calls: '` a `' · tools used: '` en el hook `ui.render` y guarde. La línea resaltada es la que cambia:228 Deja la sesión abierta. En `register.js`, cambia `' · tool calls: '` por `' · tools used: '` en el hook `ui.render` y guarda. La línea resaltada es la que cambia:
229 229
230 ```javascript first-mod/hooks/register.js {4} theme={null}230 ```javascript first-mod/hooks/register.js {4} theme={null}
231 // Runs each time Claude Code draws the spinner231 // Runs each time Claude Code draws the spinner
235 })235 })
236 ```236 ```
237 237
238 Una línea en la transcripción dice que `first-mod` se recargó y enumera sus hooks, y el siguiente spinner usa el nuevo texto, como en `Thinking · tools used: 1…`.238 Una línea en la transcripción indica que `first-mod` se recargó y enumera sus hooks, y el siguiente spinner usa el nuevo texto, como en `Thinking · tools used: 1…`.
239 </Step>239 </Step>
240</Steps>240</Steps>
241 241
243 Cómo funciona el mod de ejemplo243 Cómo funciona el mod de ejemplo
244</h3>244</h3>
245 245
246Cada función que pasa a `on` es un hook, que es un controlador de eventos. Claude Code pasa a cada hook los mismos tres argumentos:246Cada función que pasas a `on` es un hook, que es un manejador de eventos. Claude Code pasa a cada hook los mismos tres argumentos:
247 247
248* **La API de mods**, llamada `$`: cada método que un mod puede llamar para llegar fuera de sí mismo, en [espacios de nombres](/docs/es/plugins/mods/reference#mods-api-methods) como `$.ui` y `$.command`248* **La API de mods**, llamada `$`: todos los métodos que un mod puede llamar para llegar fuera de sí mismo, organizados en [espacios de nombres](/docs/es/plugins/mods/reference#mods-api-methods) como `$.ui` y `$.command`
249* **El evento**, llamado `e`: la [entrada del evento](/docs/es/plugins/mods/reference#events) como datos simples, como el nombre y los argumentos de una llamada de herramienta249* **El evento**, llamado `e`: la [entrada del evento](/docs/es/plugins/mods/reference#events) como datos simples, como el nombre y los argumentos de una llamada a herramienta
250* **El siguiente controlador**, llamado [`next`](/docs/es/plugins/mods/events#how-a-hook-handles-an-event): una función que pasa el evento a los otros mods y luego al comportamiento propio de Claude Code, y devuelve el resultado250* **El siguiente manejador**, llamado [`next`](/docs/es/plugins/mods/events#how-a-hook-handles-an-event): una función que pasa el evento a los demás mods y luego al comportamiento propio de Claude Code, y devuelve el resultado
251 251
252Los hooks en `first-mod` manejan sus eventos de las tres formas en que un hook puede:252Los hooks de `first-mod` manejan sus eventos de estas formas:
253 253
254* **Observar**: el hook `session.start` registra el comando, y el hook `tool.call` cuenta la llamada y pide un redibujado. Ambos devuelven `next(e)`, por lo que la sesión comienza y la herramienta se ejecuta como de costumbre.254* **Observar**: el hook `session.start` registra el comando, y el hook `tool.call` cuenta la llamada y solicita que se vuelva a dibujar. Ambos devuelven `next(e)`, así que la sesión empieza y la herramienta se ejecuta como de costumbre.
255* **Responder**: el hook `command.run` devuelve su propio resultado y nunca llama a `next`. El segundo argumento a `on`, `{ command: 'tally' }`, es un filtro, llamado un [matcher](/docs/es/plugins/mods/events#filter-which-events-a-hook-handles), por lo que el hook se ejecuta solo para `/tally`.255* **Responder**: el hook `command.run` devuelve su propio resultado y nunca llama a `next`. El segundo argumento de `on`, `{ command: 'tally' }`, es un filtro, llamado [matcher](/docs/es/plugins/mods/events#filter-which-events-a-hook-handles), por lo que el hook se ejecuta solo para `/tally`.
256* **Reescribir**: el hook `ui.render` llama a `next` con una copia de `e` cuyo `suffix` contiene el recuento, por lo que Claude Code dibuja su spinner habitual con su texto después de la palabra256* **Reescribir**: el hook `ui.render` llama a `next` con una copia de `e` cuyo `suffix` contiene el conteo, así que Claude Code dibuja su spinner habitual con tu texto después de la palabra
257 257
258Claude Code observa un directorio cargado con `--plugin-dir` y recarga en caliente el módulo de hooks cuando un archivo en él cambia. Cada recarga ejecuta `register` nuevamente, por lo que `calls` vuelve a `0` y `/tally` comienza a contar nuevamente. Para mantener un valor entre recargas, consulte [Mantener estado](/docs/es/plugins/mods/interface#keep-state).258Claude Code vigila un directorio cargado con `--plugin-dir` y recarga en caliente el módulo de hooks cuando cambia un archivo en él. Cada recarga ejecuta `register` de nuevo, así que `calls` se restablece a `0` y `/tally` vuelve a empezar a contar. Para conservar un valor entre recargas, consulta [Conservar el estado](/docs/es/plugins/mods/interface#keep-state).
259 259
260<h2 id="keep-working-on-a-mod">260<h2 id="keep-working-on-a-mod">
261 Continúe trabajando en un mod261 Seguir trabajando en un mod
262</h2>262</h2>
263 263
264Una vez que un mod se carga, puede hacer que Claude lo cambie, verificar su código contra las definiciones de tipo para su versión, enumerar los eventos y llamadas que Claude Code encuentra en él, y probarlo.264Una vez que un mod se carga, puedes pedirle a Claude que lo cambie, comprobar tu código con las definiciones de tipos de tu versión, listar los eventos y las llamadas que Claude Code encuentra en él, y probarlo.
265 265
266<h3 id="change-a-mod-with-claude">266<h3 id="change-a-mod-with-claude">
267 Cambie un mod con Claude267 Cambiar un mod con Claude
268</h3>268</h3>
269 269
270Para cambiar un mod que ya tiene, inicie la sesión con `--plugin-dir` apuntando al directorio del mod, para que lo que Claude escribe se cargue en la misma sesión:270Para cambiar un mod que ya tienes, inicia la sesión con `--plugin-dir` apuntando al directorio del mod, de modo que lo que Claude escriba se cargue en la misma sesión:
271 271
272```bash theme={null}272```bash theme={null}
273claude --plugin-dir ./first-mod273claude --plugin-dir ./first-mod
274```274```
275 275
276Luego pida el cambio, por ejemplo `add a /tally-reset command to this mod that sets the tally back to zero`. Claude edita el módulo de hooks, ejecuta `claude plugin validate`, y corrige lo que reporta. Un directorio que carga con `--plugin-dir` es una [ruta protegida](/docs/es/permission-modes#protected-paths), por lo que en los modos `default` y `acceptEdits` se le pide que apruebe cada edición de Claude al mod. La tabla de rutas protegidas da el resultado para los otros modos de permiso.276Luego pide el cambio, por ejemplo `add a /tally-reset command to this mod that sets the tally back to zero`. Claude edita el módulo de hooks, ejecuta `claude plugin validate` y corrige lo que este reporta. Un directorio que cargas con `--plugin-dir` es una [ruta protegida](/docs/es/permission-modes#protected-paths), así que en los modos `default` y `acceptEdits` se te pide que apruebes cada una de las ediciones de Claude al mod. La tabla de rutas protegidas indica el resultado para los demás modos de permisos.
277 277
278Los archivos que Claude guarda durante su turno se recargan cuando termina el turno, por lo que puede probar `/tally-reset` tan pronto como Claude termine.278Los archivos que Claude guarda durante su turno se recargan cuando el turno termina, así que puedes probar `/tally-reset` en cuanto Claude termine.
279 279
280<h3 id="get-the-types-for-your-build">280<h3 id="get-the-types-for-your-build">
281 Obtenga definiciones de tipo para su versión281 Obtener las definiciones de tipos para tu versión
282</h3>282</h3>
283 283
284Cada vez que Claude Code carga o recarga un mod desde un directorio que pasa a `--plugin-dir`, o un mod [que Claude escribió para usted](#ask-claude-for-a-mod), escribe archivos de declaración de TypeScript, terminando en `.d.ts`, en `.claude-plugin/types/` dentro del directorio del mod. Describen los eventos exactos, métodos de la API de mods, y elementos en la versión de Claude Code que está ejecutando, por lo que su editor puede autocompletar y verificar el tipo de sus hooks. Para examinar las declaraciones en línea, lea [`mods/types/claude-code.d.ts`](https://github.com/anthropics/claude-code/blob/main/mods/types/claude-code.d.ts) en el repositorio de Claude Code, cuya primera línea nombra la versión que la escribió. El directorio contiene estos archivos:284Cada vez que Claude Code carga o recarga un mod desde un directorio que pasas a `--plugin-dir`, o un mod que [Claude escribió por ti](#ask-claude-for-a-mod), escribe archivos de declaración de TypeScript, que terminan en `.d.ts`, en `.claude-plugin/types/` dentro del directorio del mod. Describen exactamente los eventos, los métodos de la API de mods y los elementos de la versión de Claude Code que estás ejecutando, para que tu editor pueda autocompletar y verificar los tipos de tus hooks. Para consultar las declaraciones en línea, lee [`mods/types/claude-code.d.ts`](https://github.com/anthropics/claude-code/blob/main/mods/types/claude-code.d.ts) en el repositorio de Claude Code, cuya primera línea indica la versión que lo escribió. El directorio contiene estos archivos:
285 285
286| Ruta | Lo que declara |286| Ruta | Lo que declara |
287| :- | :- |287| :- | :- |
288| `claude-code/index.d.ts` | Cada evento y su entrada y resultado, cada espacio de nombres y método de la API de mods, y los elementos que cada superficie puede dibujar |288| `claude-code/index.d.ts` | Cada evento con su entrada y su resultado, cada espacio de nombres y método de la API de mods, y los elementos que cada superficie puede dibujar |
289| `claude-code-tools/index.d.ts` | Las entradas y resultados de las herramientas integradas, para que verificar `e.tool === 'Bash'` reduzca `e` |289| `claude-code-tools/index.d.ts` | Las entradas y los resultados de las herramientas integradas, de modo que comprobar `e.tool === 'Bash'` acota el tipo de `e` |
290| `claude-code-mcp/index.d.ts` | Las entradas de las herramientas MCP que se conectaron la última vez que guardó un archivo en el mod |290| `claude-code-mcp/index.d.ts` | Las entradas de las herramientas MCP que estaban conectadas la última vez que guardaste un archivo en el mod |
291| `index.d.ts` en un directorio nombrado para un plugin | Lo que ese plugin agrega a la API de mods. Hay un directorio para cada plugin que su `plugin.json` enumera bajo `dependencies`. |291| `index.d.ts` en un directorio con el nombre de un plugin | Lo que ese plugin agrega a la API de mods. Hay un directorio por cada plugin que tu `plugin.json` lista en `dependencies`. |
292| `tsconfig.json` | Opciones del compilador que se ajustan a un módulo de hooks |292| `tsconfig.json` | Opciones del compilador adecuadas para un módulo de hooks |
293 293
294Si su mod no tiene su propio `tsconfig.json`, Claude Code agrega uno en la raíz del mod que extiende el generado, por lo que su editor y `tsc -p ./first-mod` verifican el tipo del mod sin más configuración.294Si tu mod no tiene un `tsconfig.json` propio, Claude Code agrega uno en la raíz del mod que extiende el generado, para que tu editor y `tsc -p ./first-mod` verifiquen los tipos del mod sin más configuración.
295 295
296Los eventos y métodos pueden cambiar entre versiones, por lo que confíe en estos archivos sobre cualquier página, incluso esta, cuando no estén de acuerdo.296Los eventos y los métodos pueden cambiar entre versiones, así que confía en estos archivos antes que en cualquier página, incluida esta, cuando no coincidan.
297 297
298`claude-code/index.d.ts` es la referencia más completa para su compilación, con un comentario y un ejemplo para cada método de la API de mods. Para buscar algo, busque en el archivo su nombre, como `'tool.call'`.298`claude-code/index.d.ts` es la referencia más completa para tu compilación, con un comentario y un ejemplo para cada método de la API de mods. Para buscar algo, busca su nombre en el archivo, como `'tool.call'`.
299 299
300<h3 id="check-what-claude-code-reads-from-your-mod">300<h3 id="check-what-claude-code-reads-from-your-mod">
301 Verifique qué Claude Code lee de su mod301 Comprobar lo que Claude Code lee de tu mod
302</h3>302</h3>
303 303
304Para ver su mod de la forma en que Claude Code lo ve, sin ejecutar su código o iniciar una sesión, use `claude plugin validate`. Verifica el manifiesto y ejecuta el mismo análisis estático en la fuente del módulo de hooks que Claude Code ejecuta cuando carga un mod. En su shell, ejecútelo en el directorio del mod:304Para ver tu mod como lo ve Claude Code, sin ejecutar tu código ni iniciar una sesión, usa `claude plugin validate`. Comprueba el manifiesto y ejecuta sobre el código fuente del módulo de hooks el mismo análisis estático que Claude Code ejecuta al cargar un mod. En tu shell, ejecútalo sobre el directorio del mod:
305 305
306```bash theme={null}306```bash theme={null}
307claude plugin validate ./first-mod307claude plugin validate ./first-mod
316✔ Validation passed316✔ Validation passed
317```317```
318 318
319La línea `hooks:` enumera los eventos que su módulo engancha, cada uno con su filtro entre llaves. La línea `calls:` enumera cada método de la API de mods que llama. Un módulo que lee o establece variables de entorno también obtiene líneas `env reads:` y `env writes:`, y uno que usa [`$.state`](/docs/es/plugins/mods/interface#keep-state) obtiene `state reads:` y `state writes:`.319La línea `hooks:` lista los eventos a los que se engancha tu módulo, cada uno con su filtro entre llaves. La línea `calls:` lista cada método de la API de mods que llama. Un módulo que lee o establece variables de entorno también obtiene las líneas `env reads:` y `env writes:`, y uno que usa [`$.state`](/docs/es/plugins/mods/interface#keep-state) obtiene `state reads:` y `state writes:`.
320 320
321Si un evento que pretendía enganchar falta en la primera línea, Claude Code tampoco llamará a ese hook. La causa habitual es un nombre de evento mal escrito, que el comando reporta como un error como `"tool.calls" is not an event`.321Si en la primera línea falta un evento que querías manejar, Claude Code tampoco llamará a ese hook. La causa habitual es un nombre de evento mal escrito, que el comando reporta como un error como `"tool.calls" is not an event`.
322 322
323Siga estas reglas para que el análisis estático pueda encontrar cada hook y llamada:323Sigue estas reglas para que el análisis estático pueda encontrar cada hook y cada llamada:
324 324
325* Deletree cada llamada de la API de mods en su totalidad: `$`, el espacio de nombres, luego el método, como en `$.store.get('notes')`. Puede pasar `$` a una función declarada en el nivel superior del mismo archivo, y para una función suya llamada `loadNotes`, la línea `calls:` entonces lee `$.store.get (via loadNotes)`. Pasar `$` a un método, una función definida dentro del hook, o una función que importa de otro de sus archivos falla la validación. Las funciones `read` y `update` que [`$.state`](/docs/es/plugins/mods/interface#keep-state) usa son las importaciones que pueden tomarlo. No asigne `$` o uno de sus espacios de nombres a una variable, desestructúrelo, o indexarlo con un nombre calculado. `const ui = $.ui` falla con `$.ui is used as a value`.325* Escribe cada llamada a la API de mods completa: `$`, el espacio de nombres y luego el método, como en `$.store.get('notes')`. Puedes pasar `$` a una función declarada en el nivel superior del mismo archivo, y para una función tuya llamada `loadNotes`, la línea `calls:` muestra entonces `$.store.get (via loadNotes)`. Pasar `$` a un método, a una función definida dentro del hook o a una función que importas de otro de tus archivos hace que la validación falle. Las funciones `read` y `update` que usa [`$.state`](/docs/es/plugins/mods/interface#keep-state) son las importaciones que pueden recibirlo. No asignes `$` ni uno de sus espacios de nombres a una variable, no lo desestructures ni lo indexes con un nombre calculado. `const ui = $.ui` falla con `$.ui is used as a value`.
326* Escriba el nombre del evento en cada llamada a `on` como un literal de cadena, como `'tool.call'`. Una variable, o un bucle sobre una lista de nombres, falla con `the event name passed to on() is not a string literal`.326* Escribe el nombre del evento en cada llamada a `on` como un literal de cadena, como `'tool.call'`. Una variable, o un bucle sobre una lista de nombres, falla con `the event name passed to on() is not a string literal`.
327* Dentro de `register`, no declare una segunda variable o parámetro llamado `on`. La validación falla con `"on" is declared again (shadowed)`.327* Dentro de `register`, no declares una segunda variable ni un parámetro llamado `on`. La validación falla con `"on" is declared again (shadowed)`.
328* Importe solo desde archivos dentro del directorio del plugin, por ruta relativa. La única importación desnuda permitida es `claude-code`, para tipos y algunos ayudantes.328* Importa solo desde archivos dentro del directorio del plugin, mediante ruta relativa. La única importación sin ruta permitida es `claude-code`, para tipos y algunas utilidades.
329* Use declaraciones `import` en la parte superior del archivo, como en `import { name } from './file.js'`. Un `import()` dinámico falla con `a dynamic import(); a hooks module imports its own files with an import declaration`.329* Usa declaraciones `import` al principio del archivo, como en `import { name } from './file.js'`. Un `import()` dinámico falla con `a dynamic import(); a hooks module imports its own files with an import declaration`.
330* Escriba cada archivo como un módulo ES, con `import` y no `require`. La [referencia](/docs/es/plugins/mods/reference#files) enumera las extensiones de archivo que Claude Code carga.330* Escribe cada archivo como un módulo ES, con `import` y no `require`. La [referencia](/docs/es/plugins/mods/reference#files) lista las extensiones de archivo que carga Claude Code.
331 331
332<h3 id="test-the-mod">332<h3 id="test-the-mod">
333 Pruebe el mod333 Probar el mod
334</h3>334</h3>
335 335
336Puede escribir pruebas automatizadas para un mod y ejecutarlas desde su shell con `claude plugin test`, sin sesión, inicio de sesión o red. Una prueba genera los eventos que sus hooks manejan y verifica qué hicieron los hooks.336Puedes escribir pruebas automatizadas para un mod y ejecutarlas desde tu shell con `claude plugin test`, sin sesión, sin inicio de sesión y sin red. Una prueba dispara los eventos que manejan tus hooks y comprueba lo que hicieron los hooks.
337 337
338Esta prueba genera dos llamadas de herramientas, ejecuta `/tally`, y verifica que la respuesta cuente ambas. Guárdela como `first-mod/tests/first-mod.test.ts`:338Esta prueba dispara dos llamadas a herramientas, ejecuta `/tally` y comprueba que la respuesta cuenta ambas. Guárdala como `first-mod/tests/first-mod.test.ts`:
339 339
340```typescript first-mod/tests/first-mod.test.ts theme={null}340```typescript first-mod/tests/first-mod.test.ts theme={null}
341import { expect, test } from 'claude-code/testing'341import { expect, test } from 'claude-code/testing'
344 // Answer each tool call in Claude Code's place, so no tool runs344 // Answer each tool call in Claude Code's place, so no tool runs
345 on('tool.call', () => ({ result: 'ok' }))345 on('tool.call', () => ({ result: 'ok' }))
346 346
347 // Raise two tool calls, which the mod's tool.call hook counts347 // Fire two tool calls, which the mod's tool.call hook counts
348 await $.tool.call({ tool: 'Bash', command: 'ls' })348 await $.tool.call({ tool: 'Bash', command: 'ls' })
349 await $.tool.call({ tool: 'Read', file_path: 'README.md' })349 await $.tool.call({ tool: 'Read', file_path: 'README.md' })
350 350
354})354})
355```355```
356 356
357En su shell, ejecute las pruebas desde el directorio `first-mod`:357En tu shell, ejecuta las pruebas desde el directorio `first-mod`:
358 358
359```bash theme={null}359```bash theme={null}
360claude plugin test360claude plugin test
361```361```
362 362
363La salida nombra cada prueba y si pasó, con tiempos que varían de una ejecución a otra:363La salida nombra cada prueba e indica si pasó, con tiempos que varían de una ejecución a otra:
364 364
365```text theme={null}365```text theme={null}
366tests/first-mod.test.ts:366tests/first-mod.test.ts:
371Ran 1 test across 1 file. [0.19s]371Ran 1 test across 1 file. [0.19s]
372```372```
373 373
374[Pruebe un mod](/docs/es/plugins/mods/test) cubre el stubbing de una llamada de modelo o la tienda, y pruebas de temporizadores y dibujos.374[Probar un mod](/docs/es/plugins/mods/test) explica cómo simular una llamada al modelo o el almacén, y cómo probar temporizadores y dibujos.
375 375
376<h2 id="share-your-mod">376<h2 id="share-your-mod">
377 Comparta su mod377 Comparte tu mod
378</h2>378</h2>
379 379
380Un mod es un plugin, por lo que lo versiona en el manifiesto y las personas lo instalan y actualizan con los comandos `/plugin`. Para dárselo a otras personas, [agréguelo a un marketplace](/docs/es/plugins/publish).380Un mod es un plugin, así que le asignas la versión en el manifiesto y las personas lo instalan y actualizan con los comandos de `/plugin`. Para dárselo a otras personas, [agrégalo a un marketplace](/docs/es/plugins/publish).
381 381
382Antes de hacerlo, verifique el `name` del plugin: `claude plugin validate` falla un nombre que [parece uno de los propios de Anthropic](/docs/es/plugins/manifest-reference#name), como uno que comienza con `claude-`. Los eventos y métodos pueden cambiar entre versiones, por lo que su README es el lugar para decir qué versión de Claude Code probó.382Antes de hacerlo, revisa el `name` del plugin: `claude plugin validate` rechaza un nombre que [parece uno de los propios de Anthropic](/docs/es/plugins/manifest-reference#name), como uno que empieza con `claude-`. Los eventos y métodos pueden cambiar entre versiones, así que tu README es el lugar para indicar con qué versión de Claude Code hiciste las pruebas.
383 383
384Continúe desarrollando contra el directorio con `--plugin-dir`, no contra una copia instalada. Claude Code almacena en caché un plugin instalado por versión, por lo que sus ediciones no llegan a la copia instalada hasta que sube la versión e instala nuevamente.384Sigue desarrollando contra el directorio con `--plugin-dir`, no contra una copia instalada. Claude Code almacena en caché un plugin instalado por versión, así que tus ediciones no llegan a la copia instalada hasta que incrementes la versión y lo instales de nuevo.
385 385
386<h2 id="next-steps">386<h2 id="next-steps">
387 Próximos pasos387 Próximos pasos
388</h2>388</h2>
389 389
390* [Dibuje en la interfaz](/docs/es/plugins/mods/interface): abra un panel, dibuje encima del símbolo del sistema, y agregue botones y campos de texto390* [Dibuja en la interfaz](/docs/es/plugins/mods/interface): abre un panel, dibuja encima del prompt y agrega botones y campos de texto
391* [Reaccione a eventos](/docs/es/plugins/mods/events): enganche llamadas de herramientas, símboles del sistema, y turnos391* [Reacciona a eventos](/docs/es/plugins/mods/events): intercepta llamadas a herramientas, prompts y turnos
392* [Use la API de mods](/docs/es/plugins/mods/api): agregue comandos y herramientas, llame a un modelo, y ejecute trabajo en un temporizador392* [Usa la API de mods](/docs/es/plugins/mods/api): agrega comandos y herramientas, llama a un modelo y ejecuta trabajo con un temporizador
393* [Pruebe un mod](/docs/es/plugins/mods/test): stub lo que Claude Code respondería, y pruebe temporizadores y dibujos393* [Prueba un mod](/docs/es/plugins/mods/test): simula lo que respondería Claude Code y prueba temporizadores y dibujos
394* [Solucione problemas de un mod](/docs/es/plugins/mods/troubleshoot): las razones por las que un mod no hace nada, y el registro de depuración394* [Soluciona problemas de un mod](/docs/es/plugins/mods/troubleshoot): los motivos por los que un mod no hace nada y el registro de depuración
395* [Lea la fuente de mods integrados](/docs/es/plugins/mods/overview#read-the-source-of-built-in-mods): plugins completos, cada uno con su módulo de hooks y pruebas395* [Lee el código fuente de los mods integrados](/docs/es/plugins/mods/overview#read-the-source-of-built-in-mods): plugins completos, cada uno con su módulo de hooks y sus pruebas