Saltar al contenido
Volver a Artículos Publicados
Claude Code

Cómo escribir una skill de Claude Code que tu equipo realmente reutilice

Una skill es una carpeta con un markdown y su descripción es todo el producto. Cómo convertí instrucciones repetidas al agente en skills que mi equipo usa sin mí.

Cómo escribir una skill de Claude Code que tu equipo realmente reutilice
Contenido 100% autoral: Todos los artículos, desafíos técnicos y código fueron escritos por Marcelo Costa sin el uso de IA en la redacción. La inteligencia artificial se utilizó exclusivamente para ayudar con la traducción a múltiples idiomas.

La primera descripción que escribí para mi skill de creación de tests fue "Elabora y mantiene especificaciones para la cobertura end-to-end." Correcta, precisa, el tipo de frase que queda genial en un design doc. Nadie teclea algo así. (La escribí yo, así que debería haberlo sabido mejor que nadie 😅)

Y daba igual lo que pusiera debajo: esa única línea de arriba decide si la skill llega a cargarse alguna vez.

Ya escribí antes sobre cómo usé una skill de Claude Code para terminar a tiempo la migración de las APIs obsoletas en Cypress 16. Aquella era una skill personal, que mantuve fuera del repositorio. La sorpresa vino de las skills que sí puse en el repositorio: las siguió usando gente que no era yo, en tareas que yo no había previsto.

La mayoría de las skills nunca llegan tan lejos. Se escriben una vez, se activan con los prompts equivocados (o se quedan calladas con los correctos), y todo el mundo vuelve a pegar instrucciones en el chat.

Así que vamos al grano: qué separó a las skills que se quedaron de las que se escribieron una vez y se abandonaron.

Menos de lo que esperas

Una skill es un directorio con un archivo markdown. Eso es todo:

.claude/skills/
  cypress-author/
    SKILL.md
    references/
      selectors.md

Y SKILL.md es frontmatter más prosa:

---
name: cypress-author
description: Creates, updates, and fixes Cypress tests (E2E and component). Use when the user asks to create tests, add tests, write tests, test this file, new spec, or fix a failing or flaky test. Applies even when the user does not say "Cypress".
---

## Non-negotiables
## Steps
## Verify

Ese es todo el mecanismo. El agente ve el nombre y la descripción en todo momento, y solo carga el cuerpo cuando decide que la skill es relevante. ¿Adivinas entonces dónde debe ir el esfuerzo de ingeniería? Exacto, en esa descripción.

La descripción es todo el producto

Todo lo demás del archivo no sirve de nada si la skill nunca se activa. Y una skill que se activa cuando no debe es peor que una que nunca se activa, porque ahora está distorsionando trabajo que no tiene nada que ver con ella.

Dos reglas hicieron que mi precisión de activación subiera de forma notable.

1. Escribe la descripción con las palabras de tus usuarios, no con las tuyas

¿Te acuerdas de mi frase de design doc del principio? La gente no habla así. Teclea "escribe tests para este archivo", "añade un test", "este spec es flaky". Así que ahora la descripción usa exactamente ese vocabulario. Lo que estás escribiendo es el objetivo de coincidencia para una petición que todavía no has visto, y un resumen pulido para un lector humano es la herramienta equivocada para ese trabajo.

2. Cubre las peticiones en las que falta la palabra clave

"crea tests para este componente" no menciona ningún framework. En un repositorio con un solo framework de testing, sigue siendo sin ninguna duda trabajo de tu skill. Así que dilo bien claro: terminé la descripción con "Applies even when the user does not say Cypress" y el comportamiento cambió de inmediato.

Y ya que estás, dile también a la skill cuándo hacerse a un lado. Si tienes una skill complementaria para revisar tests sin modificar código, pon "prefiere esa cuando el usuario solo quiera una explicación". Uno pensaría que la competencia es el comportamiento por defecto del modelo. Pues no: la ambigüedad entre dos de tus propias skills es un fallo mucho más común.

Mi única skill ingeniosa

Mi primer intento juntaba la escritura de tests, la revisión y la planificación de reejecuciones en una sola skill, con ramas (ingenioso, ¿verdad?). Se comportaba mal en las tres cosas, porque las instrucciones cargadas para los otros dos trabajos eran ruido de contexto tirando en direcciones distintas.

Así que la dividí en tres skills — author, review, rerun-plan — cada una con su propia descripción bien acotada. Mejor en todos los sentidos. Y se combinan de forma natural: el agente escribe los tests con una → luego recurre por su cuenta a la skill de rerun-plan, porque esa descripción encaja con lo que acaba de pasar.

Mi regla práctica ahora es esta: si el cuerpo de tu skill necesita un if the user wants X... otherwise... en el nivel superior, tienes dos skills.

Donde el agente se pone "servicial"

Es en las restricciones negativas donde los agentes se desvían. Las instrucciones que se ganan su sitio son casi todas prohibiciones. El modelo suele acertar las instrucciones positivas sin ayuda; la desviación está en lo que, muy servicial, hace de más.

