
Uno skill è una cartella che contiene uno SKILL.md: un frontmatter YAML (name, description) e istruzioni Markdown, più script e riferimenti caricati su richiesta. Solo la descrizione resta in contesto in permanenza, ed è troncata, il che ne fa l'unico fattore di attivazione che conta. La stessa cartella funziona in Claude Code, Codex, Copilot e OpenCode, a condizione di metterla nella directory giusta.
Uno skill è una cartella che contiene un file SKILL.md. Scriverlo è la parte facile. Il resto richiede di sapere dove metterlo perché l’agente lo trovi, verificare che si attivi davvero, e misurare quanto costa il resto del tempo. Questa guida fa tutte e tre le cose, su uno skill costruito ed eseguito per l’occasione.
Cos’è esattamente uno skill?
Il formato Agent Skills è stato creato da Anthropic e poi pubblicato come standard aperto, la specifica vive oggi su agentskills.io. Si riassume in poche cose: una cartella, uno SKILL.md obbligatorio, e quello che vuoi accanto.
regex-verifiee/
├── SKILL.md # obbligatorio: frontmatter YAML + istruzioni Markdown
├── scripts/ # opzionale: codice che l'agente esegue
├── references/ # opzionale: documentazione caricata su richiesta
└── examples/ # opzionale: modelli, dati di esempioIl frontmatter è breve e vincolato. name: al massimo 64 caratteri, solo minuscole, cifre e trattini, niente trattino in testa o in coda, niente trattino doppio, e deve essere identico al nome della cartella genitore. description: obbligatorio, al massimo 1.024 caratteri, dice cosa fa lo skill e quando usarlo. Tre campi facoltativi completano il tutto: license, compatibility (500 caratteri) e metadata. Un sesto, allowed-tools, è segnato come sperimentale nella specifica.
Il meccanismo che rende la cosa interessante si chiama divulgazione progressiva, in tre livelli. All’avvio, l’agente carica solo il name e la description di ogni skill, la specifica punta a un centinaio di token. Quando un compito corrisponde, legge il corpo dello SKILL.md (meno di 5.000 token raccomandati, 500 righe massimo). Solo dopo, se ne ha bisogno, apre i file di scripts/, references/ o assets/. L’articolo tecnico di Anthropic del 16 ottobre 2025 lo formula al contrario: cura il name e la description, perché è su questo, e solo su questo, che l’agente decide di attivare lo skill.
Uno skill che non si attiva mai costa quindi comunque la sua descrizione, a ogni sessione, in tutte le finestre di contesto. È esattamente ciò che misura il comando /skill-doctor di Claude Code, ed è la prima voce di spesa esaminata nel resoconto di Spotify sulla bolletta dei token.
Dove va a cercare gli skill ogni agente?
È la parte che nessuno scrive correttamente, perché cambia da uno strumento all’altro. Ecco i percorsi così come compaiono nella documentazione di ogni editore, consultata il 7 settembre 2026.
| Strumento | Progetto | Utente |
|---|---|---|
| Claude Code | .claude/skills/<nom>/SKILL.md | ~/.claude/skills/<nom>/SKILL.md |
| Codex | .agents/skills/ (e .codex/skills/, vedi più sotto) | $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 |
Ne derivano due cose. .agents/skills sta diventando il percorso neutro comune, Codex, Copilot e OpenCode lo leggono tutti e tre. E sia Copilot sia OpenCode leggono anche .claude/skills, la cartella di Claude Code funge di fatto da formato di scambio. Una stessa cartella di skill può quindi servire più agenti senza essere duplicata. Sul fronte delle superfici, GitHub annuncia gli skill per l’agente cloud, la revisione del codice, Copilot CLI, l’app GitHub Copilot e la modalità agente di VS Code e degli IDE JetBrains.
Il 7 settembre 2026, la vetrina di agentskills.io elenca 46 prodotti compatibili, da Cursor a Goose passando per Junie, Kiro, Roo Code, Laravel Boost, OpenCode e OpenClaw.
Costruire uno skill che serve: regex-verifiee
Un buon skill codifica una procedura che ripeti e che l’agente salta quando non gliela imponi. Il caso scelto qui: le espressioni regolari. Un agente ti tira fuori una regex in tre secondi, senza mai eseguirla su un controesempio. Lo skill regex-verifiee vieta questo tipo di risposta.
Il SKILL.md, per intero per quanto riguarda il frontmatter e l’inizio del corpo:
---
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.La descrizione è deliberatamente prolissa nel vocabolario di attivazione: «regex», «espressione regolare», «codice postale», «SIRET», «preg_match», «RegExp». Sono le parole che l’utente digita. Scrivila nella lingua in cui ti si parla, non in quella della documentazione.
La cartella contiene poi un file di casi in formato JSON, due esecutori (uno in Node, uno in PHP) che leggono lo stesso file, e un riferimento references/cas-types.md che elenca i controesempi per tipo di dato. Il file di casi si presenta così:
{
"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"]
}I due esecutori mostrano la stessa tabella e restituiscono un codice di uscita diverso da zero non appena un caso fallisce. È questo codice di uscita che fa il lavoro: l’agente non può concludere su un comando in errore.
Prima sorpresa, ottenuta lanciando io stesso l’harness prima ancora di collegare un agente: la stessa regex non dà lo stesso verdetto nei due motori.
$ 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)In PCRE, $ accetta un ritorno a capo finale, in JavaScript no. Un campo di modulo che arriva con un \n incollato in fondo passa quindi la validazione PHP e fallisce quella JavaScript, con la stessa espressione scritta nei due file. Le due correzioni, entrambe verificate qui: il modificatore D lato PHP (preg_match('/^\d{5}$/D', "75001\n") restituisce 0), oppure un ancoraggio portabile (?![\s\S]) al posto di $, che supera i quindici casi in entrambi i motori.
Testarlo con Codex senza toccare ~/.codex
La documentazione di Codex descrive una pila di radici: $CWD/.agents/skills, le cartelle genitore, $REPO_ROOT/.agents/skills, poi $HOME/.agents/skills, /etc/codex/skills e gli skill forniti con la CLI. In altre parole, uno skill di progetto esiste: non serve scrivere in ~/.codex/skills né in ~/.codex/config.toml per provarlo.
Resta da verificare cosa fa davvero il binario. Codex espone per questo un comando di debug che mostra il prompt così come lo riceve il modello, senza chiamare il modello:
$ 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)Lo skill viene visto, da <projet>/.codex/skills, un percorso che la documentazione non menziona, ma che il binario scansiona davvero, in prima posizione. Depositando un secondo skill spia in <projet>/.agents/skills, è comparsa una radice r11 con questo percorso: entrambi funzionano, e la cartella .codex/ passa per prima.
Arriva la prova reale. Stesso prompt, stesso modello, stessa macchina, a pochi minuti di distanza: una volta nel progetto che contiene lo skill, una volta in una cartella vuota.
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."Senza lo skill: 19 secondi, zero comandi eseguiti, e questa risposta, preg_match('/\A[0-9]{5}\z/', $codePostal), con una frase che dice che l’espressione verifica il formato e non l’esistenza del codice postale. Passata nell’harness, questa regex fallisce due casi su quindici: accetta 00000 e 99999.
Con lo skill: 106 secondi, dieci comandi eseguiti. Codex ha letto lo SKILL.md, poi i due script, poi references/cas-types.md, la divulgazione progressiva al completo, livello per livello. Ha poi scritto il proprio file di casi (diciotto casi, tra cui "75001\n00000" e "2a000", ripresi dal riferimento), lanciato i due esecutori, e consegnato questo:
$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;Con, sotto, le due tabelle di diciotto casi e una sezione «limiti». Nota che non ha usato la stessa espressione nei due motori. \A … \z per PCRE, ^ … (?![\s\S]) per JavaScript. Lo skill non gli ha mai detto di farlo, lo ha dedotto eseguendo i casi.
Uno skill di una sessantina di righe ha quindi trasformato una risposta in tre secondi, sbagliata su due casi, in una procedura di due minuti il cui risultato è verificabile. L’attivazione è avvenuta da sola, sulla descrizione: il prompt non contiene né la parola «skill», né il nome regex-verifiee. In Codex, si può anche forzare la mano con $regex-verifiee nel prompt, in Claude Code, con /regex-verifiee.
Quanto costa una descrizione, e perché viene tagliata
Durante l’esecuzione, Codex ha emesso un avviso che non mi aspettavo:
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 fatta con uno skill spia la cui descrizione è una sequenza di trecento caratteri noti: su questa macchina, con 146 skill installati, ogni descrizione viene tagliata a 94 caratteri. La mia descrizione di 422 caratteri arriva quindi al modello amputata di due terzi, a metà della parola «demande». Tutto ciò che viene dopo, «SIRET», «IBAN», «preg_match», «RegExp», non serve a nulla per l’attivazione.
Il budget è regolabile. Codex accetta una chiave skills.max_context_tokens, che si può passare in override senza scrivere nel file di configurazione:
codex debug prompt-input -c skills.max_context_tokens=16000 "test"| Budget | Lunghezza di descrizione conservata | Dimensione del blocco skill |
|---|---|---|
| 2.000 | 40 caratteri | 8.202 caratteri |
| 4.000 | 54 caratteri | 16.492 caratteri |
| 5.000 | 82 caratteri | 20.482 caratteri |
| predefinito | 94 caratteri | 22.230 caratteri |
| 8.000 | 198 caratteri | 32.295 caratteri |
| 16.000 | 300 caratteri (nessun taglio) | 40.201 caratteri |
Ne escono due regole. Metti le parole di attivazione nei primi novanta caratteri della descrizione, il resto è un bonus. E tieni presente che più skill installi, più riduci la descrizione di tutti gli altri. Il catalogo occupava qui 22.230 caratteri di contesto, a ogni sessione, per 146 skill di cui ne uso solo una manciata. Disinstallare vale meglio che aumentare il budget.
Claude Code applica lo stesso principio con cifre pubblicate. Il suo budget di elenco vale l’1% della finestra di contesto del modello, regolabile tramite skillListingBudgetFraction o tramite la variabile d’ambiente SLASH_COMMAND_TOOL_CHAR_BUDGET. Ogni voce è comunque plafonata: description e when_to_use concatenati sono tagliati a 1.536 caratteri, tetto regolabile tramite skillListingMaxDescChars. E quando l’elenco straborda, la documentazione è esplicita sull’ordine di sacrificio: Claude Code elimina prima le descrizioni degli skill che invochi di meno. Il nome, invece, resta sempre nell’elenco.
I due strumenti offrono la stessa via d’uscita: disattivare piuttosto che gonfiare il budget. Sul lato Claude Code, l’impostazione skillOverrides accetta quattro stati per skill, on, name-only (il nome senza la descrizione), user-invocable-only e off, e il comando /skills li scrive per te in .claude/settings.local.json. Sul lato Codex, un blocco in ~/.codex/config.toml:
[[skills.config]]
path = "/chemin/vers/le/skill/SKILL.md"
enabled = falseCaricare e distribuire lo stesso skill in Claude Code
La cartella non cambia. Due posizioni, a seconda che lo skill ti segua ovunque o appartenga al repository:
cp -R regex-verifiee ~/.claude/skills/ # per tutti i tuoi progetti
cp -R regex-verifiee mon-projet/.claude/skills/ # versionato con il repositoryLa documentazione di Claude Code aggiunge campi di frontmatter assenti dalla specifica. disable-model-invocation: true impedisce l’attivazione automatica e riserva lo skill a una chiamata manuale tramite /nom, l’impostazione giusta per tutto ciò che pusha, distribuisce o elimina. allowed-tools concede permessi di strumenti per il solo turno di conversazione che invoca lo skill, e il permesso ricade al messaggio successivo. user-invocable: false riserva lo skill al modello.
Per distribuire lo skill a un team, l’imballaggio è un plugin: un manifesto .claude-plugin/plugin.json alla radice, lo skill nella cartella skills/, e un file .claude-plugin/marketplace.json che dichiara il marketplace. L’installazione avviene poi tramite /plugin marketplace add compte/depot e poi /plugin install mon-plugin@ma-marketplace, e /reload-plugins ricarica senza uscire dalla sessione.
Resta la domanda che scotta. Il tuo skill si attiva, e serve a qualcosa? Claude Code risponde a entrambe le metà. /skill-doctor, che richiede la versione 2.1.252 o più recente, elenca gli skill caricati, il loro numero di invocazioni e il loro ultimo utilizzo, e segnala quelli che non sono mai serviti, il rapporto si apre nella scheda Stats del gestore di plugin, e si stampa in testo semplice in modalità -p. E claude plugin eval, in accesso anticipato, automatizza esattamente il confronto che ho fatto a mano più sopra. L’aiuto del comando, su questa macchina, è senza ambiguità:
$ 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)Un caso di valutazione è una cartella evals/<cas>/ che contiene un prompt.md, un prompt realistico che soprattutto non nomina lo skill, e dei correttori in graders/. L’opzione --ablation with-without rigioca ogni caso con e senza il plugin e mostra lo scarto di punteggio: è l’unico modo onesto di dimostrare che uno skill porta qualcosa.
Condividere uno skill, e verificare quelli degli altri
Convivono tre circuiti di distribuzione. Un repository Git nudo, che si clona nella cartella giusta, il più semplice e il più verificabile. Un plugin, sia per Claude Code sia per Codex: sul lato Codex, ogni plugin vive sotto plugins/<nom>/ con un manifesto .codex-plugin/plugin.json obbligatorio e cartelle facoltative skills/, .app.json, .mcp.json. E i marketplace pubblici: ClawHub, Skills.sh, SkillsMP.
Nota di passaggio che il catalogo github.com/openai/skills, ancora citato ovunque, è segnato come obsoleto e rimanda a github.com/openai/plugins. Lo skill di sistema $skill-installer, invece, installa sempre in $CODEX_HOME/skills/<nom>.
Il terzo circuito richiede diffidenza. L’audit ToxicSkills pubblicato da Snyk il 5 febbraio 2026 ha passato al setaccio 3.984 skill di ClawHub e di skills.sh: 1.467 di essi (36,82%) presentano almeno un difetto di sicurezza, e 534, il 13,4% del totale, almeno un difetto critico. Settantasei payload malevoli sono stati confermati da revisione umana: furto di credenziali, installazione di backdoor, esfiltrazione di dati, otto di questi skill erano ancora online il giorno della pubblicazione. Tutti i payload confermati contengono codice malevolo, e il 91% vi aggiunge prompt injection.
Uno skill è testo che il tuo agente seguirà, più script che eseguirà con i tuoi diritti. Prima di installarne uno, leggi per intero lo SKILL.md, leggi ogni file di scripts/, cerca le chiamate di rete e le stringhe codificate in base64, e rifiuta ogni skill che chiede una chiave API o un token. Gli stessi riflessi che per la sandbox e i permessi di un agente di codice.
Skill o MCP?
Skill e MCP non rispondono allo stesso bisogno. Uno skill porta una procedura e un know-how, in Markdown, senza processo, senza rete, senza autenticazione. Un server MCP porta strumenti e dati: parla con un database, con un’API, con un file system remoto, con le credenziali che vanno insieme.
Il test più rapido sta in una frase. Se il tuo bisogno si scrive «procedi così», è uno skill. Se si scrive «vai a cercare questo» o «scrivi questo da qualche parte», è un server MCP. La differenza di costo segue la stessa linea: uno skill inattivo costa la sua descrizione, qualche decina di token, mentre un server MCP collegato costa la definizione di tutti i suoi strumenti, in permanenza, a ogni sessione.
I due si combinano molto bene: uno skill che dice in che ordine chiamare gli strumenti di un server MCP è spesso il meglio dei due mondi. È del resto la direzione presa dal protocollo stesso, la revisione 2026-07-28 della specifica MCP elenca un gruppo di lavoro «Skills over MCP», il cui scopo è scoprire e consumare istruzioni strutturate tramite MCP. Per la parte server, la guida al server MCP in PHP prende il testimone.
I quattro errori che ricorrono
Una descrizione che descrive lo skill invece di dire quando usarlo. «Aiuta con le regex» non si attiva mai. Scrivi le parole che l’utente digita, nella sua lingua, e mettile all’inizio, a causa del troncamento misurato più sopra.
Uno SKILL.md di duemila righe. Il corpo intero entra in contesto all’attivazione. La specifica raccomanda di restare sotto le 500 righe e di rimandare il dettaglio verso references/, caricato solo se necessario. Nella prova qui sopra, Codex ha aperto cas-types.md solo al momento di scrivere i suoi casi.
Segreti nello skill. Uno skill si condivide, si versiona, si pubblica. Una chiave API che vi trascina dentro finisce in un repository pubblico. Lo skill legge una variabile d’ambiente, non la contiene.
Accumulare skill «non si sa mai». Ogni skill installato accorcia la descrizione di tutti gli altri e rosicchia la finestra di contesto. Fai l’inventario di ciò che non si è mai attivato ed eliminalo.
Cosa ricordare
- Uno skill = una cartella + uno
SKILL.md(namedi 64 caratteri al massimo,descriptiondi 1.024 al massimo) + quello che vuoi accanto. - Solo la descrizione è caricata in permanenza, ed è troncata: le parole di attivazione vanno nei primi 90 caratteri.
.agents/skillssul lato progetto, più.claude/skillsletto da Copilot e OpenCode: una stessa cartella serve più agenti.- Uno skill di progetto si testa senza installare nulla in locale:
<projet>/.codex/skills/per Codex,<projet>/.claude/skills/per Claude Code. - Il buon skill impone una procedura verificabile e un codice di uscita, non un’indicazione di stile.
- Leggi per intero ogni skill installato da un marketplace: il 13,4% di quelli auditati da Snyk porta un difetto critico.
Errori frequenti
references/, che l'agente apre solo se ne ha bisogno.scripts/ codice che eseguirà con i tuoi diritti. Leggi tutto prima, script compresi.

