Agent Skills: o guia do SKILL.md para Claude Code e Codex

O que é um skill, onde cada agente o vai procurar, e o que muda realmente: um skill construído linha a linha, depois executado pelo Codex com e sem ele.

Agent Skills: o guia do SKILL.md para Claude Code e Codex
Resposta rápida

Um skill é uma pasta que contém um SKILL.md: um frontmatter YAML (name, description) e instruções em Markdown, mais scripts e referências carregados a pedido. Só a descrição fica em contexto permanentemente, e é truncada, o que faz dela o único gatilho que conta. A mesma pasta funciona no Claude Code, no Codex, no Copilot e no OpenCode, desde que seja colocada no diretório certo.

Um skill é uma pasta que contém um ficheiro SKILL.md. Escrevê-lo é a parte fácil. O resto exige saber onde o colocar para que o agente o encontre, verificar que se ativa mesmo, e medir o que custa o resto do tempo. Este guia faz as três coisas, sobre um skill construído e executado para a ocasião.

O que é um skill, exatamente?

O formato Agent Skills foi criado pela Anthropic e depois publicado como standard aberto, a especificação vive hoje em agentskills.io. Cabe em poucas linhas: uma pasta, um SKILL.md obrigatório, e o que quiseres ao lado.

bash
regex-verifiee/
├── SKILL.md          # obrigatório: frontmatter YAML + instruções Markdown
├── scripts/          # opcional: código que o agente executa
├── references/       # opcional: documentação carregada a pedido
└── examples/         # opcional: modelos, conjuntos de dados

O frontmatter é curto e restrito. name: 64 caracteres no máximo, minúsculas, números e hífenes apenas, sem hífen no início ou no fim, sem hífen duplo, e tem de ser idêntico ao nome da pasta-mãe. description: obrigatório, 1 024 caracteres no máximo, diz o que o skill faz e quando usá-lo. Três campos facultativos completam o conjunto: license, compatibility (500 caracteres) e metadata. Um sexto, allowed-tools, está marcado como experimental na especificação.

O mecanismo que torna isto interessante chama-se divulgação progressiva, em três níveis. No arranque, o agente só carrega o name e a description de cada skill, a especificação visa uma centena de tokens. Quando uma tarefa corresponde, lê o corpo do SKILL.md (menos de 5 000 tokens recomendados, 500 linhas no máximo). Só depois, se precisar, abre os ficheiros de scripts/, references/ ou assets/. O artigo de engenharia da Anthropic de 16 de outubro de 2025 formula-o ao contrário: cuida do name e da description, porque é com base neles, e só neles, que o agente decide ativar o skill.

Um skill que nunca se ativa custa portanto na mesma a sua descrição, em cada sessão, em todas as janelas de contexto. É exatamente isso que mede o comando /skill-doctor do Claude Code, e é o primeiro item de despesa examinado no relato de experiência da Spotify sobre a fatura de tokens.

Onde é que cada agente vai procurar os skills?

É a parte que ninguém escreve corretamente, porque muda de ferramenta para ferramenta. Eis os caminhos tal como figuram na documentação de cada fornecedor, aberta a 7 de setembro de 2026.

Ferramenta Projeto Utilizador
Claude Code .claude/skills/<nom>/SKILL.md ~/.claude/skills/<nom>/SKILL.md
Codex .agents/skills/ (e .codex/skills/, ver mais abaixo) $CODEX_HOME/skills, ~/.agents/skills
GitHub Copilot .github/skills, .claude/skills, .agents/skills ~/.copilot/skills, ~/.agents/skills
OpenCode .opencode/skills, .claude/skills, .agents/skills ~/.config/opencode/skills, ~/.claude/skills, ~/.agents/skills

