MÓDULO 2.4

🧩 Skills canónicas con polyskill

Una fuente, N runtimes. Copiar una skill a mano al segundo ejecutor funciona el primer día y se pudre al segundo mes. Aquí conviertes un SKILL.md en una definición portable, generas las copias con un build, las instalas en los dos runtimes con un respaldo al lado y mides el drift: la distancia entre lo que escribiste y lo que está instalado.

6
Temas
~30
Minutos
Interm.
Nivel
Práctica
Tipo
1

🧬 Por qué las copias manuales divergen

El caso es real y está documentado en esta máquina. Para darle skills a dsh-sandbox (un tercer ejecutor, con el modelo corriendo en un contenedor), se copiaron a mano tres skills a ~/projetos/dsh-skills: formato-curso-v2, formato-curso-v5 y capa-inema, que es dependencia de las otras dos. La documentación lo advierte con todas las letras: "Son COPIAS: Claude sigue usando los originales en ~/projetos/formato-curso-inema mediante un symlink en ~/.claude/skills/". Dos carpetas, dos verdades, ningún mecanismo que las conecte.

El día de la copia, ambos lados son idénticos. Después corriges un error de prompt en el original: la skill de Claude mejora, la copia de dsh no. Luego ajustas una ruta en la copia porque dentro del contenedor ~/projetos se resuelve distinto: ahora la copia tiene una corrección que el original no tiene. Dos semanas después nadie sabe cuál de las dos está bien, y "bien" se volvió una pregunta sin respuesta. Eso es drift: divergencia silenciosa entre copias que deberían ser la misma cosa.

copia manual el tiempo separa las dos carpetas día 0 · iguales fix de prompt ajuste de ruta original (Claude) copia (dsh) · divergió ¿cuál está bien? fuente canónica + build definition.md dist/claude dist/codex regenerar es barato la divergencia no tiene dónde nacer

Compara las dos mitades. Arriba, las líneas azul y roja punteada parten del mismo punto y se alejan con cada edición: nadie lo programó, es solo el paso del tiempo. Abajo, todo sale de un único bloque: la salida es desechable y se rehace en cualquier momento.

💡 ¿Nuevo aquí?

Skill es una carpeta con un SKILL.md adentro: instrucciones que el agente carga bajo demanda para ejecutar un tipo de tarea. Runtime es el programa que ejecuta el agente (Claude Code, Codex CLI, dsh-sandbox). Fuente canónica es el único lugar donde editas — todo lo demás se genera a partir de ella. Drift es cuando una copia dejó de ser igual a la fuente. MCP (Model Context Protocol) es el estándar mediante el cual un agente obtiene herramientas externas: generar imágenes, publicar posts, consultar una API.

Conceptos clave

Copia manual

Funciona hoy, diverge mañana, sin aviso.

Fuente canónica

El único archivo que editas a mano.

Salida generada

dist/ es desechable: borrarla y rehacerla es gratis.

Caso real

Tres skills copiadas a mano en ~/projetos/dsh-skills.

2

📥 import: SKILL.md se convierte en definición portátil

El sync-skills.sh del kit es una capa delgada alrededor de polyskill. El comando import toma una skill que ya existe en ~/.claude/skills/<nome> y la traduce al formato portátil dentro de skills/<nome>/, en el repositorio del kit. De ahí salen dos archivos: definition.md, con frontmatter YAML y el cuerpo en Markdown, y polyskill.yaml, que indica qué runtimes debe atender esta skill.

Aquí importan dos garantías. La primera: el import nunca copia ~/.claude o ~/.codex en masa — nombras skill por skill, a propósito, porque migrar 117 skills de una vez es como mudar un armario entero sin abrir los cajones. La segunda: el round-trip es sin pérdidas para el núcleo de la especificación (name, description, cuerpo, scripts/, references/, assets/) y con aviso para las extensiones de cada runtime. Si algo no sobrevive a la traducción, polyskill lo dice.

