I custom commands sono confluiti in Skills. Quando migrare a `.claude/skills/` e cosa ci guadagni.
I tre articoli precedenti hanno coperto l'uso completo degli slash command: dal file Markdown all'iniezione tramite !comando, fino all'orchestrazione via subagent e MCP. Nulla di tutto ciò è obsoleto — ma dietro le quinte è avvenuta una fusione ufficiale: i custom command sono confluiti in Skills.
Il tuo .claude/commands/review.md continua a funzionare, /review è ancora disponibile, non devi cambiare nulla. Ma se vuoi che il comando cresca di capacità (più file, esecuzione in fork, attivazione automatica per path), la nuova strada è .claude/skills/review/SKILL.md. Questo articolo chiarisce due cose: come migrare e se ne vale la pena.
La promessa di compatibilità ufficiale è chiara: .claude/commands/deploy.md e .claude/skills/deploy/SKILL.md vengono entrambi registrati come /deploy e si comportano nello stesso modo. In caso di collisione di nomi, vincono gli skill.
Passi minimi:
cd .claude/commands
mkdir -p ../skills/review
mv review.md ../skills/review/SKILL.md
Nel contenuto del file non cambia una sola riga. Frontmatter YAML, !`comando`, @file, $ARGUMENTS — tutto resta compatibile.
Fermandosi qui, però, viene spontaneo chiedersi: allora perché migrare? La risposta sta nel fatto che una cartella skill può ospitare più file, mentre un command può averne solo uno.
SKILL.md è il punto d'ingresso; nella stessa cartella puoi mettere qualsiasi file accessorio. Immagina questa struttura:
.claude/skills/review/
├── SKILL.md # entry point, istruzioni brevi + riferimenti
├── checklist.md # checklist lunga di code review
├── examples/
│ └── good-diff.md # esempio positivo
└── scripts/
└── lint.sh # script invocabile da SKILL.md
Dentro SKILL.md si referenziano via path relativo:
Rivedi il diff corrente seguendo i criteri di [checklist.md](checklist.md).
Consulta [examples/good-diff.md](examples/good-diff.md) per il formato di output atteso.
Questi file accessori non entrano automaticamente nel context — Claude li legge quando servono. La raccomandazione ufficiale: tenere SKILL.md sotto le 500 righe e spostare il resto nei file di supporto.
disable-model-invocation: quali skill solo tu puoi attivare a manoPer default Claude può invocare autonomamente uno skill quando ritiene che sia il momento giusto. Per i comandi con effetti collaterali come /deploy, /commit, /send-email, è pericoloso — non vuoi che «deployi perché trova il codice bello».
---
name: deploy
description: Deploy verso la produzione
disable-model-invocation: true
allowed-tools: Bash(kamal deploy:*), Bash(git push:*)
---
Con questa riga, /deploy si attiva solo digitandolo manualmente: Claude non lo lancerà più di sua iniziativa nel corso della conversazione.
Al contrario, user-invocable: false significa «lo può chiamare solo Claude, ma non appare nel menu /» — adatto a skill di conoscenza di sfondo (per esempio legacy-system-context, che Claude carica automaticamente nei contesti rilevanti e che non avrebbe senso innescare a mano).
context: fork: fai girare lo skill in un subagentÈ l'evoluzione più grossa. Nel precedente articolo vedevamo che un command poteva usare allowed-tools: Task per chiedere al modello di avviare un subagent — ma dovevi scrivere a mano nel prompt «avvia un subagent Explore che…».
Con uno SKILL basta una riga di frontmatter:
---
name: deep-research
description: Investigare a fondo un simbolo
context: fork
agent: Explore
---
Indaga tutti gli usi di $ARGUMENTS:
- tutti i punti di chiamata
- scenari di business
- implementazioni alternative
Restituisci un riassunto di ≤300 parole.
Quando attivi /deep-research SomeClass: l'intero SKILL.md diventa il prompt di un subagent indipendente, eseguito con agent type Explore, che a fine esecuzione restituisce solo la conclusione. Il context della conversazione principale resta perfettamente pulito.
È come trasformare «avviare un subagent» da testo descrittivo nel prompt ad attributo dichiarativo dello skill.
paths: attivazione automatica per tipo di file---
name: rails-conventions
description: Convenzioni di codice per questo progetto Rails
paths: ["app/**/*.rb", "config/**/*.rb"]
---
Segui le convenzioni Rails di questo progetto:
- usa service object invece di fat controller
- gli scope ActiveRecord devono essere nominati
...
Mentre stai editando app/models/user.rb, questo skill viene aggiunto automaticamente al context; quando editi package.json no. Più preciso del background globale di CLAUDE.md — una specie di «CLAUDE.md stratificato per path».
/plan a skillL'ultimo /plan dell'articolo precedente era un command a singolo file:
.claude/commands/plan.md
Versione skill:
.claude/skills/plan/
├── SKILL.md
├── research-prompt.md # istruzioni per il subagent 1
└── risk-prompt.md # istruzioni per il subagent 2
SKILL.md:
---
name: plan
description: Produrre un piano implementativo a partire da un ticket Linear
disable-model-invocation: true
allowed-tools: mcp__linear__*, Task, Read, Grep, Bash(git log:*)
---
## Context
@.claude/context/architecture.md
## Stato
!`git log --oneline -10`
## Compito
Recupera descrizione e commenti del ticket Linear $ARGUMENTS.
Usa Task per lanciare in parallelo due subagent:
1. Ricerca nel codice: prompt in [research-prompt.md](research-prompt.md)
2. Valutazione dei rischi: prompt in [risk-prompt.md](risk-prompt.md)
Unifica i due risultati producendo: passi implementativi + elenco rischi + raccomandazioni sulla granularità dei commit.
I prompt dei due subagent vivono in file separati: li si modifica senza toccare SKILL.md. Lo skill resta sotto le 30 righe, pulito, mentre i file accessori possono superare tranquillamente le centinaia di righe l'uno.
Se non vuoi nemmeno orchestrare tu i subagent, puoi spingerti oltre: buttare l'intero skill in fork e lasciare che l'agente Explore lo esegua di filato:
---
name: plan
context: fork
agent: Explore
allowed-tools: mcp__linear__*
---
/plan ENG-4213 → l'agente Explore, in un context isolato, prende tutto il contenuto di SKILL.md come compito → restituisce solo il piano finale. La conversazione principale resta completamente pulita.
Non tutti i command meritano l'upgrade. Conviene restare in .claude/commands/ quando:
I semplici /commit, /pr-desc e simili — un frontmatter più qualche riga di prompt — risultano persino più chiari in .claude/commands/. Ufficialmente: entrambe le forme coesistono e nessuna sarà deprecata.
Oggi l'organizzazione più pulita di .claude/ è più o meno così:
.claude/
├── commands/ # leggero: file singolo + prompt semplice
│ ├── commit.md
│ └── pr-desc.md
├── skills/ # pesante: multi-file / fork / controllo accessi
│ ├── plan/
│ │ ├── SKILL.md
│ │ ├── research-prompt.md
│ │ └── risk-prompt.md
│ ├── deploy/
│ │ └── SKILL.md # disable-model-invocation
│ └── rails-conventions/
│ └── SKILL.md # attivazione auto via paths glob
└── context/
└── coding-standards.md
Non migrare tutto in blocco. Il segnale per migrare è «questo command sta iniziando a gonfiarsi» — oltre 200 righe, bisogno di spezzare la doc, voglia di farlo girare in un subagent. Quando ci sei, cambi il path. Questione di minuti.
| Capacità desiderata | commands/ |
skills/ |
|---|---|---|
| Shortcut a prompt in singolo file | ✅ | ✅ |
!`comando` / @file / $ARGUMENTS |
✅ | ✅ |
Controllo accessi tramite allowed-tools |
✅ | ✅ |
| File di supporto (riferimenti, script) | ❌ | ✅ |
disable-model-invocation anti-falso-trigger |
❌ | ✅ |
Esecuzione isolata con context: fork + agent: |
❌ | ✅ |
Attivazione automatica via paths: glob |
❌ | ✅ |
Sulle prime tre righe commands e skills sono perfettamente equivalenti; le ultime quattro sono prerogativa degli skill. Si usa ciò che serve e basta.
La direzione ufficiale pende verso gli skill, ma la promessa di compatibilità di commands/ è chiara — non è un cambio del tipo «migra subito o sparisci», ma un'estensione «ti offro più potenza senza obbligarti». Capisci le differenze, migra quando serve, non inseguire un'uniformità estetica.