MÓDULO 2.4

🧩 Skills canônicas com polyskill

Uma fonte, N runtimes. Copiar uma skill à mão pro segundo executor funciona no primeiro dia e apodrece no segundo mês. Aqui você transforma um SKILL.md numa definição portátil, gera as cópias por build, instala nos dois runtimes com backup ao lado e mede o drift — a distância entre o que você escreveu e o que está instalado.

6
Tópicos
~30
Minutos
Interm.
Nível
Prática
Tipo
1

🧬 Por que cópias manuais divergem

O caso é real e está documentado nesta máquina. Pra dar skills ao dsh-sandbox (um terceiro executor, com modelo rodando em container), três skills foram copiadas à mão pra ~/projetos/dsh-skills: formato-curso-v2, formato-curso-v5 e capa-inema, que é dependência das outras duas. A documentação avisa em letras claras: "São CÓPIAS — o Claude segue usando os originais em ~/projetos/formato-curso-inema via symlink em ~/.claude/skills/". Duas pastas, duas verdades, nenhum mecanismo ligando as duas.

No dia da cópia, os dois lados são idênticos. Depois você corrige um erro de prompt no original — a skill do Claude melhora, a cópia do dsh não. Aí você ajusta um caminho na cópia porque dentro do container ~/projetos resolve diferente — agora a cópia tem uma correção que o original não tem. Duas semanas depois ninguém sabe qual das duas está certa, e "certa" virou uma pergunta sem resposta. Isso é drift: divergência silenciosa entre cópias que deveriam ser a mesma coisa.

cópia manual o tempo separa as duas pastas dia 0 · iguais fix de prompt ajuste de caminho original (Claude) cópia (dsh) · divergiu qual está certa? fonte canônica + build definition.md dist/claude dist/codex regenerar é barato a divergência não tem onde nascer

Compare as duas metades. Em cima, as linhas azul e vermelha tracejada partem do mesmo ponto e se afastam a cada edição — ninguém programou isso, é só o tempo passando. Embaixo, tudo sai de um bloco só: a saída é descartável e refeita a qualquer momento.

💡 Novo aqui?

Skill é uma pasta com um SKILL.md dentro: instruções que o agente carrega sob demanda pra executar um tipo de tarefa. Runtime é o programa que executa o agente (Claude Code, Codex CLI, dsh-sandbox). Fonte canônica é o único lugar onde você edita — todo o resto é gerado a partir dela. Drift é quando uma cópia deixou de ser igual à fonte. MCP (Model Context Protocol) é o padrão pelo qual um agente ganha ferramentas externas: gerar imagem, publicar post, consultar uma API.

Conceitos-chave

Cópia manual

Funciona hoje, diverge amanhã, sem aviso.

Fonte canônica

O único arquivo que você edita à mão.

Saída gerada

dist/ é descartável: apagar e refazer é grátis.

Caso real

Três skills copiadas à mão em ~/projetos/dsh-skills.

2

📥 import: SKILL.md vira definição portátil

O sync-skills.sh do kit é uma casca fina em volta do polyskill. O comando import pega uma skill que já existe em ~/.claude/skills/<nome> e a traduz pro formato portátil dentro de skills/<nome>/, no repositório do kit. O que sai de lá são dois arquivos: definition.md, com frontmatter YAML e o corpo em Markdown, e polyskill.yaml, que diz quais runtimes esta skill deve atender.

Duas garantias importam aqui. A primeira: o import nunca copia ~/.claude ou ~/.codex em massa — você nomeia skill por skill, de propósito, porque migrar 117 skills de uma vez é como migrar um armário inteiro sem abrir as gavetas. A segunda: o round-trip é sem perdas para o núcleo da especificação (name, description, corpo, scripts/, references/, assets/) e com aviso para as extensões de cada runtime. Se algo não sobrevive à tradução, o polyskill diz.

🎯 Importar a primeira skill

Objetivo: transformar a skill session-handoff — a mesma do piloto registrado em tasks/current.md — numa fonte canônica dentro do kit.

# pré-requisito, uma vez só nesta máquina
npm i -g polyskill
polyskill --version   # 0.1.0

cd ~/projetos/agente-claude-codex

# importa do Claude para o formato portátil
scripts/sync-skills.sh import session-handoff
# importada: skills/session-handoff

# o que nasceu
ls skills/session-handoff/
# definition.md  polyskill.yaml

# troque pelo nome de qualquer skill sua
scripts/sync-skills.sh import <sua-skill>