🎯 Importar la primera skill

Objetivo: convertir la skill session-handoff — la misma del piloto registrado en tasks/current.md — en una fuente canónica dentro del kit.

# requisito previo, una sola vez en esta máquina
npm i -g polyskill
polyskill --version   # 0.1.0

cd ~/projetos/agente-claude-codex

# importa de Claude al formato portátil
scripts/sync-skills.sh import session-handoff
# importada: skills/session-handoff

# lo que se creó
ls skills/session-handoff/
# definition.md  polyskill.yaml

# cámbialo por el nombre de cualquier skill tuya
scripts/sync-skills.sh import <tu-skill>

Cómo verificar: head -12 skills/session-handoff/definition.md muestra el frontmatter con name y description iguales a los del SKILL.md original. Si el script responde skip <nome>: não existe em ~/.claude/skills, revisa la ortografía — el nombre es el de la carpeta, no el del slash command.

✓ Buenas candidatas para importar

  • Skills clasificadas como reutilizable en el audit del módulo 2.1.
  • Las que usas cada semana — el retorno aparece rápido.
  • Las que ya están copiadas a mano en algún lugar (detén el sangrado primero).
  • Skills pequeñas, para aprender el ciclo antes de enfrentar las grandes.

✗ Déjalas para después

  • Skills de adaptador: sin el MCP en el destino, no funcionan (tema 6).
  • Skills clasificadas como nativo: dependen de un hook que Codex no tiene.
  • Carpetas sin SKILL.md: no hay nada que importar; resuélvelo a mano.
  • Lotes de 50: importa de 5 en 5 y ejecuta el drift entre lotes.

Conceptos clave

definition.md

Frontmatter YAML + cuerpo Markdown. La fuente.

polyskill.yaml

Qué runtimes atiende esta skill.

Round-trip

Sin pérdida en el núcleo; con aviso en las extensiones.

Skill por skill

Nunca copia las carpetas de runtime en masa.

3

🏗️ build: dist/claude y dist/codex

El build recorre todas las carpetas en skills/ y, para cada una, le pide a polyskill que emita la versión optimizada de cada runtime configurado. El resultado va a skills/<nome>/dist/claude/<nome>/ y skills/<nome>/dist/codex/<nome>/. Dos salidas, una fuente. La regla de oro de todo el módulo cabe en una frase: editas definition.md; nunca editas nada dentro de dist/.

skills/<nome>/ definition.md polyskill.yaml fuente canónica · editas aquí build adaptadores por runtime dist/claude → ~/.claude/skillsClaude Code dist/codex → ~/.codex/skillsCodex CLI · espejo en ~/.agents/skills --dsh → ~/projetos/dsh-skillstercer ejecutor · destino por agregar

Fíjate que solo hay un bloque a la izquierda. Las tres cajas de la derecha son salidas: borrar cualquiera de ellas no hace perder nada, porque el build las rehace. La tercera aparece punteada porque el destino --dsh todavía es un ítem planificado en el tasks/current.md del kit, no una opción lista.

🎯 Generar las copias de los dos runtimes

Objetivo: producir dist/claude y dist/codex a partir de la definición importada, sin tocar todavía ninguna carpeta de runtime.

cd ~/projetos/agente-claude-codex

scripts/sync-skills.sh build
# build: skills/session-handoff/

# revisa lo que se generó
find skills/<tu-skill>/dist -maxdepth 3 -type d
# skills/<tu-skill>/dist/claude/<tu-skill>
# skills/<tu-skill>/dist/codex/<tu-skill>

# si un archivo de dist/ se editó a mano, el build se niega;
# FORCE=1 lo obliga a regenerar encima (polyskill build --force)
FORCE=1 scripts/sync-skills.sh build

Cómo verificar: las dos carpetas existen y cada una contiene el archivo de skill en el formato de su runtime. Ejecuta el build dos veces seguidas sin editar nada: la segunda vez no debe cambiar ningún archivo — el build es determinista, y eso es lo que hace confiable el drift.

💡 Consejo práctico

Versiona skills/ en git e ignora dist/. La fuente merece historial; la salida, no. Cuando alguien clone el kit, un build reconstruye todo — y el diff del repositorio vuelve a mostrar solo lo que realmente escribiste, en lugar de cientos de líneas generadas.

Conceptos clave

Adaptador de runtime

El que sabe traducir la definición al formato de cada ejecutor.

dist/

Salida generada. Nunca la edites; siempre regenérala.

--force

Sobrescribe la salida que alguien editó a mano.

Determinismo

Misma fuente, misma salida — la base del drift.

4

📦 install --both, con backup al lado

El install es el único comando del módulo que escribe fuera del repositorio del kit. Copia skills/<nombre>/dist/<runtime>/<nombre>/ a ~/.claude/skills/<nombre> o ~/.codex/skills/<nombre>, según el destino que pidas: --claude, --codex o --both. Antes de sobrescribir cualquier carpeta que ya exista, copia lo que había a .<nombre>.bak-<timestamp>, en la misma carpeta. Nunca pierdes la versión anterior sin tener cómo volver.

Hay un detalle específico de Codex que el script resuelve por ti: además de ~/.codex/skills, Codex también descubre skills en ~/.agents/skills. Cuando el destino incluye Codex y esa carpeta existe, el script replica la instalación allí también. Es la razón por la que el doctor del módulo 2.1 reporta dos conteos distintos en esta máquina — 27 skills en ~/.codex/skills y 29 en ~/.agents/skills.

🎯 Instalar en los dos runtimes

Objetivo: poner la misma skill generada en los dos ejecutores y confirmar que el backup existe.

cd ~/projetos/agente-claude-codex

# solo en Codex, si quieres ir despacio
scripts/sync-skills.sh install session-handoff --codex

# en los dos a la vez
scripts/sync-skills.sh install session-handoff --both
# instalada: /home/<usuario>/.claude/skills/session-handoff (backup al lado si ya existía)
# instalada: /home/<usuario>/.codex/skills/session-handoff (backup al lado si ya existía)
# replicada: ~/.agents/skills/session-handoff

# los backups quedan ocultos, en la misma carpeta
ls -d ~/.claude/skills/.session-handoff.bak-*

# revertir, si hace falta
rm -rf ~/.claude/skills/session-handoff
cp -a ~/.claude/skills/.session-handoff.bak-<timestamp> \
      ~/.claude/skills/session-handoff

Cómo verificar: abre una sesión nueva en cada runtime y pide que liste las skills disponibles; el nombre tiene que aparecer en los dos. Si el script dice rode build antes: skills/<nome>/dist/<runtime>/<nome>, es porque te saltaste el tema 3.

1

Revisa la salida

Si dist/<runtime>/<nombre> no existe, el script se detiene con un mensaje y código 1. No inventa contenido.

2

Hace el backup

Si el destino ya existía, se convierte en .<nombre>.bak-<timestamp> al lado. Uno por instalación, con la hora en el nombre.

3

Copia

cp -a preserva permisos y estructura — los scripts de la skill siguen siendo ejecutables.

4

Replica en Codex

Si el destino es Codex y ~/.agents/skills existe, la misma carpeta se copia allí.

5

Registra

Imprime cada ruta instalada. Pega esa salida en handoffs/latest.md: es la evidencia de que el paso se ejecutó.

Conceptos clave

--both

Instala en Claude y Codex en la misma ejecución.

.bak-<timestamp>

Backup oculto al lado; revertir es un cp -a.

~/.agents/skills

Segunda carpeta donde Codex descubre skills.

Falla ruidosa

Sin build, el install se detiene y dice lo que falta.

5

📡 drift: [ok] o [DRIFT] por runtime