Daí decorrem duas coisas. .agents/skills está a tornar-se o caminho neutro comum, Codex, Copilot e OpenCode leem-no os três. E tanto o Copilot como o OpenCode também leem .claude/skills, a pasta do Claude Code serve de formato de troca de facto. Uma mesma pasta de skill pode portanto servir vários agentes sem ser duplicada. Do lado das superfícies, o GitHub anuncia os skills para o agente cloud, a revisão de código, o Copilot CLI, a aplicação GitHub Copilot e o modo agente do VS Code e dos IDE JetBrains.

A 7 de setembro de 2026, a vitrine do agentskills.io regista 46 produtos compatíveis, de Cursor a Goose, passando por Junie, Kiro, Roo Code, Laravel Boost, OpenCode e OpenClaw.

Construir um skill que serve: regex-verifiee

Um bom skill codifica um procedimento que repetes e que o agente salta quando não é imposto. O caso escolhido aqui: as expressões regulares. Um agente dá-te uma regex em três segundos, sem nunca a executar sobre um contraexemplo. O skill regex-verifiee proíbe essa resposta.

O SKILL.md, na íntegra para o frontmatter e o início do corpo:

markdown
---
name: regex-verifiee
description: Écrire une expression régulière et la prouver avant de la livrer. À utiliser dès qu'une demande porte sur une regex, une expression régulière, une validation de format (code postal, SIRET, IBAN, e-mail, téléphone, slug, plaque), un preg_match, un preg_replace ou un RegExp. Impose un fichier de cas valides et invalides, son exécution dans le moteur cible (Node et PHP), puis la livraison regex + tableau de cas + limites.
---

# Regex vérifiée

Une regex qui n'a jamais tourné sur ses contre-exemples n'est pas une regex, c'est une intuition.
Suivez ces cinq étapes dans l'ordre. Ne sautez pas l'étape 4.

## Procédure

1. **Cadrer.** Demandez, ou décidez explicitement : le moteur (JavaScript, PCRE/PHP, POSIX), la
   chaîne testée (déjà nettoyée ou brute), et si la valeur peut être vide.
2. **Proposer.** Écrivez la regex ancrée et, en une phrase par groupe, ce que chaque partie accepte.
3. **Écrire les cas.** Créez un fichier JSON : au moins six valides et six invalides. Les invalides
   doivent inclure les pièges de `references/cas-types.md` pour le type de donnée concerné.
4. **Exécuter.** Lancez le script sur les deux moteurs et collez la sortie brute dans la réponse.
5. **Livrer.** Réponse finale = la regex + le tableau de cas produit par le script + les limites.

A descrição é deliberadamente tagarela em vocabulário de ativação: « regex », « expression régulière », « code postal », « SIRET », « preg_match », « RegExp ». São as palavras que o leitor escreve. Escreve-a na língua em que te falam, não na da documentação.

A pasta contém depois um ficheiro de casos em formato JSON, dois executores (um em Node, um em PHP) que leem o mesmo ficheiro, e uma referência references/cas-types.md que lista os contraexemplos por tipo de dado. O ficheiro de casos parece-se com isto:

json
{
  "name": "code postal français",
  "engine": "both",
  "pattern": "^(?:0[1-9]|[1-8]\\d|9[0-8])\\d{3}$",
  "flags": "",
  "valid": ["01000", "20000", "62500", "75001", "97400", "98000"],
  "invalid": ["", "00000", "99999", "7500", "750011", "75 001", "2A000", " 75001", "75001\n"]
}

Os dois executores mostram a mesma tabela e devolvem um código de saída não nulo assim que um caso falha. É esse código de saída que faz o trabalho: o agente não pode concluir com um comando em erro.

Primeira surpresa, obtida ao lançar o arnês eu mesmo antes sequer de ligar um agente: a mesma regex não dá o mesmo veredito nos dois motores.

bash
$ node scripts/verifier.mjs examples/code-postal-fr.json
moteur : node v22.23.2
regex  : /^(?:0[1-9]|[1-8]\d|9[0-8])\d{3}$/
...
"75001\n"  false    false   ok

15 cas, 0 échec(s)

