Salta al contenuto principale

Skill design pattern: progressive disclosure, lazy-load, frontmatter

Cluster 1 della serie Claude Code Workflow. Come progettare skill che vengono davvero invocate: regola dei tre quando, frontmatter chirurgico, body progressive-disclosure, references lazy. Esempi illustrativi tratti dal portfolio.

Cosa ne pensi di questo articolo?

Skill design pattern: progressive disclosure, lazy-load, frontmatter
Claude Code WorkflowFoto:PixabayPexels

In Breve

Cluster 1 della serie Claude Code Workflow. Come progettare skill che vengono davvero invocate: regola dei tre quando, frontmatter chirurgico, body progressive-disclosure, references lazy. Esempi illustrativi tratti dal portfolio.

Risposta diretta

La chiave per una buona progettazione di skill è scrivere istruzioni specifiche e concesse, evitando la vaghezza, e utilizzare il frontmatter solo per informazioni essenziali come nome e descrizione. Il body della SKILL.md deve essere progressivamente disclosivo, caricando solo le informazioni necessarie al momento dell'invocazione, e non dovrebbe superare le 250 righe.

Una skill ben progettata è invisibile: viene invocata al momento giusto, fa quello che deve, restituisce il controllo. Una skill mal progettata è un fastidio: viene ignorata quando serve, attivata quando non serve, o peggio, attiva un comportamento che confonde il modello. In questo articolo racconto cosa ha funzionato sul mio portfolio brownfield, quali skill ho riscritto da zero perché ignorate, e tre regole pratiche che ti fanno passare dal skill che hai scritto al skill che il modello usa davvero.

Disclaimer di indipendenza: non sono affiliato a obra né ad Anthropic. Tutto quanto segue è esperienza personale su sessanta-più skill (alcune Superpowers ufficiali, altre custom) installate nel mio .claude/skills/ da circa un anno.

La regola dei tre quando

Prima di scrivere una sola riga di SKILL.md, rispondi a tre domande. Sono la regola che ho rubato a una conversazione con la skill "using-superpowers" di obra e che ho riapplicato a tutte le mie skill custom. Le tre domande sono:

  1. Quando il problema che la skill risolve si presenta? (situazione che la attiva)
  2. Cosa deve fare la skill, in concreto? (il comportamento che impone)
  3. Come la skill sa di aver finito? (criterio di chiusura)

Il primo quando finisce nel description del frontmatter. Il cosa e il come nel body della SKILL.md. Tutte e tre devono essere specifiche al dominio. Vaghezza in una di queste tre = skill che non funziona.

Esempio negativo (skill che il modello ignora)

---
name: code-helper
description: Use when coding to write better code
---

You are a helpful coding assistant. Write clean code.

Cosa c'è di sbagliato? Tutto, ma in particolare:

  • Quando vaghissimo: "use when coding" matcha praticamente sempre, quindi il modello non ha un trigger preciso per attivarla.
  • Cosa generico: "write better code" non descrive un comportamento, descrive un'intenzione.
  • Nessun come: non c'è criterio di chiusura. Quando la skill ha "finito"? Mai? Sempre?

Risultato sul mio portfolio: skill simili a questa che avevo scritto nei primi mesi venivano invocate random, peggiorando l'output invece di migliorarlo. Dopo tre settimane le ho disabilitate.

Esempio positivo (skill che il modello invoca)

---
name: debugging
description: Use when investigating a bug that did not resolve on first attempt.
  Drives a scientific-method loop (hypothesis -> test -> measure) with
  checkpoints between cycles, and stops when the failing test turns green.
metadata:
  type: rigid
---

Cosa c'è di giusto?

  • Quando specifico: "use when investigating a bug that did not resolve on first attempt". Non si attiva al primo tentativo; si attiva quando il fix banale non ha funzionato.
  • Cosa concreto: scientific-method loop con checkpoint. Non "be a good debugger" ma un comportamento procedurale preciso.
  • Come definito: "stops when the failing test turns green". Il criterio di chiusura è una condizione osservabile.

Questa è la skill debugging di Superpowers (riassunta). Funziona. Se la cerchi in upstream e ne studi il body, vedi che le 200-300 righe del file espandono cosa e come in passi specifici, mentre quando resta condensato nel description.

