🌐 Cross-runtime: o problema
Você escreve uma skill para o Claude Code. Funciona perfeito. Aí seu colega usa Codex e pergunta: "como rodo isso aqui?". Resposta curta: não roda. Resposta longa: cada agente tem sua sintaxe — frontmatter, formato de tools, sistema de permissões. Copiar e colar não basta.
💡 Dica
Skills são documentação executável. A lógica é a mesma em qualquer runtime — o que muda é o envelope: como o agente carrega, ativa e chama tools. Resolver o envelope é o trabalho.
✓ Formato portável (fonte única)
- ✓Escreve uma vez em formato neutro
- ✓Build emite versões pra cada runtime
- ✓Mudança propaga pra todos com um comando
- ✓Testes rodam contra a fonte, não cópias
✗ Copy-paste entre runtimes
- ✗3 cópias divergem em 2 semanas
- ✗Bug fix em uma, esquecida nas outras
- ✗Frontmatter quebrado por runtime errado
- ✗Não tem como testar consistência
📦 polyskill — formato portável
A skill polyskill (presente no repo) resolve o problema do envelope. Você escreve uma fonte única e ela emite builds específicos pra cada runtime. Pense em "Babel pra skills".
🗂️ Estrutura típica de um polyskill
minha-skill/
├── source.md # fonte única (neutra)
├── polyskill.config.json # mapeamento de tools
├── claude-code/ # build pra Claude Code
│ └── SKILL.md # frontmatter + Read/Edit/Bash
├── codex/ # build pra Codex
│ └── skill.yaml # frontmatter Codex + read_file/write_file
└── tests/
└── snapshot.test.ts # garante paridade entre builds
⚡ Tradução automática
O polyskill faz três tradutoras essenciais:
- →Frontmatter:
name/description/toolsmapeados pra cada runtime - →Tools:
Read↔read_file,Bash↔shell - →Ativação: Skill tool (Claude Code) vs activate_skill (Codex)
Vantagem prática: você ajusta um parágrafo na fonte única, roda polyskill build e os dois builds saem coerentes. Bug em produção é um git diff, não um "em qual cópia eu fixei isso mesmo?".
🔀 Diferenças entre Claude Code e Codex
Antes de portar uma skill, vale entender onde os dois divergem. Spoiler: na superfície são iguais (markdown + frontmatter), no detalhe são bem diferentes.
| Dimensão | Claude Code | Codex |
|---|---|---|
| Tools de arquivo | Read, Edit, Write |
read_file, write_file, apply_patch |
| Execução de shell | Bash com sandbox por permissão |
shell com workspace-write/read |
| Carregamento de skill | Skill tool (/skill-name) + descrição dispara automático |
activate_skill explícito ou prompt-trigger |
| Permissões | Allowlist em settings.json, prompt por tool |
Modos (suggest / auto-edit / full-auto) |
| Suporte a MCP | Nativo, configurado em ~/.claude/mcp.json |
Suporte recente, em evolução |
| Subagents | Sim (Task tool, agentes paralelos) | Limitado — uma sessão por vez |
| Slash commands | Sim, ~/.claude/commands/ |
Sim, mas formato distinto |
A regra prática: se sua skill só lê arquivos e escreve markdown, ela é trivialmente portável. Se ela orquestra subagents paralelos com hooks, vai precisar de adaptação séria — provavelmente vira duas skills.
🔗 Chamando skills via MCP
Em vez de pedir pro outro agente entender seu formato de skill, embrulhe a skill num MCP server. Qualquer cliente MCP (Claude Code, Codex, Cursor, Cline) pode chamar como tool, sem saber que por trás é uma skill.
🛠️ Snippet: skill como endpoint MCP
// mcp-skills-server/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { readFileSync } from "fs";
const server = new Server({ name: "skills-bridge", version: "0.1.0" });
server.tool({
name: "grill-me",
description: "Stress-test a plan adversarially. Returns gaps and risks.",
inputSchema: {
type: "object",
properties: { plan: { type: "string" } },
required: ["plan"]
},
handler: async ({ plan }) => {
const skillBody = readFileSync("./skills/grill-me/SKILL.md", "utf8");
return runAgentLoop({ system: skillBody, user: plan });
}
});
server.start();
Use case: skills como API. Sua skill /grill-me vira um endpoint que qualquer agente — ou até seu CI — chama via HTTP/MCP. Centraliza a lógica, evita duplicação.
📊 Quando usar MCP vs polyskill
- polyskill: skill é principalmente documentação — guia o modelo, não executa lógica pesada
- MCP server: skill chama APIs externas, mantém estado, ou tem código que você não quer duplicar
- Híbrido: polyskill emite a doc, MCP server expõe as tools especializadas
🤖 Skills em CI/CD
Skills não precisam ser interativas. Em CI/CD você roda em modo batch (não-interativo, com input fixo, output em arquivo). Útil pra revisão automática de PR, geração de docs, validação de migrations.
✓ Funciona em CI
- ✓Skills determinísticas com input bem definido
- ✓Saída em arquivo (markdown, JSON)
- ✓Tools restritas (Read + Write, sem Bash livre)
- ✓Timeout configurado, fallback em caso de erro
✗ Não funciona em CI
- ✗Skills que perguntam ao usuário (clarificações)
- ✗Skills que dependem de estado de sessão local
- ✗Skills com TUIs interativas ou prompts
- ✗Skills que demoram > 10min (timeout do runner)
⚠️ Dica importante
Antes de rodar uma skill em CI, teste com --non-interactive localmente. Se ela pede input em algum ponto, ela vai travar no runner — e o GitHub Actions cobra os 6h até o timeout.
🧪 Exemplo prático: /tdd em GitHub Actions
Cenário concreto: quando um PR quebra testes, dispare a skill /tdd automaticamente. Ela analisa o erro, propõe um fix e abre um commit no próprio PR. O dev acorda no dia seguinte com o build verde.
📄 .github/workflows/tdd-loop.yml
name: tdd-loop
on:
pull_request:
types: [opened, synchronize]
jobs:
run-tdd:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run tests (capture failure)
id: tests
run: npm test || echo "failed=true" >> $GITHUB_OUTPUT
- name: Run /tdd skill
if: steps.tests.outputs.failed == 'true'
uses: anthropics/claude-action@v1
with:
skill: tdd
input: "fix failing tests in this PR"
allowed-tools: "Read,Edit,Bash(npm test)"
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Commit fix
if: steps.tests.outputs.failed == 'true'
run: |
git config user.name "tdd-bot"
git config user.email "bot@example.com"
git add -A
git commit -m "fix: /tdd auto-repair" || exit 0
git push
Trigger no PR
Roda em cada opened e synchronize (novos commits)
Capturamos o fluxo desde o início — não esperamos o dev pedir ajuda.
Roda testes e detecta falha
Output failed=true serve de condição pros próximos steps
Só ativa a skill se de fato algo quebrou — não desperdiça quota de API.
Aciona /tdd com tools restritas
allowed-tools limita a Read, Edit e Bash(npm test) — nada de rm ou curl
A allowlist é o cinto de segurança. Sem ela, a skill teria poder demais num ambiente sem revisão humana.
Commit + push de volta no PR
A correção vira parte da história do PR, com autoria do bot
O dev revisa o diff humano e o do bot — não um patch fantasma sem contexto.
🧩 Integração com Cursor, Aider, Continue
Cursor, Aider e Continue não têm o conceito de skill nativo. Eles têm rules, conventions ou system prompts. A boa notícia: o conteúdo de uma skill cabe perfeitamente nesses formatos.
📐 Estado atual de portabilidade
- Cursor: arquivos
.cursorrulesaceitam markdown direto da skill (sem frontmatter) - Aider: usa
CONVENTIONS.mdou--readpra carregar contexto - Continue:
config.jsonpermitesystemMessagecom o corpo da skill - Cline / Roo Code: aceita
.clinerulesem markdown
🔄 Adapter genérico — emite pra qualquer agente
// scripts/sync-skills.ts
import { readFileSync, writeFileSync } from "fs";
import { stripFrontmatter } from "./utils";
const skill = readFileSync("./skills/tdd/SKILL.md", "utf8");
const body = stripFrontmatter(skill);
// Cursor
writeFileSync(".cursorrules", body);
// Aider
writeFileSync("CONVENTIONS.md", body);
// Continue
const config = JSON.parse(readFileSync(".continue/config.json", "utf8"));
config.systemMessage = body;
writeFileSync(".continue/config.json", JSON.stringify(config, null, 2));
console.log("✓ skill syncronized to Cursor / Aider / Continue");
Limitação: agentes sem conceito de skill carregam o conteúdo o tempo todo (sem ativação dinâmica). Pra skills curtas, sem problema. Pra skills longas, considere quebrar em rules menores e específicas por contexto.
🎼 Skills + MCP servers
A composição mais poderosa hoje: skill orquestra, MCP server executa. A skill guia o modelo no quando e como; o MCP server entrega tools especializadas (DB, GitHub, Figma, Slack).
🏗️ Arquitetura de composição
┌──────────────────────────────────────────────────────────┐
│ USUÁRIO │
│ "/release-notes v2.3" │
└────────────────────────┬─────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ SKILL: /release-notes (markdown + frontmatter) │
│ "Quando o user pedir release notes: │
│ 1. liste commits desde a última tag │
│ 2. agrupe por tipo (feat/fix/chore) │
│ 3. publique no Slack #releases" │
└──────┬───────────────────┬───────────────────┬───────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌───────────────┐ ┌──────────────┐
│ MCP: github │ │ MCP: linear │ │ MCP: slack │
│ list-commits │ │ get-issues │ │ post-message │
└──────────────┘ └───────────────┘ └──────────────┘
🎯 Princípio de design
A skill é o roteiro; o MCP é a caixa de ferramentas. Roteiro sem caixa é teoria; caixa sem roteiro é caos.
- →Skill descreve quando usar cada tool MCP
- →MCP server expõe o que cada tool faz e seu schema
- →Modelo amarra os dois no como da execução
🚧 Limitações atuais
Cross-runtime é um trabalho em andamento. Algumas coisas já funcionam bem; outras ainda dependem de gambiarra. Mapa honesto do território:
✓ Funciona bem cross-runtime
- ✓Skills declarativas (sem código)
- ✓Tools básicas: ler, escrever, executar
- ✓MCP servers (padrão aberto)
- ✓Skills curtas (< 200 linhas)
- ✓Sync via polyskill / adapters
✗ Ainda não / com ressalvas
- ✗Subagents paralelos (só Claude Code)
- ✗Hooks (PreToolUse, PostToolUse): específicos
- ✗Slash commands com argumentos complexos
- ✗Modelos de permissão divergem bastante
- ✗Skills que usam features experimentais de um runtime
🗺️ Roadmap (estado real, não promessas)
O Matt mencionou no repo que o objetivo é que "toda skill do curso rode em pelo menos Claude Code e Codex". Hoje (2026), isso vale pras 80% mais simples. As skills que dependem de subagents paralelos ou hooks pesados ainda são específicas de runtime.
Tendência: padronização vai vir do MCP, não de um formato de skill universal. Se sua skill é principalmente um system prompt + tools, ela já é portável hoje.
🎓 Conclusão do curso
Você chegou ao fim. Recap das três trilhas, num parágrafo cada — pra fixar o caminho percorrido.
Trilha 1 — Fundamentos: os 4 problemas
Por que skills existem e o que elas resolvem
Mostramos os 4 problemas que skills resolvem: contexto repetido, prompts difusos, falta de processo replicável e ausência de memória entre sessões. A partir daí, escolher uma skill virou uma decisão racional, não estética.
Trilha 2 — Sobre o Repo: estrutura e instalação
Como o repositório do Matt Pocock está organizado e como instalar
Caminhamos pela estrutura skills/, productivity/, engineering/, misc/, e fizemos instalação via plugin do Claude Code. Depois disso, qualquer skill nova encontra seu lugar sem você precisar perguntar.
Trilha 3 — Avançado: composição, customização, integração
Como ir além do uso básico
Compomos skills entre si, customizamos pro contexto local do projeto e integramos com outros agentes via MCP e CI/CD. Agora você não usa skills — você constrói com elas.
🚀 Próximos passos
Teoria sem prática vira poeira. Próximo passo concreto: escolha um projeto real seu nas próximas 48h e instale 3 skills. Use por uma semana inteira. Note o que economiza e o que falha.
Depois disso, três caminhos:
- 1.Customize: ajuste o frontmatter, edite o corpo, faça suas próprias
- 2.Componha: encadeie skills (ex:
/grill-me+/tdd) - 3.Porte: use
polyskille leve suas skills pra Codex / Cursor
🎯 O que você sai sabendo
Continue aprendendo:
- 📬 Newsletter do Matt Pocock: aihero.dev/s/skills-newsletter
- 📦 Repositório do curso: github.com/inematds/mp-skill
- 🌐 INEMA.CLUB — comunidade brasileira: inema.club