$ php scripts/verifier.php examples/code-postal-fr.json
moteur : PHP 8.4.19, PCRE 10.47 2025-10-21
regex  : /^(?:0[1-9]|[1-8]\d|9[0-8])\d{3}$/
...
"75001\n"  false    true    ECHEC

15 cas, 1 échec(s)

Em PCRE, $ aceita uma quebra de linha final, em JavaScript, não. Um campo de formulário que chega com um \n colado no fim passa portanto a validação PHP e falha a validação JavaScript, com a mesma expressão escrita nos dois ficheiros. As duas correções, ambas verificadas aqui: o modificador D do lado do PHP (preg_match('/^\d{5}$/D', "75001\n") devolve 0), ou uma âncora portátil (?![\s\S]) em vez de $, que passa os quinze casos nos dois motores.

Testá-lo com o Codex sem tocar em ~/.codex

A documentação do Codex descreve uma pilha de raízes: $CWD/.agents/skills, as pastas-mãe, $REPO_ROOT/.agents/skills, depois $HOME/.agents/skills, /etc/codex/skills e os skills entregues com o CLI. Ou seja, existe um skill de projeto: não é preciso escrever em ~/.codex/skills nem em ~/.codex/config.toml para o experimentar.

Falta verificar o que o binário faz realmente. O Codex expõe para isso um comando de depuração que mostra o prompt tal como o modelo o recebe, sem chamar o modelo:

bash
$ mkdir -p demo-projet/.codex/skills
$ cp -R regex-verifiee demo-projet/.codex/skills/
$ cd demo-projet && codex debug prompt-input "test"

### Skill roots
- `r0` = `/…/demo-projet/.codex/skills`
- `r1` = `/Users/gekkode/.codex/skills`
- `r2` = `/Users/gekkode/.agents/skills`
- `r3` = `/Users/gekkode/.codex/skills/.system`
- `r4` … `r10` = caches de plugins
### Available skills
- regex-verifiee: Écrire une expression régulière et la prouver avant de la livrer. À utiliser dès qu'une deman (file: r0/regex-verifiee/SKILL.md)

O skill é visto, a partir de <projet>/.codex/skills, um caminho que a documentação não menciona, mas que o binário varre mesmo, em primeira posição. Ao colocar um segundo skill de teste em <projet>/.agents/skills, apareceu uma raiz r11 com este caminho: os dois funcionam, e a pasta .codex/ passa primeiro.

Chega o teste real. Mesmo prompt, mesmo modelo, mesma máquina, com poucos minutos de diferença: uma vez no projeto que contém o skill, uma vez numa pasta vazia.

bash
codex exec -m gpt-6-astra -s workspace-write --skip-git-repo-check \
  "Dans un formulaire PHP, je dois valider le code postal saisi par le visiteur. Donne-moi l'expression reguliere a utiliser."

Sem o skill: 19 segundos, zero comandos executados, e esta resposta, preg_match('/\A[0-9]{5}\z/', $codePostal), com uma frase a dizer que a expressão verifica o formato e não a existência do código postal. Passada pelo arnês, esta regex falha dois casos em quinze: aceita 00000 e 99999.

Com o skill: 106 segundos, dez comandos executados. O Codex leu o SKILL.md, depois os dois scripts, depois references/cas-types.md, a divulgação progressiva completa, nível a nível. Escreveu depois o seu próprio ficheiro de casos (dezoito casos, incluindo "75001\n00000" e "2a000", retomados da referência), lançou os dois executores, e entregou isto:

php
$codePostal = $_POST['code_postal'] ?? '';

$valide = is_string($codePostal)
    && preg_match('/\A(?:0[1-9]|[1-8][0-9]|9[0-8])[0-9]{3}\z/', $codePostal) === 1;

Com, por baixo, as duas tabelas de dezoito casos e uma secção «limites». Repara que não usou a mesma expressão nos dois motores. \A … \z para PCRE, ^ … (?![\s\S]) para JavaScript. O skill nunca lhe disse para fazer isso, ele deduziu-o ao executar os casos.