Frontmatter chirurgico: name + description, niente di più

Il frontmatter delle SKILL.md migliori che ho letto è impressionante per quanto poco contiene. Spesso solo due campi:

---
name: code-reviewer
description: Use after writing or modifying code to review for quality,
  security, and maintainability. Focuses on what was just changed (not the
  entire codebase). Stops with a structured report flagging CRITICAL,
  HIGH, MEDIUM issues.
---

Campi opzionali che vedi a volte:

  • metadata.type = rigid | flexible - segnala se la skill deve essere seguita alla lettera o se è adattabile al contesto. Default flexible.
  • metadata.bypass = auto | prompt - controlla se la skill viene invocata automaticamente o se chiede conferma all'utente. Default auto.

Aggiungere campi non riconosciuti dal runtime di Claude Code non rompe la skill, ma diventano rumore informativo. Resisti alla tentazione di mettere metadata superflua nel frontmatter ("version", "author", "tags", "tested_on") - quelle informazioni vivono meglio nel README del pacchetto skill, non nella SKILL.md che viene parsata a ogni sessione.

Il description è scritto per il modello, non per te

Il description è la cosa più importante della skill. Il modello lo legge ogni volta che valuta se invocare la skill. Tre regole pratiche:

  1. Verbo + sostantivo specifico. "Use when investigating a bug" (verbo + sostantivo) batte "Use when something is wrong" (verbo + sostantivo astratto). Verbi tipici: investigate, refactor, review, validate, summarize, brainstorm. Sostantivi specifici: bug, dead code, pull request, configuration drift, query, prompt.
  2. Condizione che restringe. "Use after writing or modifying code" (restringe ai momenti post-write) batte "Use when coding" (sempre). La condizione restrittiva evita il rumore.
  3. Output osservabile. "Stops with a structured report flagging CRITICAL, HIGH, MEDIUM issues" dice al modello cosa la skill produce. Aiuta il modello a decidere se la skill è quello di cui ha bisogno.

Body progressive-disclosure

Il body della SKILL.md viene caricato solo quando la skill viene invocata. Questo è cruciale: significa che puoi scrivere istruzioni lunghe (300-500 righe) senza preoccuparti del consumo token nel "caso base" (skill non invocata). Tuttavia, una volta invocata, le istruzioni vanno in context, e quanto vanno in context conta.

Pattern progressive-disclosure tipico:

SKILL.md (~150-250 righe)
├── Overview + when to invoke (riassunto del description)
├── Core procedure (steps high-level)
├── Anti-patterns (cosa non fare)
└── References to subdir lazy-load:
    references/
    ├── advanced-workflows.md  (load only if step X requires)
    ├── edge-cases.md           (load only if user reports edge case)
    └── examples-checklist.md   (load only on user request)