El drift es el comando más corto y el más importante. Para cada skill en skills/ y para cada runtime, compara la salida generada con lo que está instalado, usando diff -rq. Hay tres respuestas posibles por línea: [ok] cuando son idénticos, [DRIFT] cuando divergieron, y [não instalada] cuando falta la carpeta de un lado o del otro. Además, termina con código 1 si cualquier línea dio DRIFT; es decir, puedes colgarlo de un check.sh o de una rutina semanal y recibir el aviso en lugar de descubrirlo por accidente.

🎯 Medir y resolver un drift

Objetivo: provocar un DRIFT a propósito, verlo aparecer y resolverlo desde la fuente, no desde la copia.

cd ~/projetos/agente-claude-codex

# 1. estado limpio
scripts/sync-skills.sh drift; echo "exit=$?"
# [ok] session-handoff → claude
# [ok] session-handoff → codex
# exit=0

# 2. alguien edita la copia instalada (así es como empieza)
echo "# anotação solta" >> ~/.codex/skills/session-handoff/SKILL.md

# 3. el drift lo detecta
scripts/sync-skills.sh drift; echo "exit=$?"
# [ok]    session-handoff → claude
# [DRIFT] session-handoff → codex
# exit=1

# 4. decide: ¿la edición era buena? llévala a la fuente y regenera
$EDITOR skills/session-handoff/definition.md
scripts/sync-skills.sh build
scripts/sync-skills.sh install session-handoff --both
scripts/sync-skills.sh drift; echo "exit=$?"   # vuelve a exit=0

Cómo verificar: el exit=1 del paso 3 y el exit=0 del paso 4. Si aparece [não instalada], la skill existe en la fuente pero nunca se instaló en ese runtime: ejecuta el install. Cambia session-handoff por <tu-skill> para repetirlo con la tuya.

✓ Cómo resolver un DRIFT

  • Leer el diff antes de decidir: la edición de la copia puede ser buena.
  • Si es buena, llevarla al definition.md y regenerar.
  • Si no lo es, reinstalar encima: el backup guarda la versión anterior.
  • Ejecutar el drift después de cada lote de instalación, no solo al final.

✗ Lo que convierte el drift en deuda

  • Editar directamente en ~/.codex/skills "solo esta vez".
  • Ejecutar FORCE=1 sin leer lo que se va a sobrescribir.
  • Dejar [DRIFT] en pantalla durante semanas: deja de ser señal y se vuelve ruido.
  • Tratar [não instalada] como error: muchas veces es una elección consciente.

Conceptos clave

[ok]

Lo generado y lo instalado son iguales byte a byte.

[DRIFT]

Divergieron; alguien editó la copia. Código de salida 1.

[não instalada]

Falta la carpeta en uno de los lados; no es una falla.

Resolver desde la fuente

Se corrige el definition.md, nunca el dist/.

6

🔌 Skills de adaptador: solo después del MCP

La auditoría del módulo 2.1 marcó 15 skills como adaptador: heygen, magnific, las ocho variantes de printing-press, y otras. No dependen de Claude por capricho: dependen de herramientas MCP que hoy solo están registradas en Claude. El doctor es explícito en este punto: "ningún MCP en Codex: las skills marcadas 'adaptador' solo funcionan después de codex mcp add". Portar su Markdown antes de registrar el servidor genera una skill que carga, intenta llamar a una herramienta inexistente y falla a la mitad, lo cual es peor que no haberla portado.

El orden, entonces, es: primero codex mcp add en el destino, después import, build, install, drift. Y el registro del MCP nunca copia el secreto: la clave sigue donde siempre estuvo, en un .env referenciado por una variable de entorno. El informe de la auditoría sigue esta misma regla: lista nombres de servidores MCP y jamás valores.

🎯 Desbloquear una skill de adaptador

Objetivo: registrar el MCP en Codex sin copiar la clave, y solo entonces portar la skill que depende de él.

# 1. lo que ya existe hoy en Codex
codex mcp list

# 2. registrar, referenciando la variable, nunca el valor de la clave
codex mcp add <nombre-del-servidor> \
  --env API_KEY="$<VARIABLE_DE_TU_ENV>" \
  -- <comando-del-servidor>