Como verificar: head -12 skills/session-handoff/definition.md mostra o frontmatter com name e description iguais aos do SKILL.md original. Se o script responder skip <nome>: não existe em ~/.claude/skills, confira a grafia — o nome é o da pasta, não o do slash command.

✓ Boas candidatas a importar

  • Skills classificadas como reutilizável no audit do módulo 2.1.
  • As que você usa toda semana — o retorno aparece rápido.
  • As que já estão copiadas à mão em algum lugar (pare o sangramento primeiro).
  • Skills pequenas, pra aprender o ciclo antes de encarar as grandes.

✗ Deixe pra depois

  • Skills de adaptador: sem o MCP no destino, elas não rodam (tópico 6).
  • Skills classificadas como nativo: dependem de hook que o Codex não tem.
  • Pastas sem SKILL.md: não há o que importar; resolva à mão.
  • Lotes de 50: importe de 5 em 5 e rode o drift entre os lotes.

Conceitos-chave

definition.md

Frontmatter YAML + corpo Markdown. A fonte.

polyskill.yaml

Quais runtimes esta skill atende.

Round-trip

Sem perda no núcleo; com aviso nas extensões.

Skill por skill

Nunca copia as pastas de runtime em massa.

3

🏗️ build: dist/claude e dist/codex

O build percorre todas as pastas em skills/ e, pra cada uma, pede ao polyskill que emita a versão otimizada de cada runtime configurado. O resultado vai pra skills/<nome>/dist/claude/<nome>/ e skills/<nome>/dist/codex/<nome>/. Duas saídas, uma fonte. A regra de ouro do módulo inteiro cabe em uma frase: você edita definition.md; nunca edita nada dentro de dist/.

skills/<nome>/ definition.md polyskill.yaml fonte canônica · você edita aqui build adaptadores por runtime dist/claude → ~/.claude/skillsClaude Code dist/codex → ~/.codex/skillsCodex CLI · espelho em ~/.agents/skills --dsh → ~/projetos/dsh-skillsterceiro executor · destino a acrescentar

Repare que só há um bloco à esquerda. As três caixas da direita são saídas: apagar qualquer uma delas não perde nada, porque o build refaz. A terceira aparece tracejada porque o destino --dsh ainda é um item planejado no tasks/current.md do kit, não uma opção pronta.

🎯 Gerar as cópias dos dois runtimes

Objetivo: produzir dist/claude e dist/codex a partir da definição importada, sem tocar em nenhuma pasta de runtime ainda.

cd ~/projetos/agente-claude-codex

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

# confira o que foi emitido
find skills/<sua-skill>/dist -maxdepth 3 -type d
# skills/<sua-skill>/dist/claude/<sua-skill>
# skills/<sua-skill>/dist/codex/<sua-skill>

# se um arquivo de dist/ foi editado à mão, o build recusa;
# FORCE=1 manda regenerar por cima (polyskill build --force)
FORCE=1 scripts/sync-skills.sh build

Como verificar: as duas pastas existem e cada uma contém o arquivo de skill no formato do seu runtime. Rode o build duas vezes seguidas sem editar nada: a segunda vez não deve mudar arquivo nenhum — build é determinístico, e isso é o que torna o drift confiável.

💡 Dica prática

Versione skills/ no git e ignore dist/. A fonte merece histórico; a saída, não. Quando alguém clonar o kit, um build reconstrói tudo — e o diff do repositório volta a mostrar só o que você realmente escreveu, em vez de centenas de linhas geradas.

Conceitos-chave

Adaptador de runtime

Quem sabe traduzir a definição pro formato de cada executor.

dist/

Saída gerada. Nunca edite; sempre regenere.

--force

Sobrescreve saída que alguém editou à mão.

Determinismo

Mesma fonte, mesma saída — a base do drift.

4

📦 install --both, com backup ao lado

O install é o único comando do módulo que escreve fora do repositório do kit. Ele copia skills/<nome>/dist/<runtime>/<nome>/ pra ~/.claude/skills/<nome> ou ~/.codex/skills/<nome>, conforme o destino que você pedir: --claude, --codex ou --both. Antes de sobrescrever qualquer pasta que já exista, ele copia o que estava lá pra .<nome>.bak-<timestamp>, na mesma pasta. Você nunca perde a versão anterior sem ter como voltar.

Tem um detalhe específico do Codex que o script resolve por você: além de ~/.codex/skills, o Codex também descobre skills em ~/.agents/skills. Quando o destino inclui o Codex e essa pasta existe, o script espelha a instalação lá também. É a razão de o doctor do módulo 2.1 reportar duas contagens diferentes nesta máquina — 27 skills em ~/.codex/skills e 29 em ~/.agents/skills.