Estas son las líneas que más cambiaron los resultados en mi skill para arreglar tests:

  • No ejecutes la suite. Imprime el comando y detente. (Solo el humano sabe si el entorno está en condiciones.)
  • No elimines un flag .only. Está ahí a propósito.
  • No sugieras código que se haya borrado en esta sesión.
  • No refactorices código, comentarios ni formato de alrededor.
  • Si ya existe un helper para esto, úsalo. No escribas otro.

Cada una de ellas está ahí porque vi al agente hacer lo contrario y tuve que corregirlo. Y ese, al final, es el verdadero ciclo de escritura de una skill.

Ejecútala, mira cómo se desvía, ajusta una línea

No puedes escribir una buena skill a la primera. Escribes una mediocre (mediocre está bien aquí, de verdad) y dejas que las tareas reales te digan dónde falla.

  1. Escribe la versión más pequeña que podría funcionar.
  2. Ejecútala en una tarea real, no en una de juguete.
  3. Anota el primer punto en el que la salida se apartó de lo que querías.
  4. Añade o ajusta exactamente la única instrucción que lo habría evitado.
  5. Repite.

Una divergencia por iteración. Reescribe tres instrucciones a la vez y no aprendes nada sobre cuál de ellas importaba. Y las skills acumulan líneas de cargo cult muy rápido: texto que está ahí porque alguien tuvo una vez una mala ejecución, y ahora nadie sabe decir si quitarlo cambia algo.

Para cualquier cosa de la que vayas a depender, ponle un número. Ejecuta la skill contra diez tareas representativas y cuenta cuántas necesitaron corrección. Lleva una tarde, te dice si la iteración 6 es de verdad mejor que la iteración 5, y es la única defensa contra una skill que parece mejor solo porque la escribiste tú.

"Parece correcto" no es terminado

El fallo más común de una skill que ya funciona es quedarse en "parece correcto". ¿Por qué? Porque el modelo no tiene forma de conocer tu definición de terminado a menos que esté escrita.

Así que la skill termina con una sección de verificación, y es mecánica a propósito:

## Verify
- Run the type checker on the changed files. It must pass.
- Run the linter on the changed files. It must pass.
- Print the exact headless command for the affected specs.
- List every other spec that touches the helpers you changed.

Esa última línea es la que la gente nota. "¿Qué otros tests acabo de poner en riesgo?" es una pregunta con una respuesta concreta que a nadie le gusta averiguar a mano. Justo el tipo de exhaustividad mecánica que quieres codificar una vez y olvidarte del tema.

De vuelta a la skill de migración

Para que conste, ya que este post es la continuación de aquel. Un barrido grande de APIs obsoletas no es difícil. Es tedioso de una forma muy concreta: criterio repetitivo. Miles de puntos de llamada, cada uno con una decisión que es 90% mecánica y 10% "este es distinto". Tres cosas tenían que estar en la skill:

1. Una regla de clasificación para los casos que se salen de lo normal:

  • valor sensible → debe pasar a otro mecanismo
  • valor simple → se puede reescribir en el sitio

Sin una regla escrita acabas con una base de código inconsistente, y eso es peor que cualquiera de las dos opciones aplicada de forma uniforme.

2. Un invariante que preservar. El orden de los comandos importa en este framework, y una reescritura que lo altera es incorrecta sin dar ninguna señal. Dejar explícito el invariante fue lo que evitó que ocurriera.

3. Una secuencia de verificación que ejecutar antes de cantar victoria: buscar las llamadas antiguas que hayan sobrevivido → activar la opción que convierte cualquier llamada restante en un error fatal en tiempo de ejecución → dejar que CI sea el juez. Sin eso, "parece terminado" habría sido la línea de meta.

Nada de esto es específico de la IA. Es la checklist que le darías a un contratista externo haciendo el mismo barrido. Y ese es el modelo mental que hizo que estas skills me resultaran útiles: una skill es documentación de onboarding que se ejecuta. Si no ayudaría a una persona recién contratada y competente, tampoco ayudará al agente.

De mi directorio personal al repositorio

Una última nota práctica: mantenlas independientes de la herramienta. Guardo las skills en .agents/skills/ dentro del repositorio y creo enlaces simbólicos hacia el directorio específico de la herramienta:

ln -s ../../.agents/skills/cypress-author .claude/skills/cypress-author

Son markdown plano, sin sintaxis específica de ningún proveedor en el cuerpo. Así que las mismas instrucciones sirven para el asistente que prefiera cada compañero, y viven en el repositorio, donde se revisan en pull requests como todo lo demás.

Las skills que viven en el directorio personal de alguien son el truco de productividad de esa persona. Las skills en el repositorio son infraestructura del equipo. Y ahí es exactamente donde las mías acabaron rindiendo: las que están en el repositorio son las que mi equipo ejecuta sin mí, en tareas que yo nunca tuve en mente cuando las escribí. Nada mal para una carpeta con un archivo markdown dentro.

¿Y tú? ¿Tus skills viven en el repositorio o en tu directorio personal, y cuál es la peor descripción que has escrito para una de ellas? Cuéntamelo en los comentarios. La mía ya está al principio de este post, ¡así que estás en buena compañía!