🧩 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.
🧬 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.
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
Funciona hoy, diverge mañana, sin aviso.
El único archivo que editas a mano.
dist/ es desechable: borrarla y rehacerla es gratis.
Tres skills copiadas a mano en ~/projetos/dsh-skills.
📥 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
Frontmatter YAML + cuerpo Markdown. La fuente.
Qué runtimes atiende esta skill.
Sin pérdida en el núcleo; con aviso en las extensiones.
Nunca copia las carpetas de runtime en masa.
🏗️ 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/.
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
El que sabe traducir la definición al formato de cada ejecutor.
Salida generada. Nunca la edites; siempre regenérala.
Sobrescribe la salida que alguien editó a mano.
Misma fuente, misma salida — la base del drift.
📦 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.
Revisa la salida
Si dist/<runtime>/<nombre> no existe, el script se detiene con un mensaje y código 1. No inventa contenido.
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.
Copia
cp -a preserva permisos y estructura — los scripts de la skill siguen siendo ejecutables.
Replica en Codex
Si el destino es Codex y ~/.agents/skills existe, la misma carpeta se copia allí.
Registra
Imprime cada ruta instalada. Pega esa salida en handoffs/latest.md: es la evidencia de que el paso se ejecutó.
Conceptos clave
Instala en Claude y Codex en la misma ejecución.
Backup oculto al lado; revertir es un cp -a.
Segunda carpeta donde Codex descubre skills.
Sin build, el install se detiene y dice lo que falta.
📡 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
diffantes de decidir: la edición de la copia puede ser buena. - ✓Si es buena, llevarla al
definition.mdy 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=1sin 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
Lo generado y lo instalado son iguales byte a byte.
Divergieron; alguien editó la copia. Código de salida 1.
Falta la carpeta en uno de los lados; no es una falla.
Se corrige el definition.md, nunca el dist/.
🔌 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
Depende de una herramienta MCP en el runtime de destino.
Registra el servidor antes de portar la skill.
Variable de entorno, nunca el valor en el comando.
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
~/projetos/dsh-skills muestran cómo dos carpetas se convierten en dos verdades.SKILL.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.[ok], [DRIFT] o [não instalada] por runtime, con código de salida 1 en DRIFT. Resuélvelo siempre desde la fuente.codex 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