====== 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.