cursos:sdd:09-creando-skills
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| cursos:sdd:09-creando-skills [2026/11/05 22:23] – Renumera el tema y sus referencias tras añadir el tema 7 (AGENTS.md) claude | cursos:sdd:09-creando-skills [2026/11/06 08:37] (actual) – Renumerar el curso: Estructura de un skill pasa al 10 y los temas siguientes suben un número: movida a cursos:sdd:10-creando-skills claude | ||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| - | ====== 9. Estructura de un skill ====== | ||
| - | |||
| - | Qué es una //skill//, su frontmatter y cómo se redacta están en [[cursos: | ||
| - | Más información: | ||
| - | |||
| - | * [[https:// | ||
| - | * [[https:// | ||
| - | * [[https:// | ||
| - | * [[https:// | ||
| - | |||
| - | |||
| - | Cada //skill// es una carpeta dentro de la carpeta de //skills// del proyecto. La carpeta en concreto depende de la herramienta: | ||
| - | |||
| - | * **OpenCode**: | ||
| - | * **Claude Code**: '' | ||
| - | |||
| - | OpenCode también lee '' | ||
| - | |||
| - | ---- | ||
| - | |||
| - | ===== 1. Tipos de skills ===== | ||
| - | |||
| - | Hay dos tipos de //skills//: | ||
| - | |||
| - | * **Las que saben cosas**: describen las convenciones del proyecto (cómo son los servicios, cómo se escriben los tests). No hacen nada solas: las cargan otras //skills// y los agentes. | ||
| - | * **Las que hacen cosas**: ejecutan un proceso por fases (crear un servicio, revisar un PR). Las lanzas tú con ''/'' | ||
| - | |||
| - | Lo que hace una //skill// que hace cosas es, en el fondo, el trabajo de un [[cursos: | ||
| - | |||
| - | * **Un agente no tiene carpeta propia.** Es un único fichero en '' | ||
| - | * **Lanzarlo es más engorroso.** En Claude Code un agente se lanza con '' | ||
| - | <sxh bash> | ||
| - | @agent-crear-servicio R-12 | ||
| - | / | ||
| - | </ | ||
| - | |||
| - | Normalmente no hace falta convertirla en agente: lo que aporta un agente es empezar con el contexto vacío, y eso ya se consigue lanzando la //skill// en una sesión limpia, con ''/ | ||
| - | |||
| - | <sxh markdown; | ||
| - | --- | ||
| - | name: do-crear-servicio | ||
| - | description: | ||
| - | context: fork | ||
| - | --- | ||
| - | </ | ||
| - | |||
| - | |||
| - | |||
| - | <note tip> | ||
| - | |||
| - | ===== 2. El nombre ===== | ||
| - | |||
| - | El nombre de la //skill// (su carpeta y su '' | ||
| - | |||
| - | * **'' | ||
| - | * **'' | ||
| - | |||
| - | Detrás del prefijo, en // | ||
| - | |||
| - | Ventajas del prefijo: | ||
| - | |||
| - | * **No chocan con los comandos de Claude Code**, que también se lanzan con ''/'' | ||
| - | * **Escribiendo ''/ | ||
| - | |||
| - | |||
| - | ===== 3. Estructura de carpetas y ficheros ===== | ||
| - | |||
| - | Una //skill// no suele ser un único '' | ||
| - | |||
| - | ==== Qué hay en cada carpeta ==== | ||
| - | |||
| - | Qué hace cada pieza está en [[cursos: | ||
| - | |||
| - | ^ Carpeta o fichero ^ Contiene ^ Ejemplo ^ | ||
| - | | '' | ||
| - | | ''< | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | |||
| - | ==== Qué carpetas tiene cada tipo ==== | ||
| - | |||
| - | Las que suele tener cada [[# | ||
| - | |||
| - | ^ Carpeta ^ Skill de conocimiento ('' | ||
| - | | '' | ||
| - | | ''< | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | La de conocimiento guarda lo que **se sabe**: temas, ejemplos y documentación. La que hace guarda lo que **se ejecuta**: subagentes, plantillas de lo que genera y scripts. Si una '' | ||
| - | |||
| - | ==== Ejemplo: k-servicios ==== | ||
| - | |||
| - | Para explicar la estructura de carpetas de un skill , lo vamos a hacer con un ejemplo de un skill que " | ||
| - | |||
| - | <sxh text; | ||
| - | .claude/ | ||
| - | ├── SKILL.md | ||
| - | ├── transacciones.md | ||
| - | ├── templates/ | ||
| - | │ | ||
| - | ├── examples/ | ||
| - | │ | ||
| - | ├── references/ | ||
| - | │ | ||
| - | ├── scripts/ | ||
| - | │ | ||
| - | └── assets/ | ||
| - | └── errores.schema.json | ||
| - | |||
| - | </ | ||
| - | |||
| - | ==== Ejemplo: do-crear-servicio ==== | ||
| - | |||
| - | La //skill// que crea un servicio a partir de un requisito de '' | ||
| - | |||
| - | <sxh text; | ||
| - | .claude/ | ||
| - | ├── SKILL.md | ||
| - | ├── agents/ | ||
| - | │ | ||
| - | ├── templates/ | ||
| - | │ | ||
| - | └── scripts/ | ||
| - | └── sin-test.py | ||
| - | |||
| - | </ | ||
| - | |||
| - | |||
| - | ===== 4. SKILL.md y < | ||
| - | En el fichero '' | ||
| - | |||
| - | El motivo de hace esto es para ahorrar contexto. A veces un skill trata de varios temas relacionados. Por ejemplo, si vamos a cear un CRUD, podríamos tener un skill que sepa hacer CRUDs y en ese caso hablaría sobre controladores, | ||
| - | |||
| - | |||
| - | ==== La description y la frase de entrada ==== | ||
| - | |||
| - | La '' | ||
| - | |||
| - | ^ ^ '' | ||
| - | | Cuándo la lee | Siempre: está en contexto junto con las de todas las //skills// | Solo cuando la //skill// ya está cargada | | ||
| - | | Para qué | Decidir si carga la //skill// | Saber qué es y cómo actuar | | ||
| - | | Qué dice | Qué es y **cuándo usarla**, con las palabras que escribiría el usuario | En las '' | ||
| - | |||
| - | <sxh markdown; | ||
| - | --- | ||
| - | name: do-crear-servicio | ||
| - | description: | ||
| - | specs/. Usar cuando se pida crear, añadir o generar un servicio o una clase *Service. | ||
| - | --- | ||
| - | |||
| - | # do-crear-servicio | ||
| - | |||
| - | Eres un desarrollador del servidor: conviertes un requisito de `specs/` en un `*Service` con su test. | ||
| - | </ | ||
| - | |||
| - | La frase de entrada es imprescindible cuando la //skill// se ejecuta sin pasar por la '' | ||
| - | |||
| - | * **Con '' | ||
| - | * **Cuando la lanzas tú con ''/ | ||
| - | |||
| - | <note tip>Si la frase de entrada repite la '' | ||
| - | |||
| - | |||
| - | ===== 5. El índice ===== | ||
| - | |||
| - | La tabla índice del '' | ||
| - | |||
| - | * **Un fichero que no está en la tabla es un huérfano**: | ||
| - | * **'' | ||
| - | * **Cada fichero se cita además donde se usa**, diciendo cuándo cargarlo. La tabla da la visión de conjunto; la cita, el momento. | ||
| - | <sxh markdown> | ||
| - | ✅ En la Fase 2, copia `templates/ | ||
| - | ❌ Ver también `templates/ | ||
| - | </ | ||
| - | * **Todo '' | ||
| - | |||
| - | ---- | ||
| - | |||
| - | ===== 6. Dos tipos de skill ===== | ||
| - | |||
| - | |||
| - | ==== Skill de conocimiento ==== | ||
| - | |||
| - | <sxh markdown; | ||
| - | --- | ||
| - | name: k-servicios | ||
| - | description: | ||
| - | errores de negocio). Usar al escribir, revisar o probar una clase *Service. | ||
| - | --- | ||
| - | |||
| - | # k-servicios | ||
| - | |||
| - | Reglas de las clases `*Service` del servidor. La cargan `do-crear-servicio` y `do-revisar-pr`. | ||
| - | |||
| - | ## Índice | ||
| - | |||
| - | | Fichero | ||
| - | |-----------------------------|----------------------------------------| | ||
| - | | `transacciones.md` | ||
| - | | `templates/ | ||
| - | |||
| - | ## 1. Conceptos clave | ||
| - | < | ||
| - | |||
| - | ## 2. Convenciones del proyecto | ||
| - | <solo lo propio del proyecto, no lo del framework> | ||
| - | |||
| - | ## 3. Patrones recomendados | ||
| - | < | ||
| - | |||
| - | ## 4. Ejemplos ✅/❌ | ||
| - | <casos correctos e incorrectos, | ||
| - | |||
| - | ## 5. Anti-patrones | ||
| - | <lo que no se hace nunca y por qué> | ||
| - | </ | ||
| - | |||
| - | * **H1 igual que el '' | ||
| - | * **Frase de entrada**: qué cubre y **quién la usa**, para que el modelo sepa si es la que busca. | ||
| - | |||
| - | ==== Skill de procedimiento ==== | ||
| - | |||
| - | Sigue la estructura de los comandos de [[https:// | ||
| - | |||
| - | <sxh markdown; | ||
| - | --- | ||
| - | name: do-crear-servicio | ||
| - | description: | ||
| - | specs/. Usar cuando se pida crear, añadir o generar un servicio o una clase *Service. | ||
| - | --- | ||
| - | |||
| - | # do-crear-servicio | ||
| - | |||
| - | Eres un desarrollador del servidor: conviertes un requisito de `specs/` en un `*Service` con su test. | ||
| - | |||
| - | ## Índice | ||
| - | |||
| - | | Fichero | ||
| - | |-----------------------------|-----------------------------------------| | ||
| - | | `templates/ | ||
| - | | `agents/ | ||
| - | | `scripts/ | ||
| - | | `evals/ | ||
| - | |||
| - | ## Formato de entrada | ||
| - | |||
| - | ```text | ||
| - | $ARGUMENTS | ||
| - | ``` | ||
| - | |||
| - | You **MUST** consider the user input before proceeding (if not empty). Se espera el | ||
| - | identificador del requisito (`R-12`) y, opcionalmente, | ||
| - | |||
| - | ## Outline | ||
| - | |||
| - | 1. **Leer** el requisito (Fase 1). | ||
| - | 2. **Escribir** el servicio y su test (Fase 2). | ||
| - | 3. **Comprobar** que el requisito tiene test y pasa (Fase 3). | ||
| - | |||
| - | **STOP conditions**: | ||
| - | |||
| - | - No hay ningún requisito con ese identificador → **ERROR** y detente. | ||
| - | - El servicio ya existe → **STOP** y pregunta antes de sobrescribirlo. | ||
| - | |||
| - | ## 1. Fase 1 — Leer el requisito | ||
| - | |||
| - | 1. Busca el identificador en `specs/`. | ||
| - | 2. Carga la skill `k-servicios`. | ||
| - | |||
| - | ## 2. Fase 2 — Escribir el servicio | ||
| - | |||
| - | 1. Escribe el servicio con la plantilla de `k-servicios`. | ||
| - | 2. Copia `templates/ | ||
| - | |||
| - | ## 3. Fase 3 — Comprobar | ||
| - | |||
| - | 1. Ejecuta `python3 .claude/ | ||
| - | 2. Lanza un subagente con model: haiku que lea `agents/ | ||
| - | 3. Ejecuta `./mvnw -pl servidor test`. | ||
| - | |||
| - | **LIMIT**: máximo 3 vueltas de corrección; | ||
| - | |||
| - | ## Quick Guidelines | ||
| - | |||
| - | - Un servicio por agregado. | ||
| - | - Ningún requisito sin su test. | ||
| - | - Si el requisito es ambiguo, pregunta: no lo interpretes. | ||
| - | </ | ||
| - | |||
| - | Las secciones, en este orden: | ||
| - | |||
| - | * **Frase de entrada**: el **rol** que asume el modelo y **qué transforma en qué**. | ||
| - | * **''## | ||
| - | * **''## | ||
| - | * **Una sección por fase** del Outline, con sus pasos. | ||
| - | * **''## | ||
| - | |||
| - | ==== Palabras clave ==== | ||
| - | |||
| - | El cuerpo va en español, pero las palabras que marcan una orden van **en inglés y en negrita**: el modelo les da más peso que a «debes» o «es importante». | ||
| - | |||
| - | ^ Palabra ^ Para qué ^ | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | Solo en lo que de verdad no puede fallar ([[cursos: | ||
| - | |||
| - | ==== Si genera un fichero: checklist y vueltas ==== | ||
| - | |||
| - | Una //skill// que escribe un fichero termina esa fase con un **checklist** que el modelo repasa antes de dar el fichero por bueno, y un **'' | ||
| - | |||
| - | <sxh markdown> | ||
| - | ### Checklist del servicio | ||
| - | |||
| - | - [ ] ¿Cada método público valida su entrada? | ||
| - | - [ ] ¿Cada requisito de `specs/` tiene un test con su identificador? | ||
| - | |||
| - | **MUST NOT** dar el servicio por terminado con algún punto sin cumplir. | ||
| - | **LIMIT**: máximo 3 vueltas de corrección; | ||
| - | </ | ||
| - | |||
| - | ==== agents/: los subagentes ==== | ||
| - | |||
| - | Si una fase delega en un subagente (comprobar, revisar, juzgar), su rol va en un fichero de '' | ||
| - | |||
| - | <sxh markdown> | ||
| - | ✅ Lanza un subagente con model: haiku que lea `agents/ | ||
| - | ❌ Lanza un subagente que lea `agents/ | ||
| - | </ | ||
| - | |||
| - | Todos los ficheros de '' | ||
| - | |||
| - | <sxh markdown; | ||
| - | # Verificador | ||
| - | |||
| - | Comprueba que un requisito tiene su test y que el test prueba lo que pide el requisito. | ||
| - | |||
| - | ## Rol | ||
| - | Revisas el trabajo de otro sin haberlo visto hacer. No le das la razón por haberlo intentado. | ||
| - | |||
| - | ## Entradas | ||
| - | Te llegan en el prompt: | ||
| - | - `requisito`: | ||
| - | - `ruta_test`: | ||
| - | |||
| - | ## Proceso | ||
| - | 1. Lee el requisito en `specs/`. | ||
| - | 2. Lee el test y busca el identificador en su nombre. | ||
| - | 3. Comprueba que cada condición del requisito tiene su aserción. | ||
| - | |||
| - | ## Criterios | ||
| - | - OK cuando: el test cita el requisito y comprueba todas sus condiciones. | ||
| - | - Fallo cuando: falta el identificador o alguna condición no tiene aserción. | ||
| - | - En la duda: fallo. | ||
| - | |||
| - | ## Salida | ||
| - | La primera línea es exactamente `PASS R-12` o `FAIL R-12`; debajo, una línea por condición sin probar. | ||
| - | ✅ `FAIL R-12` / `Sin aserción: el pedido enviado no se puede cancelar.` | ||
| - | ❌ `Parece que el test está bastante bien.` (el que lo lanza no puede comparar eso) | ||
| - | |||
| - | ## Pautas | ||
| - | - **MUST NOT** modificar el test: solo dice qué falta. | ||
| - | </ | ||
| - | |||
| - | * **Autocontenido**: | ||
| - | * **Criterios explícitos**: | ||
| - | * **Salida cerrada**: palabras literales ('' | ||
| - | * **Modelo barato si el rol es mecánico**: | ||
| - | |||
| - | <note warning> | ||
| - | |||
| - | ==== El siguiente paso lo lanzas tú ==== | ||
| - | |||
| - | Una //skill// de procedimiento **no lanza la siguiente** cuando decides tú cuándo se sigue: termina diciendo la orden exacta y para. | ||
| - | |||
| - | <sxh markdown> | ||
| - | ✅ Servicio creado. Siguiente paso: `/ | ||
| - | ❌ Servicio creado. Ahora lanzo do-revisar-pr. (te quita la revisión de lo generado) | ||
| - | </ | ||
| - | |||
| - | ===== 7. Argumentos de entrada ===== | ||
| - | |||
| - | Lo que escribes detrás de ''/ | ||
| - | |||
| - | <sxh bash> | ||
| - | /do-test unit create PedidoService | ||
| - | /do-test api create Pedido: alta válida, sin cliente, cliente que no existe | ||
| - | /do-test e2e repair | ||
| - | </ | ||
| - | |||
| - | En ese caso, el ''## | ||
| - | |||
| - | <sxh markdown; | ||
| - | --- | ||
| - | name: do-test | ||
| - | description: | ||
| - | Usar cuando se pida escribir tests, generarlos o arreglar los que fallan. | ||
| - | argument-hint: | ||
| - | --- | ||
| - | |||
| - | # do-test | ||
| - | |||
| - | Eres el responsable de los tests: los creas a partir del código o de los escenarios y reparas los que fallan. | ||
| - | |||
| - | ## Formato de entrada | ||
| - | |||
| - | ```text | ||
| - | $ARGUMENTS | ||
| - | ``` | ||
| - | |||
| - | You **MUST** consider the user input before proceeding (if not empty). El formato es | ||
| - | `< | ||
| - | |||
| - | - `tipo`: `unit`, `arch`, `api` o `e2e`. Obligatorio. | ||
| - | - `verbo`: `create` o `repair`. Obligatorio. | ||
| - | - `resto`: todo lo que va detrás del verbo, tal cual. | ||
| - | - `unit create`: una clase o un paquete. Si no hay, las clases de `domain` sin tests. | ||
| - | - `arch create`: las reglas de arquitectura, | ||
| - | - `api create` y `e2e create`: los escenarios. Obligatorio. | ||
| - | - `repair`: no lleva. | ||
| - | |||
| - | **STOP conditions**: | ||
| - | |||
| - | - Falta el tipo o el verbo, o no es uno de los valores → **ERROR** con la forma de uso | ||
| - | y detente. | ||
| - | - `api create` o `e2e create` sin escenarios → **STOP** y pide los escenarios. | ||
| - | </ | ||
| - | |||
| - | * **'' | ||
| - | * **'' | ||
| - | |||
| - | <note important> | ||
| - | |||
| - | <note important> | ||
| - | |||
| - | ===== 8. Formato de salida ===== | ||
| - | |||
| - | Cuando una //skill// o un [[# | ||
| - | |||
| - | * **'' | ||
| - | * **'' | ||
| - | |||
| - | Ahora lo normal es que el agente nos retorne la lista de problemas que nos ha encontrado. Esa lista obviamente debe ser texto, así que podría ser un JSON , un XML, etc. | ||
| - | Pero pensar que esos formatos son demasiado estrictos, por lo que se gastarán tokens en que tenga alguno de esos formato y además puede cometer errores. | ||
| - | Por ello es mejor un formato sencillo y facil de leer. | ||
| - | |||
| - | Mi recomendación es simplemente columnas separadas por ":" | ||
| - | |||
| - | |||
| - | Ejemplos de ellos podrían ser: | ||
| - | |||
| - | ^ Formato ^ Cuándo ^ | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | Según lo que haga cada agente debes elegir el formato que más se acople a tu problema. | ||
| - | |||
| - | Lo mismo pasa con el tipo. A modo de ejemplo te indico posibles valores: | ||
| - | |||
| - | ^ Agente ^ Valores ^ Qué miden ^ | ||
| - | | Codex ('' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | CodeRabbit | '' | ||
| - | | ::: | '' | ||
| - | | '' | ||
| - | |||
| - | |||
| - | Ahora que hemos visto el formato, veamos como decirselo al agente para que retorne ese formato.Hay que tener una sección titulada " | ||
| - | |||
| - | <sxh markdown; | ||
| - | ## Formato de Salida | ||
| - | |||
| - | La primera línea es `PASS` o `FAIL`. Con `PASS` no se escribe nada más. Con `FAIL`, | ||
| - | debajo, una línea por problema con el formato `fichero: | ||
| - | |||
| - | - `fichero` es donde se ha encontrado el problema. La ruta es relativa al proyecto. | ||
| - | - `linea` es un número (`42`) o un rango (`50-71`). Si el problema es del fichero | ||
| - | entero, no lleva `linea`: `fichero: | ||
| - | - `tipo` es `CRITICAL`, `MAJOR` o `MINOR`. | ||
| - | - `descripcion`es la descripción del problema que ha encontrado. Es texto libre pero si hay retornos de carro se deben escapar para que solo sea una línea. | ||
| - | |||
| - | |||
| - | **MUST NOT** escribir nada más antes ni después. | ||
| - | </ | ||
| - | |||
| - | ==== Ejemplos ==== | ||
| - | |||
| - | Una revisión sin problemas: | ||
| - | |||
| - | <sxh markdown> | ||
| - | PASS | ||
| - | </ | ||
| - | |||
| - | '' | ||
| - | |||
| - | <sxh markdown> | ||
| - | FAIL | ||
| - | src/ | ||
| - | src/ | ||
| - | specs/ | ||
| - | </ | ||
| - | |||
| - | Una //skill// que revisa los tests, sin '' | ||
| - | |||
| - | <sxh markdown> | ||
| - | FAIL | ||
| - | src/ | ||
| - | src/ | ||
| - | src/ | ||
| - | </ | ||
| - | |||
| - | Una //skill// que revisa el diseño de las clases, por método ('' | ||
| - | |||
| - | <sxh markdown> | ||
| - | FAIL | ||
| - | com.tienda.domain.PedidoService.crear: | ||
| - | com.tienda.domain.PedidoService: | ||
| - | R-12: | ||
| - | </ | ||
| - | |||
| - | ---- | ||
| - | |||
| - | ===== Ejercicios ===== | ||
| - | |||
| - | ==== Ejercicio 1 ==== | ||
| - | |||
| - | Esta //skill// tiene cinco fallos de estructura. Encuéntralos y di cómo se arregla cada uno. | ||
| - | |||
| - | <sxh text; | ||
| - | .claude/ | ||
| - | ├── skill.md | ||
| - | ├── validacion/ | ||
| - | │ | ||
| - | ├── agents/ | ||
| - | │ | ||
| - | ├── templates/ | ||
| - | │ | ||
| - | └── examples/ | ||
| - | └── pedido-controller.md | ||
| - | </ | ||
| - | |||
| - | ==== Ejercicio 2 ==== | ||
| - | |||
| - | Escribe la //skill// de conocimiento '' | ||
| - | |||
| - | ==== Ejercicio 3 ==== | ||
| - | |||
| - | Escribe la //skill// de procedimiento '' | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
cursos/sdd/09-creando-skills.1793913816.txt.gz · Última modificación: por claude