🎯 Instalar nos dois runtimes

Objetivo: colocar a mesma skill gerada nos dois executores e confirmar que o backup existe.

cd ~/projetos/agente-claude-codex

# só no Codex, se quiser ir devagar
scripts/sync-skills.sh install session-handoff --codex

# nos dois de uma vez
scripts/sync-skills.sh install session-handoff --both
# instalada: /home/<usuario>/.claude/skills/session-handoff (backup ao lado se já existia)
# instalada: /home/<usuario>/.codex/skills/session-handoff (backup ao lado se já existia)
# espelhada: ~/.agents/skills/session-handoff

# os backups ficam ocultos, na mesma pasta
ls -d ~/.claude/skills/.session-handoff.bak-*

# voltar atrás, se precisar
rm -rf ~/.claude/skills/session-handoff
cp -a ~/.claude/skills/.session-handoff.bak-<timestamp> \
      ~/.claude/skills/session-handoff

Como verificar: abra uma sessão nova em cada runtime e peça pra listar as skills disponíveis; o nome tem que aparecer nos dois. Se o script disser rode build antes: skills/<nome>/dist/<runtime>/<nome>, é porque você pulou o tópico 3.

1

Confere a saída

Se dist/<runtime>/<nome> não existe, o script para com mensagem e código 1. Não inventa conteúdo.

2

Faz o backup

Se o destino já existia, ele vira .<nome>.bak-<timestamp> ao lado. Um por instalação, com hora no nome.

3

Copia

cp -a preserva permissões e estrutura — scripts da skill continuam executáveis.

4

Espelha no Codex

Se o destino é o Codex e ~/.agents/skills existe, a mesma pasta é copiada pra lá.

5

Registra

Imprime cada caminho instalado. Cole essa saída no handoffs/latest.md: é a evidência de que o passo rodou.

Conceitos-chave

--both

Instala em Claude e Codex na mesma execução.

.bak-<timestamp>

Backup oculto ao lado; reversão é um cp -a.

~/.agents/skills

Segunda pasta onde o Codex descobre skills.

Falha ruidosa

Sem build, o install para e diz o que falta.

5

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

O drift é o comando mais curto e o mais importante. Pra cada skill em skills/ e pra cada runtime, ele compara a saída gerada com o que está instalado, usando diff -rq. Três respostas possíveis por linha: [ok] quando são idênticos, [DRIFT] quando divergiram, e [não instalada] quando falta a pasta de um lado ou do outro. E ele sai com código 1 se qualquer linha deu DRIFT — ou seja, dá pra pendurar isso num check.sh ou numa rotina semanal e ser avisado em vez de descobrir por acidente.

🎯 Medir e resolver um drift

Objetivo: provocar um DRIFT de propósito, vê-lo aparecer e resolvê-lo pela fonte — não pela cópia.

cd ~/projetos/agente-claude-codex

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

# 2. alguém edita a cópia instalada (é assim que começa)
echo "# anotação solta" >> ~/.codex/skills/session-handoff/SKILL.md

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

# 4. decida: a edição era boa? leve pra fonte e regenere
$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=$?"   # volta a exit=0

Como verificar: o exit=1 do passo 3 e o exit=0 do passo 4. Se aparecer [não instalada], a skill existe na fonte mas nunca foi instalada naquele runtime — rode o install. Troque session-handoff por <sua-skill> pra repetir com a sua.

✓ Como resolver um DRIFT

  • Ler o diff antes de decidir: a edição da cópia pode ser boa.
  • Se for boa, levá-la pro definition.md e regenerar.
  • Se não for, reinstalar por cima — o backup guarda a versão anterior.
  • Rodar o drift depois de cada lote de instalação, não só no fim.

✗ O que transforma drift em dívida

  • Editar direto em ~/.codex/skills "só desta vez".
  • Rodar FORCE=1 sem ler o que vai ser sobrescrito.
  • Deixar [DRIFT] na tela por semanas: ele deixa de ser sinal e vira ruído.
  • Tratar [não instalada] como erro: muitas vezes é escolha consciente.

Conceitos-chave

[ok]

Gerado e instalado são byte a byte iguais.

[DRIFT]

Divergiram; alguém editou a cópia. Código de saída 1.

[não instalada]

Falta a pasta num dos lados; não é falha.

Resolver pela fonte

Conserta-se o definition.md, nunca o dist/.

6

🔌 Skills de adaptador: só depois do MCP