Il body principale contiene il flusso happy-path. Quando il task corrente ne ha bisogno (es. l'utente chiede un workflow avanzato non coperto dal flusso base), il body istruisce il modello a leggere il file specifico sotto references/. Risparmio: il primo step di un'invocazione tipica resta sotto i 250 righe; solo i casi non-banali tirano dentro le references.

Anti-pattern: body monolitico da 800 righe

Una skill custom che avevo scritto nei primi mesi del portfolio aveva 800 righe nel body principale. Conteneva:

  • Overview (50 righe)
  • Happy path (200 righe)
  • Sei workflow alternativi (300 righe totali)
  • Quindici esempi (200 righe)
  • Checklist finale (50 righe)

Problema: ogni volta che la skill veniva invocata, tutto questo entrava in context. Per una skill invocata ogni terzo o quarto messaggio, l'overhead cumulato erodeva la context window.

Soluzione applicata: splittato in body principale (200 righe happy path) + sei references/workflow-N.md (lazy-load) + un singolo references/examples.md caricato solo a richiesta esplicita. Token consumption per invocazione tipica: -65%.

References subdir: quando, dove, come

La cartella references/ accanto a SKILL.md è il meccanismo ufficiale per estendere una skill senza inflazionare il body principale. Tre principi:

  1. Una file per concetto. Non un file "miscellaneous.md" con dieci sezioni. Meglio sei file singoli, ognuno con un nome che descrive il contenuto: code-review-checklist.md, security-anti-patterns.md, performance-edge-cases.md.
  2. Linka esplicitamente nel body. Non sperare che il modello "trovi" le references da solo. Scrivi nel body principale: "Se il task richiede X, leggi references/x.md prima di procedere". Senza link esplicito, le references restano dormienti.
  3. References sono read-only per il modello. Sono documentazione, non script. Niente "esegui questo comando" che modifica stato. Lo stato lo cambia il body principale o l'utente.

Naming: convention che evitano collisione

Il nome della cartella skill diventa il nome del file SKILL.md path (.claude/skills/<name>/SKILL.md). Convention pratica:

  • kebab-case: code-reviewer, tdd-guide, debug-flow.
  • verbo o sostantivo descrittivo: debugging (sostantivo), refactor-cleaner (verbo + sostantivo).
  • evita prefissi di plugin: non chiamare la tua skill custom superpowers-debugging; chiamarla my-debugging o debug-domain-x.
  • evita versioning nel nome: tdd-guide-v2 non scala. Versiona via git history, non via filename.

Plugin skill vs. custom skill: convivenza

Quando installi Superpowers (o un altro plugin Claude Code che fornisce skill), le skill upstream vivono in una cartella plugin separata. Le tue skill custom restano in .claude/skills/. Il runtime indicizza tutte le SKILL.md, indipendentemente dall'origine.

Collisione potenziale: due skill con name uguale. Il runtime si lamenta con un warning (e tipicamente carica una sola delle due, con behavior non garantito). Risoluzione: rinomina la tua skill custom per non collidere.

Caso più sottile: due skill con description simile. Nessun warning del runtime, ma il modello sceglie tra di loro in modo non deterministico. Risoluzione: differenzia il description in modo che ognuna copra una situazione disgiunta. Esempio di disambiguazione: una skill code-reviewer di Superpowers (review post-write generico) + una skill code-reviewer-fintech custom (review post-write con focus regolamentazione PSD2). Description differenziato sul "quando si attiva" + "cosa cerca specificamente".

Misurare se la skill è davvero invocata

C'è un modo brutale ma efficace per scoprire se le tue skill vengono effettivamente usate: elimina temporaneamente quelle che sospetti siano inutili e osserva. Se nessuna sessione successiva mostra degrado nell'output, la skill era rumore e puoi tenerla disabilitata.

Sul mio portfolio ho fatto questo esercizio tre volte (ogni quattro-cinque mesi). Risultato cumulato: ho disabilitato 9 skill custom su 23 perché non contribuivano. Le 14 rimaste sono quelle che lavorano davvero.

Checklist pre-commit per una nuova skill

  1. Rispondi alle tre domande (quando / cosa / come).
  2. Description = verbo + sostantivo specifico + condizione restrittiva + output osservabile (max 2-3 righe).
  3. Body progressive-disclosure: happy-path 150-250 righe, references separate per workflow avanzati.
  4. Anti-pattern section esplicita: cosa la skill NON deve fare.
  5. Test mentale: una sessione tipica del tuo dominio attiverebbe questa skill al momento giusto?
  6. Test reale: nelle prime due settimane, monitora se viene invocata. Se non lo è, riformula il description.

Quando una skill non è la soluzione giusta

Skill design è uno strumento, non un fine. A volte la risposta corretta è non scrivere una skill. Tre situazioni:

  1. Comportamento desiderato è già nel modello. Se Claude risponde correttamente al task tipico senza skill, aggiungere una skill è overhead. Le skill servono per forzare un comportamento controintuitivo (es. TDD su business logic, code review post-write).
  2. Comportamento desiderato è una preferenza utente specifica. Se la regola si applica solo al tuo workflow personale (es. "commit message in italiano"), va in CLAUDE.md di progetto, non in una skill globale.
  3. Comportamento desiderato è un tool reale. Se hai bisogno di un'azione su un sistema esterno (interrogare DB, chiamare API), un MCP server è meglio di una skill. Le skill istruiscono il modello, gli MCP gli danno tool.

Una skill custom del portfolio: i18n-bulk-translator

Esempio reale di skill custom che ho scritto per il mio portfolio (qui illustrativa, non production-ready copy-paste):

---
name: i18n-bulk-translator
description: Use when translating a new batch of i18n keys across 17
  target languages via the on-prem Ollama qwen2.5:14b pipeline. Drives
  the xlf.py + auto-translate-new-keys.py workflow with checkpoint
  between languages, and stops when all targets reach >= 95% coverage
  per the audit script.
metadata:
  type: rigid
---

# i18n-bulk-translator

## When to invoke
[descrizione del trigger specifico]

## Procedure
1. Run `scripts/i18n/xlf.py extract` to gather new IT source keys.
2. For each target language (17 total), spawn translation batch...
[5-6 steps high-level]

## Anti-patterns
- Do NOT batch all 17 languages in one call (timeout).
- Do NOT skip audit step between batches.

## References
- references/language-priority.md (order in cui tradurre).
- references/audit-thresholds.md (soglie per quality gate).
- references/edge-cases.md (placeholder gestione, route slug).

Risultati pratici: prima di questa skill, ogni batch di traduzione era cinque-sette messaggi di prompt re-engineering. Dopo, è un singolo messaggio "traduci il nuovo batch" e la skill prende il controllo.

Cosa ho imparato scrivendo questo articolo

La regola dei tre quando sembra ovvia letta scritta, ma sui primi sei mesi di skill custom non l'avevo mai messa nero su bianco. Avevo "intuizioni" su quando una skill avrebbe funzionato e quando no, ma non sapevo articolarle. Scrivere questo cluster mi ha costretto a tradurre l'intuizione in tre domande operative.

La seconda lezione è sul rumore. La fase iniziale di adozione di Superpowers (e di skill custom in generale) tende all'over-installation: installo trenta skill perché "potrebbero servire". Tre mesi dopo, la maggior parte non era stata mai invocata utilmente, e quelle che lo erano state si pestavano i piedi a vicenda (description overlap). Less is more applica con forza al skill design.

Anti-pattern evitati

  • Skill come reference manual. Le skill non sono documentazione: sono istruzioni operative. Se ti viene voglia di scrivere "background context" o "history of this skill" nel body, sposta tutto in references/ e linkalo solo quando il modello ne ha bisogno.
  • Skill che mescola due responsabilità. Una skill "debug-and-test" che fa sia bug investigation che TDD enforcement è un'astrazione sbagliata. Due skill separate (debugging + tdd-guide) con description disgiunte funzionano meglio perché il modello può attivare l'una o l'altra in base al contesto.

Una storia ricevuta che vale la pena condividere

Sezione segnaposto. Se hai sperimentato uno schema skill che ha funzionato (o un anti-pattern che hai pagato a caro prezzo) e vuoi che diventi parte dell'articolo successivo della serie, scrivimi a federico@federicocalo.dev. Con il tuo consenso esplicito (e pseudonimizzazione) la storia entra nel cluster successivo come reader story.


← Sub-page Superpowers Prossimo cluster: Brainstorming skill →

Domande frequenti

Quali sono le caratteristiche di una skill ben progettata?

Una skill ben progettata è invisibile, viene invocata al momento giusto, fa quello che deve e restituisce il controllo.

Come si può determinare se una skill è davvero invocata?

C'è un modo brutale ma efficace per scoprire se le tue skill vengono effettivamente usate: elimina temporaneamente quelle che sospetti siano inutili e osserva.

Quali sono le tre regole pratiche per scrivere un description efficace nella SKILL.md?

Il description è scritto per il modello, non per te. Tre regole pratiche sono: il body della SKILL.md deve essere progressivo-disclosure, il description deve essere specifico al dominio e vaghezza in una di queste tre = skill che non funziona.

Quali sono le situazioni in cui la risposta corretta è non scrivere una skill?

La risposta corretta è non scrivere una skill quando si tratta di un problema che può essere risolto con un approccio diverso, come ad esempio utilizzare un'altra skill o modificare il flusso del modello.

Fonti e approfondimenti

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti