El problema de repetir todo
¿Alguna vez has tenido que explicarle lo mismo a alguien veinte veces? Pues imagina eso, pero con un robot que además se queda sin memoria cada pocas horas.
«No, Claude, el commit tiene que pasar los tests primero.»
«Claude, ya te dije que uses el formato tipo: descripción.»
«¡Que no añadas emojis, coño!»
Esto era mi día a día hasta que descubrí los Skills. Dicho en cristiano: son instrucciones que escribes una vez y Claude sigue para siempre. Como entrenar a un perro, pero sin las croquetas.
Qué son los Skills
Desde la versión 2.1.3, Claude Code fusionó los antiguos slash commands con algo más potente: los Skills. Son archivos Markdown con instrucciones que Claude puede ejecutar de dos formas:
- Manualmente: cuando tú escribes
/mi-skill - Automáticamente: cuando Claude detecta que debería usarlo
Ese segundo punto es la magia. Ya no tienes que acordarte de invocar el comando. Si tienes un skill que dice «usar cuando el usuario termine una tarea y haya cambios sin commitear», Claude lo hará solo.
Es como tener un mayordomo que sabe cuándo recoger la mesa sin que se lo pidas.
Dónde viven
~/.claude/skills/ # Personales (todos tus proyectos)
.claude/skills/ # Del proyecto (compartidos con el equipo)
~/.claude/commands/ # Legacy, sigue funcionando
.claude/commands/ # Legacy, sigue funcionando
Si quieres que solo tú uses el skill, lo pones en tu home. Si quieres que todo el equipo lo tenga, lo commiteas al repo. Así de simple.
Anatomía de un Skill
Un skill es un archivo Markdown con un frontmatter YAML y luego el contenido:
---
name: mi-skill
description: Breve descripción de qué hace
---
# Instrucciones
Lo que Claude debe hacer cuando se invoque este skill.
Eso es lo mínimo. Pero el frontmatter tiene bastantes más opciones que vale la pena conocer.
Campos obligatorios
name
El identificador del skill. Solo minúsculas, números y guiones (máx. 64 caracteres). Debe coincidir con el nombre del archivo o directorio.
name: check-types # ✓ válido
name: Check_Types # ✗ inválido (mayúsculas y guión bajo)
description
Este es el campo más importante. Claude lo usa para dos cosas: 1. Decidir cuándo auto-invocar el skill 2. Entender qué debe hacer
Máximo 1024 caracteres. Incluye palabras clave que el usuario diría naturalmente.
# Mal - demasiado vago
description: Hace cosas con commits
# Bien - específico y con triggers
description: >
Crea commits git verificando type-check, lint y tests.
Usar cuando el usuario diga "commit", "commitea", o termine una tarea
con cambios pendientes.
Campos opcionales
model
Fuerza un modelo específico para este skill. Útil para tareas que requieren más capacidad.
model: opus # Para auditorías de seguridad, refactoring complejo
model: sonnet # Balance entre capacidad y coste
model: haiku # Para tareas simples y rápidas
Si no lo especificas, usa el modelo de la conversación actual.
allowed-tools
Restringe qué herramientas puede usar Claude. Crítico para skills de solo lectura o seguros.
# Solo puede leer, no modificar
allowed-tools:
- Read
- Grep
- Glob
# Solo puede ejecutar comandos específicos
allowed-tools:
- Bash(git:*) # Solo comandos git
- Bash(uv:*) # Solo comandos uv
- Read
Ejemplo práctico: un skill de análisis que NO debe tocar nada:
---
name: analyze-deps
description: Analiza dependencias del proyecto sin modificar nada
allowed-tools:
- Read
- Grep
- Bash(uv pip list:*)
---
context: fork
Ejecuta el skill en un sub-agente aislado con su propio contexto. El historial de la conversación principal no se contamina.
context: fork
Útil para operaciones complejas de varios pasos donde no quieres llenar el chat de ruido.
agent
Solo funciona con context: fork. Define qué tipo de agente ejecuta el skill.
context: fork
agent: Explore # Agente de exploración rápida
agent: Plan # Agente de planificación
user-invocable
Controla si aparece en el menú de / (slash commands). Por defecto es true.
user-invocable: false # Oculto del menú, pero Claude puede usarlo
Útil para skills internos que solo deberían activarse automáticamente.
disable-model-invocation
Bloquea que Claude invoque el skill por su cuenta. Solo tú puedes activarlo con /nombre.
disable-model-invocation: true
Útil para operaciones destructivas o costosas que requieren decisión humana explícita.
hooks
Define hooks que se ejecutan durante el ciclo de vida del skill. Soporta PreToolUse, PostToolUse y Stop.
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/validate-input.sh $TOOL_INPUT"
once: true
Variables de sustitución
Dentro del contenido del skill puedes usar:
| Variable | Qué contiene |
|---|---|
$ARGUMENTS |
Los argumentos pasados al invocar /skill arg1 arg2 |
${CLAUDE_SESSION_ID} |
ID de la sesión actual (útil para logs) |
Tabla resumen
| Campo | Obligatorio | Propósito |
|---|---|---|
name |
✓ | Identificador del skill |
description |
✓ | Cuándo y para qué usarlo |
model |
Forzar modelo específico | |
allowed-tools |
Restringir herramientas | |
context |
fork para sub-agente aislado |
|
agent |
Tipo de agente (con context: fork) |
|
user-invocable |
Mostrar/ocultar en menú / |
|
disable-model-invocation |
Bloquear auto-invocación | |
hooks |
Hooks del ciclo de vida |
Ejemplo completo
---
name: security-audit
description: >
Auditoría de seguridad OWASP. Usar cuando el usuario pida revisar
seguridad, buscar vulnerabilidades, o antes de deployar a producción.
model: opus
allowed-tools:
- Read
- Grep
- Glob
user-invocable: true
disable-model-invocation: true # Solo manual, es costoso
---
# Auditoría de Seguridad
[instrucciones...]
Para la referencia completa, consulta la documentación oficial de Agent Skills.
¿Texto libre o código determinista?
Esta es la pregunta del millón: si los skills son Markdown, ¿significa que Claude siempre «interpreta» lo que escribes? ¿Puedo hacer algo realmente predecible?
La respuesta corta: los skills son tan deterministas como tú los escribas.
Piensa en un espectro:
Vago/Flexible ──────────────────────────► Determinista
"revisa el código" "ejecuta estos 3 comandos en orden"
Skill flexible (Claude decide)
---
name: review
description: Revisa el código en busca de problemas
---
Analiza el código y sugiere mejoras.
Aquí Claude tiene libertad total. Puede mirar lo que quiera, sugerir lo que le parezca. Útil para exploración, peligroso para procesos críticos.
Skill determinista (script disfrazado)
---
name: check
description: Verificaciones de calidad obligatorias
allowed-tools:
- Bash
---
Ejecutar **exactamente** estos comandos en orden:
1. `uv run basedpyright src/`
2. `uv run ruff check src/`
3. `uv run pytest -x`
## Reglas
- **NO interpretar** los errores creativamente
- **NO continuar** si alguno falla
- **NO sugerir** fixes automáticamente
- Reportar solo: ✓ pasó / ✗ falló con output
Esto es básicamente un script de 3 líneas. Claude no tiene margen para ser creativo. Ejecuta, reporta, punto.
Skill con lógica condicional
---
name: release
description: Prepara release del proyecto
---
## Paso 1: Verificar rama
```bash
git branch --show-current
- Si NO es
main→ ABORTAR con «Solo desde main»
Paso 2: Estado limpio
git status --porcelain
- Si hay output → ABORTAR con «Cambios sin commitear»
Paso 3: Bump + push
uv run bump2version patch
git push && git push --tags
Aquí hay lógica de branches, pero sigue siendo determinista: las condiciones están explícitas.
### Skill que invoca un script real
Si necesitas lógica compleja de verdad (loops, parsing, APIs), pon el código en un script y que el skill solo lo ejecute:
.claude/skills/deploy/ ├── SKILL.md └── deploy.sh
**SKILL.md:**
```markdown
---
name: deploy
description: Despliega a producción
---
Ejecutar:
```bash
bash .claude/skills/deploy/deploy.sh
Reportar el resultado. NO modificar el script.
**deploy.sh:**
```bash
#!/bin/bash
set -e
uv run pytest || exit 1
hugo --minify
rsync -avz public/ user@server:/var/www/
Lo mejor de ambos mundos: la lógica compleja vive en Bash/Python donde pertenece, y el skill es solo el gatillo.
Cuándo usar cada enfoque
| Necesidad | Enfoque |
|---|---|
| Comandos fijos, siempre iguales | Skill determinista |
| Lógica compleja con muchos branches | Script externo |
| Análisis que requiere criterio | Skill flexible con guardrails |
| Operaciones peligrosas | allowed-tools restrictivo |
Ejemplo real: el skill de commit
Este es el que más uso. Antes tenía que recordar: «vale, ejecuta los tests, luego el linter, luego el type-check, y solo entonces commitea». Ahora simplemente digo «commitea» y Claude hace todo solo.
---
name: commit
description: Crea commits git con verificación obligatoria de calidad.
Ejecuta type-check, lint y tests antes de commitear.
---
# Commit
## Cuándo Usar (Automático)
Aplicar cuando:
- El usuario dice "commit", "commitea", "guarda los cambios"
- El usuario termina una tarea y hay cambios sin commitear
## Prohibido
- Commitear sin ejecutar verificaciones
- Pedir confirmación (simplemente hazlo)
- Añadir Co-Authored-By
- Usar emojis en mensajes de commit
## Proceso
### Fase 1: Detectar cambios
```bash
git diff --name-only HEAD
Fase 2: Verificaciones OBLIGATORIAS
uv run basedpyright src/
uv run ruff check src/
uv run pytest
Si falla alguna, NO continuar.
Fase 3: Crear commit
git add -A- Analizar cambios
- Generar mensaje:
tipo: descripción git commit
¿Ves la sección "Cuándo Usar"? Eso es lo que permite la auto-invocación. Claude lee eso y piensa: "ah, el usuario acaba de decir 'ya está', hay cambios pendientes, debería usar este skill".
## Otro ejemplo: archivado de tareas
Si usas un archivo `TASKS.md` para trackear lo que haces (yo lo hacía antes de Beads), este skill te limpia las tareas completadas automáticamente:
```markdown
---
name: archive-tasks
description: Archiva tareas completadas de TASKS.md a TASKS-DONE.md.
Usar automáticamente cuando TASKS.md tenga muchas tareas completadas
o supere los 20K tokens.
---
# Archive Tasks
## Cuándo Usar (Automático)
- TASKS.md tiene más de 50 tareas completadas `[x]`
- TASKS.md supera los 20,000 tokens
- El usuario menciona que TASKS.md es muy grande
## Proceso
1. Leer `docs/llm/TASKS.md`
2. Identificar tareas completadas (`[x]`)
3. Mover a `docs/llm/TASKS-DONE.md` con fecha
4. Eliminar de TASKS.md
5. Reportar cuántas fueron archivadas
## Reglas
- **NO eliminar** tareas pendientes `[ ]`
- **PRESERVAR** el contexto (sección padre)
- **AÑADIR** fecha de archivado
Lo bonito es que no tienes que acordarte. Claude ve que TASKS.md está enorme y actúa.
Tips para escribir buenos skills
1. Descripciones específicas
# Mal
description: Hace cosas con commits
# Bien
description: Crea commits git verificando type-check, lint y tests.
Bloquea si hay errores.
2. Define cuándo aplicar
## Cuándo Usar Este Skill (Automático)
Aplicar automáticamente cuando:
- El usuario dice "commit" o "guarda los cambios"
- Hay cambios staged listos
- El usuario termina una tarea
3. Sé explícito con las prohibiciones
Claude tiende a querer ser educado y pedir confirmación. Si no quieres eso, dilo claramente:
## Prohibido
- Pedir confirmación (JAMÁS)
- Añadir Co-Authored-By
- Usar emojis
4. Usa model: opus para lo importante
Si el skill hace algo crítico (auditoría de seguridad, refactoring complejo), fuerza el modelo más capaz:
---
name: owasp
description: Auditoría de seguridad OWASP
model: opus
---
5. Restringe herramientas si hace falta
A veces quieres un skill que solo lea, sin modificar nada:
---
name: readonly-analysis
description: Analiza código sin modificarlo
allowed-tools:
- Glob
- Grep
- Read
---
Skills simples vs complejos
Un skill simple es un solo archivo:
.claude/skills/review.md
Un skill complejo es un directorio con recursos:
.claude/skills/deploy/
├── SKILL.md # Instrucciones
├── templates/
│ └── k8s-deployment.yaml
└── scripts/
└── healthcheck.sh
Claude puede leer los archivos del directorio como contexto adicional.
Lo que uso yo
| Skill | Para qué | Auto-invocación |
|---|---|---|
commit |
Commit con verificaciones | Cuando digo «commit» o termino algo |
check-diagnostics |
Verificar tipos y lint | Antes de commits |
owasp |
Auditoría de seguridad | Manual (es costoso) |
archive-tasks |
Limpiar TASKS.md | Cuando está muy grande |
La diferencia con los commands legacy
| Aspecto | Skills | Commands |
|---|---|---|
| Auto-invocación | Sí | No |
| Estructura | Directorio o archivo | Solo archivo |
| Recomendación | Usar para todo nuevo | Legacy |
Los commands siguen funcionando, pero los skills son estrictamente mejores. Si tienes commands viejos, no hace falta migrarlos, pero para cosas nuevas usa skills.
Conclusión
Los skills son básicamente programación, pero en lenguaje natural. Defines qué quieres que pase, cuándo, y con qué restricciones. Claude hace el resto.
Lo mejor es que se versionan con tu código. Si trabajas en equipo, todos tienen los mismos skills. Si cambias algo, queda en el historial de git.
¿Vale la pena el esfuerzo de escribirlos? Si repites lo mismo más de tres veces, absolutamente. Cada skill que escribes es una conversación que no tendrás que tener nunca más.
Ahora si me disculpas, tengo que ir a enseñarle a Claude que «refactorizar» no significa «reescribir todo desde cero».
TL;DR: Los skills son instrucciones en Markdown que Claude Code ejecuta manual o automáticamente. Pueden ser tan flexibles o deterministas como necesites: desde «analiza esto» hasta scripts disfrazados de prosa. Si necesitas lógica compleja, invoca scripts externos. Viven en .claude/skills/ y se versionan con tu código.
Read this article in English.