O audit do módulo 2.1 marcou 15 skills como adaptadorheygen, magnific, as oito variantes de printing-press, e outras. Elas não dependem do Claude por capricho: dependem de ferramentas MCP que hoje só estão registradas no Claude. O doctor é explícito nesse ponto: "nenhum MCP no Codex: skills marcadas 'adaptador' só funcionam após codex mcp add". Portar o Markdown delas antes de registrar o servidor gera uma skill que carrega, tenta chamar uma ferramenta inexistente e falha no meio — pior que não ter portado.

A ordem, então, é: primeiro codex mcp add no destino, depois import, build, install, drift. E o registro do MCP nunca copia o segredo: a chave continua onde sempre esteve, num .env referenciado por variável de ambiente. O relatório do audit segue essa mesma regra — ele lista nomes de servidores MCP e jamais valores.

🎯 Destravar uma skill de adaptador

Objetivo: registrar o MCP no Codex sem copiar chave, e só então portar a skill que depende dele.

# 1. o que já existe no Codex hoje
codex mcp list

# 2. registrar, referenciando a variável — nunca o valor da chave
codex mcp add <nome-do-servidor> \
  --env API_KEY="$<VARIAVEL_DO_SEU_ENV>" \
  -- <comando-do-servidor>

# 3. confirmar que apareceu
codex mcp list | grep <nome-do-servidor>

# 4. agora sim, o ciclo do 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

Como verificar: rode scripts/doctor.sh de novo — a linha [aviso] nenhum MCP no Codex tem que sumir. Depois peça ao Codex, numa sessão nova, pra executar a skill numa tarefa mínima. Se a ferramenta não aparecer, o servidor foi registrado mas não está subindo; o problema é o comando do passo 2, não a skill.

⚠️ Honestidade sobre o estado deste passo

Em 2026-09-14, no README do kit, a linha do sync-skills.sh estava marcada como "não rodado" — ao contrário do adapt-instructions.sh, que já tinha passado em dry-run com os 71/7 do módulo 2.2. O comando existe, foi lido e revisado, mas ninguém tinha executado o ciclo completo import → build → install → drift numa skill de verdade. Isso não é defeito do material: é a diferença entre escrito e provado, que este curso insiste em não confundir.

Quando você rodar, você vira a evidência. Anote o resultado — passou, falhou ou parcial — e em qual runtime. Um parágrafo em handoffs/latest.md muda o status do kit de "não rodado" pra "rodado em tal data, com tal saída".

# handoffs/latest.md — o registro que fecha o módulo
## Sessão 2026-09-14 · polyskill

- Rodado: `sync-skills.sh import session-handoff` → `build` → `install --both` → `drift`.
- Resultado: `[ok] session-handoff → claude`, `[ok] session-handoff → codex`, exit=0.
- Evidência: saída colada abaixo; backups em `~/.claude/skills/.session-handoff.bak-*`.
- Ainda não rodado: skills de adaptador (dependem de `codex mcp add`, nenhum MCP no Codex).
- Próxima ação: registrar o primeiro MCP no Codex e repetir o ciclo com uma skill de adaptador.

💡 Dica prática

"Não rodado" é um estado legítimo e merece ficar escrito. O que corrompe um projeto não é admitir que um passo ainda não foi executado — é o silêncio, que faz todo mundo assumir que foi. Se algo quebrar durante o ciclo, registre também em FALHAS.md: uma linha com data, o que quebrou, a menor correção possível e se a causa era prompt ou infraestrutura.

Conceitos-chave

Skill de adaptador

Depende de ferramenta MCP no runtime de destino.

codex mcp add

Registra o servidor antes de portar a skill.

Chave por referência

Variável de ambiente, nunca o valor no comando.

Não rodado

Estado honesto; vira evidência quando você executa.

Auto-checagem (opcional): o drift respondeu [DRIFT] minha-skill → codex. Qual é a primeira ação correta?

🎯 Resumo do módulo

Cópia manual diverge — as três skills copiadas à mão em ~/projetos/dsh-skills mostram como duas pastas viram duas verdades.
import → build → installSKILL.md vira definition.md + polyskill.yaml; o build emite dist/claude e dist/codex; o install copia com backup ao lado e espelha em ~/.agents/skills.
drift[ok], [DRIFT] ou [não instalada] por runtime, com código de saída 1 no DRIFT. Resolva sempre pela fonte.
Adaptador só depois do MCPcodex mcp add primeiro; e em 2026-09-14 este passo ainda constava como "não rodado" no kit. Rode e registre em handoffs/latest.md.

Próximo módulo:

2.5 — Readback: provar em sessão nova, cinco perguntas e dois runtimes