# 3. confirmar que apareció
codex mcp list | grep <nombre-del-servidor>

# 4. ahora sí, el ciclo del módulo
cd ~/projetos/agente-claude-codex
scripts/sync-skills.sh import <skill-de-adaptador>
scripts/sync-skills.sh build
scripts/sync-skills.sh install <skill-de-adaptador> --codex
scripts/sync-skills.sh drift

Cómo verificar: vuelve a ejecutar scripts/doctor.sh: la línea [aviso] nenhum MCP no Codex tiene que desaparecer. Después pídele a Codex, en una sesión nueva, que ejecute la skill en una tarea mínima. Si la herramienta no aparece, el servidor se registró pero no está arrancando; el problema es el comando del paso 2, no la skill.

⚠️ Honestidad sobre el estado de este paso

El 2026-09-14, en el README del kit, la línea de sync-skills.sh estaba marcada como "no ejecutado", a diferencia de adapt-instructions.sh, que ya había pasado en dry-run con los 71/7 del módulo 2.2. El comando existe, fue leído y revisado, pero nadie había ejecutado el ciclo completo import → build → install → drift en una skill real. Eso no es un defecto del material: es la diferencia entre escrito y probado, que este curso insiste en no confundir.

Cuando lo ejecutes, tú te conviertes en la evidencia. Anota el resultado (pasó, falló o parcial) y en qué runtime. Un párrafo en handoffs/latest.md cambia el estado del kit de "no ejecutado" a "ejecutado en tal fecha, con tal salida".

# handoffs/latest.md — el registro que cierra el módulo
## Sesión 2026-09-14 · polyskill

- Ejecutado: `sync-skills.sh import session-handoff` → `build` → `install --both` → `drift`.
- Resultado: `[ok] session-handoff → claude`, `[ok] session-handoff → codex`, exit=0.
- Evidencia: salida pegada abajo; backups en `~/.claude/skills/.session-handoff.bak-*`.
- Aún no ejecutado: skills de adaptador (dependen de `codex mcp add`, ningún MCP en Codex).
- Próxima acción: registrar el primer MCP en Codex y repetir el ciclo con una skill de adaptador.

💡 Consejo práctico

"No ejecutado" es un estado legítimo y merece quedar por escrito. Lo que corrompe un proyecto no es admitir que un paso todavía no se ejecutó: es el silencio, que hace que todos asuman que sí. Si algo se rompe durante el ciclo, regístralo también en FALHAS.md: una línea con la fecha, qué se rompió, la corrección mínima posible y si la causa era de prompt o de infraestructura.

Conceptos clave

Skill de adaptador

Depende de una herramienta MCP en el runtime de destino.

codex mcp add

Registra el servidor antes de portar la skill.

Clave por referencia

Variable de entorno, nunca el valor en el comando.

No ejecutado

Estado honesto; se vuelve evidencia cuando lo ejecutas.

Autoevaluación (opcional): drift respondió [DRIFT] minha-skill → codex. ¿Cuál es la primera acción correcta?

🎯 Resumen del módulo

La copia manual diverge — las tres skills copiadas a mano en ~/projetos/dsh-skills muestran cómo dos carpetas se convierten en dos verdades.
import → build → installSKILL.md se convierte en definition.md + polyskill.yaml; el build emite dist/claude y dist/codex; el install copia con backup al lado y refleja en ~/.agents/skills.
drift[ok], [DRIFT] o [não instalada] por runtime, con código de salida 1 en DRIFT. Resuélvelo siempre desde la fuente.
Adaptador solo después del MCPcodex mcp add primero; y el 2026-09-14 este paso todavía figuraba como "no ejecutado" en el kit. Ejecútalo y regístralo en handoffs/latest.md.

Próximo módulo:

2.5 — Readback: probar en una sesión nueva, cinco preguntas y dos runtimes