====== Skills ======
Qué es una //skill// en dos líneas está en [[cursos:sdd:02-conceptos-basicos#skills|Conceptos básicos]]; cómo se lanza y dónde se guarda, en [[cursos:sdd:03-opencode#skills|OpenCode]] y [[cursos:sdd:03-claude-code#skills|Claude Code]]. Aquí, qué va en una //skill// y qué en un agente, cómo se escriben y cómo se reparte el conocimiento del proyecto entre ''AGENTS.md'' y las //skills//.
----
===== 1. Qué es una skill =====
Una //skill// es una carpeta con un fichero de instrucciones que le dice al agente **cómo se hace** una tarea concreta en tu equipo. No es código: es contexto empaquetado y versionado.
.claude/skills/revisar-pr
├── SKILL.md <- las instrucciones
└── checklist.md <- material de apoyo, se carga solo si hace falta
---
name: revisar-pr
description: Revisa un pull request con el checklist del equipo. Usar cuando se pida revisar un PR, unos cambios o un diff.
---
# Revisión de pull request
1. Leer la descripción del PR y comprobar que hay una issue enlazada.
2. Revisar contra checklist.md, en ese orden.
3. Clasificar cada hallazgo: bloqueante, recomendable o nota.
4. No comentar estilo: de eso ya se encarga el formateador.
Lo que hace que esto escale es **cómo se cargan**: de todas las //skills// instaladas, el agente lleva siempre en contexto solo el nombre y la descripción —dos líneas—, y el cuerpo entra únicamente cuando la tarea encaja. Por eso se pueden tener veinte sin llenar la ventana de contexto.
La **descripción** es lo único que el modelo lee para decidir si la usa: [[#el_frontmatter|cómo se escribe]].
Dónde viven:
* ''.claude/skills/'' **en el proyecto**: viajan en el repositorio, se revisan en el PR y valen para todo el equipo. Es el caso normal. OpenCode también lee esta carpeta, así que una sola vale para las dos herramientas.
* ''~/.claude/skills/'' **en tu casa**: tus manías, en todos los proyectos.
Los comandos ''/kiro-*'' de [[cursos:sdd:11-kiro|Kiro]] son exactamente esto: cc-sdd instala el flujo SDD completo como //skills// dentro del proyecto.
**Cuándo escribir una**: cuando algo se repite y sale distinto cada vez, cuando hay un procedimiento del equipo que hoy solo está en la cabeza de alguien, o para el detalle del proyecto que solo hace falta en algunas tareas ([[#pequenoel_detalle_va_en_skills|AGENTS.md pequeño]]). Lo que no puede hacer una //skill// es **actuar**: solo guía cómo se actúa.
----
===== 2. Cómo se escribe una skill =====
==== Skill o agente ====
Una //skill// y un [[cursos:sdd:07-agentes|agente]] son los dos un markdown con frontmatter, pero hacen cosas distintas: **la //skill// es el conocimiento** y **el agente organiza el trabajo**. Lo decide una pregunta: **¿cambiaría si el proyecto fuera otro?** Si cambia, es conocimiento y va en una //skill//.
^ Qué es ^ Skill ^ Agente ^
| Convenciones, patrones y vocabulario del proyecto | ✓ | |
| Ejemplos ✅/❌, plantillas, documentación de terceros | ✓ | |
| Procedimiento de una tarea sin delegar («cómo se revisa un PR aquí») | ✓ | |
| Rol, sesgo que evitar y criterio de bien o mal | | ✓ |
| Herramientas permitidas y modelo | | ✓ |
| Lanzar subagentes y juntar lo que devuelven | | ✓ |
| Cuándo para: límite de vueltas y condiciones de parada | | ✓ |
| Formato cerrado de la respuesta (''DONE'', ''BLOCKED'') | | ✓ |
| ''name'' y ''description'' con el **cuándo** | ✓ | ✓ |
| Ejecutar scripts | ✓ | ✓ |
Un agente es **un solo fichero ''.md'', sin carpeta**: no tiene dónde guardar ejemplos, plantillas ni scripts. Lo que necesita saber lo carga de una //skill//, y los scripts que ejecuta están en la carpeta ''scripts/'' de una //skill//.
El procedimiento de una tarea que hace el propio agente, como ''/revisar-pr 128'', es una //skill//. En cuanto reparte el trabajo entre subagentes y junta lo que devuelven, es un agente.
==== El frontmatter ====
Dos campos, los dos obligatorios:
* ''name'': el mismo que el nombre de la carpeta.
* ''description'': **qué hace y cuándo usarla**, en tercera persona y con las palabras con las que se pedirá la tarea. Es lo único que el modelo lee siempre: con ella decide si la carga. El proceso no va aquí, va en el cuerpo. Máximo 1.024 caracteres.
# ✅ qué cubre, cuándo usarla y con qué palabras se pide
description: Convenciones de los servicios de Pedidos (transacciones, validación,
errores de negocio). Usar al escribir, revisar o probar una clase *Service.
# ❌ no dice cuándo: no se carga nunca
description: Utilidades para servicios.
# ❌ cuenta el proceso, que va en el cuerpo, y no dice cuándo
description: Primero lee el servicio, luego revisa las transacciones y lanza los tests.
==== La carpeta ====
Solo el ''SKILL.md'' es obligatorio; cada carpeta aparece únicamente si la //skill// tiene ese tipo de contenido.
.claude/skills/servicios/
├── SKILL.md <- obligatorio: las reglas y el índice de los demás ficheros
├── transacciones.md <- un tema que solo hace falta a veces
├── templates/ <- texto literal para copiar y rellenar
├── examples/ <- casos resueltos, para ver el resultado
├── references/ <- documentación de terceros copiada tal cual
└── scripts/ <- código que se ejecuta, no se lee
* **''.md''**: lo que solo hace falta en algunas tareas sale del ''SKILL.md'' a su fichero, que se carga solo cuando la tarea toca ese tema.
* **''templates/''**: un fichero con estructura fija se da como plantilla literal; descrito en prosa, el modelo se inventa el formato.
* **''examples/''**: un caso resuelto entero. No es normativo: una regla que solo está en un ejemplo no es una regla.
* **''references/''**: la documentación de una librería sin adaptar. La regla del proyecto va en la raíz y apunta aquí.
* **''scripts/''**: ver [[#scripts|scripts]].
==== El SKILL.md ====
Detrás del frontmatter, una frase de qué cubre y, si hay más ficheros, **la tabla índice**: cada fichero con **cuándo cargarlo**. Un fichero que no está en la tabla no lo lee nadie.
---
name: servicios
description: Convenciones de los servicios de Pedidos (transacciones, validación,
errores de negocio). Usar al escribir, revisar o probar una clase *Service.
---
# servicios
Reglas de las clases `*Service` del servidor.
## Índice
| Fichero | Qué contiene | Cuándo cargarlo |
|---|---|---|
| `transacciones.md` | Qué métodos son transaccionales y cómo | Al escribir un método que guarda |
| `templates/service.java` | Esqueleto de un servicio nuevo | Al crear un servicio |
## Convenciones
- Un servicio por agregado: `PedidoService`, no `PedidoLineaService`.
- Valida al entrar y lanza `ErrorDeNegocio` con el código de `specs/`.
- No devuelve entidades: devuelve DTOs.
## Ejemplos
- ✅ `throw new ErrorDeNegocio("R-12", "El pedido ya está enviado")`
- ❌ `throw new IllegalStateException("No se puede")` (no dice qué requisito incumple)
## Nunca
- Llamar a un repositorio de otro agregado: se pasa por su servicio.
==== Cómo se redacta ====
Una //skill// se lee **para el modelo**, no para una persona, y cada línea cuesta tokens cada vez que se carga.
* **La prueba de cada línea**: ¿cambiaría lo que hace el modelo si la quito? Si no, sobra.
* **Nada que ya sepa**: qué es JPA o cómo funciona git. Solo lo propio del proyecto.
* **Nada que se deduzca del código**: la lista de clases o de paquetes se queda vieja; se dice dónde mirarla.
* **Listas, no párrafos**: una regla o un paso por punto.
* **Ejemplos ✅/❌**, y cada ❌ con su porqué entre paréntesis. Si una regla cabe en un ejemplo, va como ejemplo.
* **Números, no adjetivos**: «máximo 3 intentos», no «unos pocos».
* **''MUST'' y ''MUST NOT'' solo en lo que de verdad no puede fallar**: si están por todas partes, dejan de pesar.
* **Cada regla en un solo fichero**: los demás la citan con un puntero, no la repiten.
* **Máximo unas 2.500 palabras por fichero**: si pasa, se parte por temas.
==== Scripts ====
Lo que es determinista (validar un fichero, calcular una tabla, contar) va en un script de ''scripts/'': es más fiable que pedírselo al modelo y no gasta contexto, porque solo entra su salida. Lo pueden ejecutar la //skill// y un [[cursos:sdd:07-agentes|agente]].
* Se cita con **el comando exacto** y la palabra «ejecuta».
✅ Ejecuta `python3 .claude/skills/servicios/scripts/sin-transaccion.py src/main/java`.
❌ Lee scripts/sin-transaccion.py y haz lo que dice. (un script se ejecuta, no se lee)
❌ Usa el script de transacciones. (sin el comando, el modelo se inventa los argumentos)
* **Los errores dicen cómo arreglarlo**: el modelo corrige a partir de ese texto.
* **Lo que necesita** (intérprete, librerías) se dice en el ''SKILL.md''.
----
===== 3. AGENTS.md =====
''AGENTS.md'' es un markdown en la raíz del repositorio con las instrucciones fijas del proyecto: lo que le contarías a un compañero nuevo el primer día. **Se carga entero en todas las sesiones**, encaje o no con la tarea. Es un [[https://agents.md/|estándar abierto]]: el mismo fichero lo leen Claude Code, OpenCode, Codex, Cursor, Copilot o Gemini CLI.
==== Pequeño: el detalle va en skills ====
Como se paga en cada petición, ''AGENTS.md'' tiene que ser **pequeño**: solo lo imprescindible y un índice. El detalle se reparte en [[#que_es_una_skill|skills]], una por tema, y el agente carga solo la que necesita para la tarea.
AGENTS.md
.claude/skills/
├── producto/
│ └── SKILL.md
├── tecnologia/
│ └── SKILL.md
├── arquitectura/
│ ├── SKILL.md
│ ├── cliente.md
│ └── servidor.md
└── despliegue/
├── SKILL.md
├── desarrollo.md
└── produccion.md
Las que tiene que haber como mínimo:
* ''producto'': para qué sirve el producto, qué valor aporta y sus capacidades principales.
* ''tecnologia'': el stack, los frameworks, las decisiones técnicas y las restricciones del sistema completo.
* ''arquitectura'': organización de directorios, patrones de arquitectura y convenciones de nombres.
* ''despliegue'': cómo se despliega la aplicación, lo común a todos los entornos.
Si hay varias arquitecturas, el ''SKILL.md'' se queda con lo común y cada una va en un fichero de apoyo dentro de la //skill//: ''cliente.md'', ''servidor.md'', ''movil.md''. Con el despliegue igual: ''desarrollo.md'' y ''produccion.md'' con lo propio de cada entorno.
---
name: arquitectura
description: Carpetas, patrones y nombres del proyecto. Usar antes de crear
cualquier clase o fichero.
---
# Arquitectura
- Un paquete por funcionalidad (`pedidos`, `clientes`), no por capa.
- Los controladores solo validan y delegan: la lógica va en los servicios.
Lee además `servidor.md` si tocas `servidor/` y `cliente.md` si tocas `cliente/`.
''AGENTS.md'' dice **cuándo** usar cada una:
# Pedidos
API REST de pedidos con cliente web. Compilar y probar: `./mvnw verify`.
## Skills del proyecto
Antes de empezar, lee la skill que necesite la tarea:
- `.claude/skills/producto/SKILL.md`: antes de escribir o revisar una especificación.
- `.claude/skills/tecnologia/SKILL.md`: antes de añadir una dependencia.
- `.claude/skills/arquitectura/SKILL.md`: antes de crear cualquier clase o fichero.
- `.claude/skills/despliegue/SKILL.md`: antes de tocar el despliegue.
**La //skill// sola no basta.** El agente la carga solo si decide que encaja con la tarea, y muchas veces no lo decide: en las [[https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals|pruebas de Vercel]] no llegó a usarse en más de la mitad de los casos. El índice de ''AGENTS.md'' está siempre en contexto, así que convierte esa decisión en una instrucción. Y como da la ruta del fichero, funciona también en un agente que no sepa de //skills//.
Cómo generar un primer ''AGENTS.md'' con ''/init'' y cómo mantenerlo: [[cursos:sdd:03-opencode#init|/init en OpenCode]].
==== CLAUDE.md: no usarlo ====
Existe también ''CLAUDE.md'', el fichero propio de Claude Code. **No lo uses**: si en una carpeta hay ''CLAUDE.md'', Claude Code lee solo ese y **deja de leer el ''AGENTS.md''** de esa misma carpeta, sin avisar. El equipo que usa otra herramienta ve unas normas y el que usa Claude Code ve otras.
Como basta con que alguien cree un ''CLAUDE.md'' para que el ''AGENTS.md'' deje de valer, se añade una **regla de arquitectura** que lo impida: un test que falla si aparece alguno en el repositorio.
class SinClaudeMdTest {
@Test
void noHayNingunClaudeMd() throws IOException {
try (Stream ficheros = Files.walk(Path.of("."))) {
List claudeMd = ficheros
.filter(f -> !f.startsWith("./target") && !f.startsWith("./.git"))
.filter(f -> f.getFileName().toString().equalsIgnoreCase("CLAUDE.md"))
.toList();
assertThat(claudeMd)
.as("Las instrucciones van en AGENTS.md, no en CLAUDE.md")
.isEmpty();
}
}
}
----
===== 4. Cómo se organiza AGENTS.md =====
La [[#agentsmd|sección 3]] dice que ''AGENTS.md'' es un índice pequeño. Aquí va qué entra en él, dónde va todo lo demás y cómo se escriben las referencias para que funcionen igual en Claude Code y en OpenCode.
==== Qué entra ====
El agente **obedece** lo que pone el fichero: en el [[https://arxiv.org/abs/2602.11988|estudio de ETH Zurich]], cuando ''AGENTS.md'' nombra una herramienta, el agente la usa en casi todas las tareas, y si no la nombra, casi nunca. Pero el fichero encarece cada tarea más de un 20 %, y solo mejora el resultado cuando cuenta lo que no es estándar. Así que entra solo lo que vale **para todas las tareas** y **no se deduce del código**:
* **Una frase** con qué es el proyecto.
* **Órdenes** para compilar, probar y comprobar, si no son las habituales.
* **Convenciones que se apartan de lo normal**: las que el agente no adivinaría leyendo el código.
* **Límites**: lo que no se hace nunca y lo que se pregunta antes.
* **El índice de //skills//**, con cuándo leer cada una.
Fuera: la descripción general del proyecto, el árbol de carpetas, la lista de dependencias y las reglas de estilo. Las tres primeras el agente las saca del propio código, y en el estudio no le ayudaron a encontrar antes los ficheros que tenía que tocar. El estilo lo impone el formateador, no un párrafo.
**No dejes tal cual el ''AGENTS.md'' que genera ''/init''.** Mete justo lo que sobra: descripción, arquitectura y dependencias. Los ficheros generados por el modelo salen peor que los escritos a mano. Úsalo de borrador y recorta.
# Pedidos
API REST de pedidos con cliente web.
## Órdenes
- Compilar y probar: `./mvnw verify`
- Solo los tests del servidor: `./mvnw -pl servidor test`
## Convenciones
- Los importes son `BigDecimal` con escala 2; nunca `double`.
- Los errores de negocio heredan de `ErrorDeNegocio`; los controladores no lanzan `RuntimeException`.
- Cada requisito de `specs/` tiene al menos un test que cita su identificador (`R-12`).
## Límites
- No modifiques una migración ya aplicada: crea una nueva.
- Pregunta antes de añadir una dependencia o de cambiar un requisito de `specs/`.
## Skills del proyecto
Explora primero el código que toca la tarea. Después lee la skill que necesite:
- `.claude/skills/producto/SKILL.md`: antes de escribir o revisar una especificación.
- `.claude/skills/tecnologia/SKILL.md`: antes de añadir una dependencia.
- `.claude/skills/arquitectura/SKILL.md`: antes de crear cualquier clase o fichero.
- `.claude/skills/despliegue/SKILL.md`: antes de tocar el despliegue.
Cabe en una pantalla, y así tiene que seguir: **menos de 200 líneas**, mejor menos de 60. Cada instrucción de más hace que el modelo cumpla peor todas las demás, no solo la nueva.
==== Dónde va lo demás ====
^ Qué es ^ Dónde va ^ Ejemplo ^
| Lo que vale en todas las tareas | ''AGENTS.md'' raíz | «Los importes son ''BigDecimal''» |
| Lo que vale solo en una carpeta | ''AGENTS.md'' de esa carpeta | ''servidor/src/test/AGENTS.md'': «los tests de integración crean los pedidos con ''PedidoFactory''; no se mockea el repositorio» |
| El detalle que solo hace falta en algunas tareas | Una //skill// | ''arquitectura'', ''despliegue'' |
| Un procedimiento que se lanza para una tarea concreta | Una //skill// | ''revisar-pr'' |
| Lo que tiene que cumplirse siempre | Un test, el linter o un //hook// | ''SinClaudeMdTest'', el formateador |
* **''AGENTS.md'' por carpeta**: Claude Code y OpenCode lo cargan cuando el agente trabaja con ficheros de esa carpeta. Solo se crea si sus normas difieren de las de la raíz, y **no puede contradecirla**: cada herramienta los junta en un orden distinto, así que no está claro cuál gana.
* **Lo que tiene que cumplirse siempre** no va en ''AGENTS.md'': ahí es una petición, no una garantía. Si de verdad no puede fallar, un test que lo compruebe, como el de la [[#claudemdno_usarlo|regla de ''CLAUDE.md'']].
==== Cómo se escriben las referencias ====
Cada referencia lleva **la ruta entre comillas invertidas** y **cuándo leerla**. Nunca con ''@'':
^ Referencia ^ Claude Code ^ OpenCode ^
| ''`.claude/skills/arquitectura/SKILL.md`: antes de crear cualquier clase o fichero.'' | La lee cuando la tarea lo pide | La lee cuando la tarea lo pide |
| ''@.claude/skills/arquitectura/SKILL.md'' | La carga entera al arrancar, en todas las sesiones | No la entiende: es texto |
| ''Ver la skill de arquitectura.'' | No sabe cuándo leerla | No sabe cuándo leerla |
**El ''@'' anula el índice.** En Claude Code, ''@ruta'' importa el fichero al arrancar, así que un índice escrito con ''@'' carga todas las //skills// en cada sesión: lo mismo que meterlas en ''AGENTS.md''. El ejemplo de la [[https://opencode.ai/docs/rules/|documentación de OpenCode]] usa ''@'' y en Claude Code hace justo eso.
La condición se escribe con **las palabras con las que se pedirá la tarea** («antes de escribir o revisar una especificación»), sin «MUST» ni mayúsculas. En la [[https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals|prueba de Vercel]], «explora primero el proyecto y luego usa la //skill//» acertó más que «debes usar la //skill//»: con la orden tajante, el agente leía la documentación primero, seguía sus ejemplos sin mirar el proyecto y se dejaba cambios.
Lo mismo vale para la ''description'' de cada //skill// ([[#el_frontmatter|el frontmatter]]): las //skills// se activan casi por palabra clave. En la [[https://scottspence.com/posts/measuring-claude-code-skill-activation-with-sandboxed-evals|medición de Scott Spence]], con la palabra en el prompt se activaban casi siempre; con una forma genérica de pedirlo, entre un 20 y un 40 % de las veces.
----
===== Fuentes =====
* [[https://agents.md/|AGENTS.md]]: el estándar, con ejemplos y la lista de herramientas que lo leen.
* [[https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals|AGENTS.md outperforms skills in our agent evals]]: la prueba de Vercel. Índice en ''AGENTS.md'': 100 %; //skill// sola: 53 %; //skill// con instrucción explícita: 79 %. La //skill// no llegó a usarse en el 56 % de los casos.
* [[https://agentskills.io/specification|Specification - Agent Skills]]: el estándar de las //skills//: formato de ''SKILL.md'' y carga por niveles (descripción, cuerpo, ficheros de apoyo).
* [[https://dreaming.press/posts/agents-md-vs-agent-skills-evals.html|AGENTS.md vs Agent Skills evals]]: lectura crítica de la prueba de Vercel. Lo que decide es dónde está el aviso de cargar la documentación (siempre en contexto o a decisión del modelo), no el formato.
* [[https://scottspence.com/posts/measuring-claude-code-skill-activation-with-sandboxed-evals|Measuring Claude Code skill activation]]: otra medición. Sin ayuda, las //skills// se activan solas la mitad de las veces; cuando se activan, siempre es la correcta.
* [[https://aihero.dev/a-complete-guide-to-agents-md|A complete guide to AGENTS.md]]: ''AGENTS.md'' mínimo y el detalle en ficheros enlazados por tema; qué no meter en él.
* [[https://skills.cat/skills/heykvnzhao/dotfiles/agents-md-best-practices|agents-md-best-practices]]: //skill// que parte un ''AGENTS.md'' grande en un índice y un fichero por tema.
* [[https://github.com/opsmill/infrahub-sdk-python/pull/609|infrahub-sdk-python PR #609]]: caso real. Un ''CLAUDE.md'' de 317 líneas pasa a un ''AGENTS.md'' de 77 más un ''AGENTS.md'' por carpeta; después el repositorio añadió //skills// para sus procedimientos.
* [[https://www.humanlayer.dev/blog/writing-a-good-claude-md|Writing a good CLAUDE.md]]: por qué cada instrucción de más empeora el cumplimiento del resto, y la carpeta de documentos enlazada desde el índice.
* [[https://arxiv.org/abs/2602.11988|Evaluating AGENTS.md]]: estudio de ETH Zurich. Los ficheros de contexto encarecen más de un 20 % cada tarea y en general no mejoran el resultado; sí ayudan cuando cuentan prácticas no estándar del proyecto.
* [[https://code.claude.com/docs/en/memory|Claude Code: memory]]: menos de 200 líneas; los procedimientos y lo que vale solo para una parte del código, a //skills//; ''@ruta'' no ahorra contexto porque carga el fichero al arrancar.
* [[https://code.claude.com/docs/en/features-overview|Claude Code: features overview]]: cuándo usar el fichero de instrucciones, //skills//, subagentes o //hooks//; el reparto «el fichero dice qué seguir y la //skill// tiene la guía».
* [[https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more|Steering Claude Code]]: el fichero de instrucciones como índice que apunta a otros ficheros.
* [[https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills|Equipping agents for the real world with Agent Skills]]: por qué las //skills// se cargan por niveles y qué pueden llevar dentro (scripts, plantillas).
* [[https://opencode.ai/docs/rules/|OpenCode: rules]]: OpenCode no sigue solo las rutas que aparecen en ''AGENTS.md''; hay que decirle cuándo leer cada fichero.
* [[https://opencode.ai/docs/skills/|OpenCode: skills]]: en qué carpetas busca //skills//, ''.claude/skills/'' incluida.