🧩 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.
🧬 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.
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
Funciona hoje, diverge amanhã, sem aviso.
O único arquivo que você edita à mão.
dist/ é descartável: apagar e refazer é grátis.
Três skills copiadas à mão em ~/projetos/dsh-skills.
📥 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
Frontmatter YAML + corpo Markdown. A fonte.
Quais runtimes esta skill atende.
Sem perda no núcleo; com aviso nas extensões.
Nunca copia as pastas de runtime em massa.
🏗️ 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/.
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
Quem sabe traduzir a definição pro formato de cada executor.
Saída gerada. Nunca edite; sempre regenere.
Sobrescreve saída que alguém editou à mão.
Mesma fonte, mesma saída — a base do drift.
📦 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.
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.
Faz o backup
Se o destino já existia, ele vira .<nome>.bak-<timestamp> ao lado. Um por instalação, com hora no nome.
Copia
cp -a preserva permissões e estrutura — scripts da skill continuam executáveis.
Espelha no Codex
Se o destino é o Codex e ~/.agents/skills existe, a mesma pasta é copiada pra lá.
Registra
Imprime cada caminho instalado. Cole essa saída no handoffs/latest.md: é a evidência de que o passo rodou.
Conceitos-chave
Instala em Claude e Codex na mesma execução.
Backup oculto ao lado; reversão é um cp -a.
Segunda pasta onde o Codex descobre skills.
Sem build, o install para e diz o que falta.
📡 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
diffantes de decidir: a edição da cópia pode ser boa. - ✓Se for boa, levá-la pro
definition.mde 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=1sem 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
Gerado e instalado são byte a byte iguais.
Divergiram; alguém editou a cópia. Código de saída 1.
Falta a pasta num dos lados; não é falha.
Conserta-se o definition.md, nunca o dist/.
🔌 Skills de adaptador: só depois do MCP
O audit do módulo 2.1 marcou 15 skills como adaptador — heygen, 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
Depende de ferramenta MCP no runtime de destino.
Registra o servidor antes de portar a skill.
Variável de ambiente, nunca o valor no comando.
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
~/projetos/dsh-skills mostram como duas pastas viram duas verdades.SKILL.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.[ok], [DRIFT] ou [não instalada] por runtime, com código de saída 1 no DRIFT. Resolva sempre pela fonte.codex 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