Um skill de umas sessenta linhas transformou assim uma resposta em três segundos, errada em dois casos, num procedimento de dois minutos cujo resultado é verificável. A ativação fez-se sozinha, pela descrição: o prompt não contém nem a palavra «skill», nem o nome regex-verifiee. No Codex, também se pode forçar a mão com $regex-verifiee no prompt, no Claude Code, com /regex-verifiee.

Quanto custa uma descrição, e porque é cortada

Durante a execução, o Codex emitiu um aviso que eu não esperava:

Skill descriptions were shortened to fit the skills context budget. Codex can still see every skill, but some descriptions are shorter. Disable unused skills or plugins to leave more room for the rest.

Verificação feita com um skill de teste cuja descrição é uma sequência de trezentos caracteres conhecidos: nesta máquina, com 146 skills instalados, cada descrição é cortada a 94 caracteres. A minha descrição de 422 caracteres chega portanto ao modelo amputada em dois terços, a meio da palavra «demande». Tudo o que vem depois, «SIRET», «IBAN», «preg_match», «RegExp», não serve para nada para a ativação.

O orçamento é ajustável. O Codex aceita uma chave skills.max_context_tokens, que se pode passar em sobrecarga sem escrever no ficheiro de configuração:

bash
codex debug prompt-input -c skills.max_context_tokens=16000 "test"
Orçamento Comprimento de descrição conservado Tamanho do bloco de skills
2 000 40 caracteres 8 202 caracteres
4 000 54 caracteres 16 492 caracteres
5 000 82 caracteres 20 482 caracteres
predefinição 94 caracteres 22 230 caracteres
8 000 198 caracteres 32 295 caracteres
16 000 300 caracteres (sem corte) 40 201 caracteres

Daí saem duas regras. Coloca as palavras de ativação nos primeiros noventa caracteres da descrição, o resto é um bónus. E conta com isto: quanto mais skills instalas, mais rebaixas a descrição de todos os outros. O catálogo ocupava aqui 22 230 caracteres de contexto, em cada sessão, para 146 skills dos quais só uso um punhado. Desinstalar vale mais do que aumentar o orçamento.

O Claude Code aplica o mesmo princípio com números publicados. O seu orçamento de listagem vale 1% da janela de contexto do modelo, ajustável por skillListingBudgetFraction ou pela variável de ambiente SLASH_COMMAND_TOOL_CHAR_BUDGET. Cada entrada está de qualquer forma limitada: description e when_to_use concatenados são cortados a 1 536 caracteres, limite ajustável por skillListingMaxDescChars. E quando a lista transborda, a documentação é explícita sobre a ordem de sacrifício: o Claude Code apaga primeiro as descrições dos skills que menos invocas. O nome, esse, fica sempre na lista.

As duas ferramentas oferecem a mesma saída: desativar em vez de inchar o orçamento. Do lado do Claude Code, a definição skillOverrides aceita quatro estados por skill, on, name-only (o nome sem a descrição), user-invocable-only e off, e o comando /skills escreve-os por ti em .claude/settings.local.json. Do lado do Codex, um bloco em ~/.codex/config.toml:

toml
[[skills.config]]
path = "/chemin/vers/le/skill/SKILL.md"
enabled = false

Carregar e distribuir o mesmo skill no Claude Code

A pasta não muda. Dois locais, consoante o skill te segue para todo o lado ou pertence ao repositório:

bash
cp -R regex-verifiee ~/.claude/skills/          # para todos os teus projetos
cp -R regex-verifiee mon-projet/.claude/skills/ # versionado com o repositório

A documentação do Claude Code acrescenta campos de frontmatter ausentes da especificação. disable-model-invocation: true impede a ativação automática e reserva o skill a uma chamada manual por /nom, a definição certa para tudo o que faz push, deploy ou apaga. allowed-tools concede permissões de ferramentas apenas para o turno de conversa que invoca o skill, e a permissão cai na mensagem seguinte. user-invocable: false reserva o skill ao modelo.

