Skills en Claude Code: instrucciones que solo pesan cuando se usan
Cierro con este post una especie de trilogía que no había planeado como tal. Primero conté los comandos de Claude Code, las barras que controlan la sesión. Luego los subagentes, las ventanas de contexto separadas con sus herramientas y su modelo. Falta la pieza que las une y que, además, es la que más ha cambiado últimamente: las skills.
La escena que las justifica la conoces si usas esto a diario. Pegas las mismas instrucciones en el chat por enésima vez —«acuérdate de que el deploy es un rsync y luego un systemctl restart, nunca sincronices content/ con --delete…»— y piensas «esto debería estar apuntado en algún sitio». Ya lo está: en tu CLAUDE.md. Pero cuando ese apunte deja de ser un dato y se convierte en un procedimiento de doce pasos, el CLAUDE.md se hincha, y todo lo que metes ahí se carga en cada conversación, la use o no. Ahí es donde entra una skill.
Todo esto está verificado contra la documentación oficial a fecha de publicación. Claude Code cambia cada semana; si algo no te cuadra, /help en tu versión manda.
Qué es, mecánicamente
Una skill es un fichero llamado SKILL.md dentro de una carpeta. El nombre de la carpeta es el comando. Es decir:
~/.claude/skills/resumir-cambios/SKILL.md → /resumir-cambios
El fichero tiene dos partes: un bloque de front matter YAML entre --- que le dice a Claude cuándo usar la skill, y debajo el cuerpo en Markdown con las instrucciones que sigue cuando la ejecuta. El mínimo viable es una sola línea de front matter:
---
description: Resume los cambios sin commitear y señala lo arriesgado. Úsala cuando pregunten qué ha cambiado o pidan un mensaje de commit.
---
Resume los cambios de abajo en dos o tres puntos y después
lista los riesgos que veas: manejo de errores que falta,
valores hardcodeados, tests que habría que tocar.
Y ya tienes /resumir-cambios funcionando.
Dónde vive el fichero decide quién puede usarlo, igual que con los subagentes:
~/.claude/skills/<nombre>/SKILL.md— personal, en todos tus proyectos..claude/skills/<nombre>/SKILL.md— del proyecto, va a git, lo tiene el equipo.- Dentro de un plugin, con su propio espacio de nombres.
Si un nombre choca entre niveles, gana el de arriba: empresa sobre personal, personal sobre proyecto.
La idea que lo cambia todo: carga diferida
Aquí está la diferencia que hace que las skills merezcan la pena, y es una sola: el cuerpo de la skill solo se carga en contexto cuando se usa.
Tu CLAUDE.md se carga entero, siempre, en cada conversación. Es lo correcto para hechos que aplican a todo —«el logging va con slog», «los handlers devuelven errores»—. Pero si metes ahí un procedimiento largo de despliegue que necesitas una vez a la semana, estás pagando ese peaje de tokens en las otras seiscientas conversaciones que no despliegan nada.
Una skill le da la vuelta a eso. Lo único que está siempre presente es la description: esa línea que Claude lee para decidir si la skill viene al caso. El cuerpo —los doce pasos, los ejemplos, el material de referencia— no entra hasta que la skill se invoca. Material de referencia larguísimo que cuesta casi cero hasta el momento en que hace falta.
Es la misma economía que defendía en el post de subagentes, aplicada al conocimiento en vez de al cómputo. Y por eso la regla práctica de dónde poner cada cosa es tan limpia: hecho que aplica siempre → CLAUDE.md; procedimiento que aplica a veces → skill.
Las dos formas de dispararla
Una skill se invoca de dos maneras, y esto es lo que la separa de un comando de toda la vida.
Tú, escribiendo /nombre. Lo explícito de siempre.
Claude, solo, cuando tu petición encaja con la description. Si tu skill se describe como «úsala cuando pregunten qué ha cambiado» y tú escribes «¿qué he tocado?», Claude la carga sin que teclees la barra. Esto es lo nuevo y lo potente: la skill se comporta como una capacidad latente que se activa cuando toca.
Si una skill concreta no quieres que se dispare sola —un despliegue, un commit, algo con efectos—, se lo dices en el front matter con disable-model-invocation: true, y entonces solo corre cuando tú escribes /nombre. Y al revés: user-invocable: false la esconde del menú de barras para que solo Claude la use, útil para conocimiento de fondo que no quieres que nadie invoque a mano.
Los comandos se han fundido en las skills
Esto es lo que más ha cambiado y conviene tenerlo claro, sobre todo si vienes de la versión de antes. Los comandos personalizados y las skills son ya la misma cosa. Un fichero en .claude/commands/deploy.md y una skill en .claude/skills/deploy/SKILL.md crean los dos /deploy y funcionan igual. Tus .claude/commands/ viejos siguen valiendo tal cual.
Lo que aporta el formato skill sobre el comando plano son tres cosas: una carpeta para ficheros de apoyo (plantillas, scripts, datos que la skill referencia), el front matter para controlar quién la invoca, y la carga automática cuando la descripción encaja. Si tu comando era una nota de dos líneas, un skill es lo mismo con superpoderes opcionales que no estás obligado a usar.
Los /code-review, /loop, /run o /claude-api que ya usas son, de hecho, skills empaquetadas que vienen de serie: instrucciones que orientan a Claude y le dejan orquestar el trabajo con sus herramientas, a diferencia de los comandos internos como /compact, que ejecutan lógica fija.
El front matter que de verdad usarás
Más allá de description, estos son los campos que van a darte juego:
allowed-tools— herramientas que Claude puede usar sin pedirte permiso durante el turno en que se invoca la skill. El permiso se levanta con tu siguiente mensaje. Es lo que convierte una skill de «recordatorio» en «procedimiento que se ejecuta sin interrumpirte cada dos pasos».model— con qué modelo corre mientras la skill está activa. La misma idea que en los subagentes: no gastes el modelo caro en una tarea tonta.context: fork— y este es el puente con los subagentes: hace que la skill corra en un subagente aislado, en segundo plano, y te devuelva el resultado. El cuerpo de la skill se convierte en el prompt de ese subagente. Conbackground: falseesperas el resultado en el mismo turno en vez de en diferido.argument-hintyarguments— para skills que reciben parámetros, con sustitución de$1,$2en el cuerpo.
Un aviso que agradecerás: la description (más el when_to_use si lo usas) se recorta a 1.536 caracteres en el listado de skills. Es a propósito, para no inflar el contexto con descripciones kilométricas. Descripción corta y específica; las instrucciones largas, al cuerpo.
El truco que no vi venir: contexto dinámico
Hay una función que me ganó, y es pequeña. Dentro del cuerpo de una skill puedes meter una línea así:
## Cambios actuales
!`git diff HEAD`
Antes de que Claude lea la skill, Claude Code ejecuta ese comando y sustituye la línea por su salida. O sea: las instrucciones le llegan con el git diff ya incrustado. La skill no le pide a Claude que mire el diff; se lo pone delante. Para cualquier procedimiento que dependa del estado real del repo —la rama actual, los ficheros tocados, la config de un entorno— esto es la diferencia entre una respuesta fundada y una adivinada.
Es una extensión propia de Claude Code sobre el estándar abierto de Agent Skills, así que si te llevas la skill a otra herramienta esa línea concreta no funcionará. Pero dentro de Claude Code, es oro.
El coste, que también lo hay
No todo es gratis, y sería deshonesto vender la carga diferida como magia sin factura. Una vez que una skill se invoca, su contenido se queda en contexto en los turnos siguientes. No se recarga cada vez, pero tampoco desaparece: cada línea es un coste de tokens recurrente durante el resto de la conversación. Por eso la propia documentación insiste en mantener el cuerpo conciso —decir qué hacer, no narrar cómo ni por qué— con el mismo criterio que aplicas al CLAUDE.md.
Y cuando la conversación se recompacta para liberar contexto, Claude Code re-adjunta la última invocación de cada skill con un presupuesto combinado de unos 25.000 tokens, quedándose con los primeros 5.000 de cada una y empezando por la más reciente. Traducido: si en una sesión has disparado quince skills gordas, las más viejas se caen. Es un comportamiento sensato, pero conviene saber que existe.
Una skill puede traer equipaje
Lo que separa de verdad una skill de un comando plano es la carpeta. El SKILL.md no está solo: junto a él puedes meter los ficheros que la skill necesite, y referenciarlos desde el cuerpo para que Claude sepa qué contiene cada uno y cuándo abrirlo.
.claude/skills/nuevo-post/
SKILL.md # las instrucciones
plantilla.md # el front matter en blanco, en orden
ejemplo-bueno.md # un post de referencia
generar-hero.py # el script que crea la imagen
La gracia es que esos ficheros de apoyo tampoco pesan hasta que se usan: el cuerpo de la skill dice «para la imagen, ejecuta generar-hero.py», y ese script no entra en contexto salvo que la skill lo abra. Es la misma carga diferida, un nivel más abajo. Una skill deja de ser un texto para convertirse en un pequeño paquete autocontenido: instrucciones, plantillas y herramientas viajando juntas, versionadas en git con el proyecto.
Y hay una recompensa por hacerlo bien. Las skills de Claude Code siguen el estándar abierto Agent Skills, pensado para funcionar en varias herramientas de IA. Seis campos del front matter son del estándar —name, description, license, compatibility, metadata y allowed-tools—; el resto (el context: fork, la inyección de contexto dinámico con !`comando`) son extensiones propias de Claude Code. Traducido: si te ciñes a lo básico, la skill que escribes hoy es portable; si usas los superpoderes, ganas potencia a cambio de atarte a esta herramienta. Un compromiso honesto, y tú decides de qué lado.
Un detalle cómodo para el día a día: los cambios en un SKILL.md se recogen en caliente. Editas el fichero y la sesión en curso lo nota sin reiniciar, igual que el blog recarga un .md al guardarlo. Solo hace falta reiniciar si creas de cero un directorio de skills que no existía al arrancar.
Cuándo cada cosa
Después de tenerlas las tres en la cabeza, mi regla mental para no confundirlas:
- CLAUDE.md — hechos que aplican a todo el proyecto, siempre en contexto. La convención de errores, el comando de build, lo que nunca hay que hacer.
- Skill — un procedimiento o un cuerpo de conocimiento que aplica a veces, que quieres poder disparar con
/nombreo dejar que Claude cargue cuando encaje, y que solo pesa cuando se usa. - Subagente — cuando lo que necesitas es aislar contexto, restringir herramientas o cambiar de modelo para una tarea, y que el trabajo ocurra en otra ventana y te devuelva solo la conclusión.
No son rivales. Una skill con context: fork es, literalmente, las dos últimas trabajando juntas.
El cierre, que me toca de cerca
Este mes he escrito unos cuantos posts con ayuda de agentes, y a cada uno le he tenido que dictar a mano las mismas reglas: front matter en este orden, entre 1.400 y 2.400 palabras, sábado de comida, domingo de amigos, page bundle siempre que haya imágenes. Las mismas instrucciones, una y otra vez, pegadas en cada arranque.
Eso es exactamente lo que una skill resuelve. Un SKILL.md con mi manual editorial dentro, disparable con /nuevo-post, que carga esas reglas solo cuando voy a escribir y no molesta el resto del tiempo. Llevo el post entero explicando la herramienta que me habría ahorrado el trabajo de escribir el post entero. Hay algo muy de este oficio en eso.
Si te pasa como a mí —si te descubres pegando el mismo bloque de texto por tercera vez—, para. Eso no es una nota para el chat. Es una skill que aún no has escrito.