Qué es una skill en dos líneas está en Conceptos básicos; cómo se lanza y dónde se guarda, en OpenCode y 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.
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: 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 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 (AGENTS.md pequeño). Lo que no puede hacer una skill es actuar: solo guía cómo se actúa.
Una skill y un 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.
/revisar-pr 128, es una skill. En cuanto reparte el trabajo entre subagentes y junta lo que devuelven, es un agente.
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.
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
<tema>.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.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.
Una skill se lee para el modelo, no para una persona, y cada línea cuesta tokens cada vez que se carga.
MUST y MUST NOT solo en lo que de verdad no puede fallar: si están por todas partes, dejan de pesar.
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 agente.
✅ 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)
SKILL.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 estándar abierto: el mismo fichero lo leen Claude Code, OpenCode, Codex, Cursor, Copilot o Gemini CLI.
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 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.
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: /init en OpenCode.
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<Path> ficheros = Files.walk(Path.of("."))) {
List<Path> 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();
}
}
}
La 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.
El agente obedece lo que pone el fichero: en el 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:
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.
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.
| 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.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 regla de ''CLAUDE.md''.
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 |
@ 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 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 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): las skills se activan casi por palabra clave. En la 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.
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.SKILL.md y carga por niveles (descripción, cuerpo, ficheros de apoyo).AGENTS.md mínimo y el detalle en ficheros enlazados por tema; qué no meter en él.AGENTS.md grande en un índice y un fichero por tema.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.@ruta no ahorra contexto porque carga el fichero al arrancar.AGENTS.md; hay que decirle cuándo leer cada fichero..claude/skills/ incluida.