Para distribuir o skill a uma equipa, a embalagem é um plugin: um manifesto .claude-plugin/plugin.json na raiz, o skill na pasta skills/, e um ficheiro .claude-plugin/marketplace.json que declara a marketplace. A instalação faz-se depois por /plugin marketplace add compte/depot, depois /plugin install mon-plugin@ma-marketplace, e /reload-plugins recarrega sem sair da sessão.

Fica a pergunta incómoda. O teu skill ativa-se, e serve para alguma coisa? O Claude Code responde às duas metades. /skill-doctor, que exige a versão 2.1.252 ou mais recente, lista os skills carregados, o seu número de invocações e o seu último uso, e assinala os que nunca serviram, o relatório abre-se no separador Stats do gestor de plugins, e imprime-se em texto simples em modo -p. E o claude plugin eval, em acesso antecipado, automatiza exatamente a comparação que fiz à mão mais acima. A ajuda do comando, nesta máquina, é inequívoca:

bash
$ claude plugin eval --help
Run eval cases (evals/**/case.yaml or evals/**/prompt.md + graders/*.md) against
a plugin and report scored results.

  --ablation <mode>   Run a no-plugin baseline arm and report the score delta
                      (none | with-without; default: with-without …)
  --runs <n>          Override per-case runs (default: case.runs ?? 3)
  --threshold <0..1>  Exit 1 if any case score is below this threshold
  --json              Emit aggregate-result.json to stdout (for CI)

Um caso de avaliação é uma pasta evals/<cas>/ contendo um prompt.md, um prompt realista que sobretudo não nomeia o skill, e corretores em graders/. A opção --ablation with-without volta a executar cada caso com e sem o plugin e mostra a diferença de pontuação: é a única forma honesta de provar que um skill traz alguma coisa.

Partilhar um skill, e verificar os dos outros

Três circuitos de distribuição coexistem. Um repositório Git nu, que se clona na pasta certa, o mais simples e o mais auditável. Um plugin, tanto para o Claude Code como para o Codex: do lado do Codex, cada plugin vive em plugins/<nom>/ com um manifesto .codex-plugin/plugin.json obrigatório e pastas facultativas skills/, .app.json, .mcp.json. E as marketplaces públicas: ClawHub, Skills.sh, SkillsMP.

Repara de passagem que o catálogo github.com/openai/skills, ainda citado por todo o lado, está marcado como obsoleto e reencaminha para github.com/openai/plugins. O skill de sistema $skill-installer, esse, instala sempre em $CODEX_HOME/skills/<nom>.

O terceiro circuito exige desconfiança. A auditoria ToxicSkills publicada pela Snyk a 5 de fevereiro de 2026 passou a pente fino 3 984 skills do ClawHub e do skills.sh: 1 467 deles (36,82%) apresentam pelo menos uma falha de segurança, e 534, 13,4% do total, pelo menos uma falha crítica. Setenta e seis cargas maliciosas foram confirmadas por revisão humana: roubo de credenciais, instalação de porta dos fundos, exfiltração de dados, oito destes skills continuavam online no dia da publicação. Todas as cargas confirmadas contêm código malicioso, e 91% acrescentam-lhe injeção de prompt.

Um skill é texto que o teu agente vai seguir, mais scripts que vai executar com os teus privilégios. Antes de instalares um, lê o SKILL.md na íntegra, lê cada ficheiro de scripts/, procura chamadas de rede e cadeias codificadas em base64, e recusa qualquer skill que peça uma chave de API ou um token. Os mesmos reflexos que para a sandbox e as permissões de um agente de código.

Skills ou MCP?

Skills e MCP não respondem à mesma necessidade. Um skill traz um procedimento e um saber-fazer, em Markdown, sem processo, sem rede, sem autenticação. Um servidor MCP traz ferramentas e dados: fala com uma base de dados, uma API, um sistema de ficheiros remoto, com as credenciais que isso implica.

O teste mais rápido cabe numa frase. Se a tua necessidade se escreve «procede assim», é um skill. Se se escreve «vai buscar isto» ou «escreve aquilo nalgum lado», é um servidor MCP. A diferença de custo segue a mesma linha: um skill inativo custa a sua descrição, umas dezenas de tokens, enquanto um servidor MCP ligado custa a definição de todas as suas ferramentas, permanentemente, em cada sessão.

Os dois combinam-se muito bem: um skill que diz por que ordem chamar as ferramentas de um servidor MCP é muitas vezes o melhor dos dois mundos. É aliás a direção tomada pelo próprio protocolo, a revisão 2026-07-28 da especificação MCP lista um grupo de trabalho «Skills over MCP», cujo objetivo é descobrir e consumir instruções estruturadas por MCP. Para a parte do servidor, o guia do servidor MCP em PHP assume o resto.

Os quatro erros que se repetem

Uma descrição que descreve o skill em vez de dizer quando o usar. «Ajuda com regex» nunca se ativa. Escreve as palavras que o utilizador escreve, na língua dele, e coloca-as no início, por causa do corte medido mais acima.

Um SKILL.md de duas mil linhas. O corpo inteiro entra em contexto na ativação. A especificação recomenda ficar abaixo de 500 linhas e remeter o detalhe para references/, carregado só se necessário. No teste acima, o Codex só abriu cas-types.md no momento de escrever os seus casos.

Segredos dentro do skill. Um skill partilha-se, versiona-se, publica-se. Uma chave de API esquecida lá dentro acaba num repositório público. O skill lê uma variável de ambiente, não a contém.

Empilhar skills «por precaução». Cada skill instalado encurta a descrição de todos os outros e rói a janela de contexto. Faz o inventário do que nunca se ativou e apaga-o.

A reter

  • Um skill = uma pasta + um SKILL.md (name com 64 caracteres no máximo, description com 1 024 no máximo) + o que quiseres ao lado.
  • Só a descrição é carregada permanentemente, e é truncada: as palavras de ativação vão nos primeiros 90 caracteres.
  • .agents/skills do lado do projeto, mais .claude/skills lido pelo Copilot e pelo OpenCode: uma mesma pasta serve vários agentes.
  • Um skill de projeto testa-se sem instalar nada em tua casa: <projet>/.codex/skills/ para o Codex, <projet>/.claude/skills/ para o Claude Code.
  • O bom skill impõe um procedimento verificável e um código de saída, não uma instrução de estilo.
  • Lê na íntegra qualquer skill instalado a partir de uma marketplace: 13,4% dos auditados pela Snyk têm uma falha crítica.

Erros frequentes

Descrição demasiado vaga «Ajuda com regex» nunca se ativa. Nomeia os casos de uso e as palavras que o utilizador escreve, na língua dele, e coloca-as no início: o Codex só guardou aqui os primeiros 94 caracteres.
SKILL.md interminável O corpo inteiro entra em contexto na ativação. Fica abaixo de 500 linhas e transfere o detalhe para references/, que o agente só abre se precisar.
Nome da pasta diferente do campo name A especificação impõe a igualdade estrita, em minúsculas, números e hífenes, sem hífen duplo nem hífen no início ou no fim. Um desvio e o skill é ignorado ou recusado na instalação.
Um segredo dentro do skill Um skill versiona-se e publica-se: uma chave de API esquecida lá dentro acaba num repositório público. Lê antes uma variável de ambiente.
Skill instalado sem ser lido Um SKILL.md é uma instrução que o teu agente vai seguir, e scripts/ código que vai executar com os teus privilégios. Lê tudo antes, incluindo os scripts.

Claude CodeCodexCopilot CLIOpenCodeSkills

Damien Flandrin Programador web desde 2010, criador da Gekkode e do Email Impact. Cada artigo é testado num projeto real antes de ser publicado. Contacto
Newsletter

Os novos testes, tutoriais e projetos, por e-mail.

Testes reproduzíveis, código versionado, resultados datados. Nunca spam.