
Un SKILL.md simple suffit pour une procédure de quelques étapes. Mais dès qu'une skill doit calculer, parser ou agréger quelque chose, écrire la logique en prose dans le SKILL.md est une mauvaise idée : c'est verbeux, peu fiable, et ça gonfle le contexte. La bonne approche consiste à déporter le travail dans un script et à charger les ressources à la demande. Ce guide montre comment, avec un lab vérifié sur lab-claude.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déporter la logique d'une skill dans un script que l'agent exécute
- Structurer une skill avec
scripts/,references/etassets/ - Charger des ressources à la demande sans alourdir le contexte
- Écrire une
descriptionqui déclenche et restreindreallowed-toolssans risque
Prérequis
Section intitulée « Prérequis »- Les bases des skills maîtrisées (frontmatter, invocation)
- Le concept de progressive disclosure compris
lab-claudeopérationnel, Python disponible (exemples vérifiés en Claude Code v2.1.152)
Pourquoi sortir la logique dans un script
Section intitulée « Pourquoi sortir la logique dans un script »Quand une skill embarque un script, l'agent exécute ce script et n'en récupère que la sortie. Le code lui-même n'entre jamais dans le contexte. C'est le troisième niveau de la progressive disclosure : les fichiers de scripts/ sont lancés sans que leur contenu coûte un seul token.
Deux bénéfices concrets. D'abord la fiabilité : un script Python qui parse du JSON ou compte des occurrences donne un résultat déterministe, là où des instructions en langage naturel laissent l'agent improviser. Ensuite l'économie de contexte : un script de 200 lignes ne pèse rien tant qu'il n'est pas exécuté, et même exécuté, seule sa sortie compte.
La règle qui en découle : tout ce qui est calculable doit être un script, le SKILL.md se contentant d'orchestrer (lancer le script, interpréter sa sortie, appliquer un format).
Anatomie d'une skill avancée
Section intitulée « Anatomie d'une skill avancée »Une skill avancée est un dossier structuré. Sur lab-claude, voici une skill inventaire-todo qui recense la dette technique du projet :
Répertoire.claude/
Répertoireskills/
Répertoireinventaire-todo/
- SKILL.md
Répertoirescripts/
- scan.py
Répertoirereferences/
- criteres.md
Chaque dossier a un rôle précis :
scripts/: le code exécutable. Lancé par l'agent, jamais chargé en contexte.references/: la documentation lue seulement si une étape la réclame (un format, des règles).assets/(non utilisé ici) : des gabarits ou fichiers produits en sortie (modèles de document, par exemple).
Le SKILL.md reste mince et se contente d'enchaîner : lancer le script, puis mettre en forme selon references/.
Lab : une skill qui exécute un vrai script
Section intitulée « Lab : une skill qui exécute un vrai script »Le script scan.py parcourt les fichiers Python et inventorie les marqueurs TODO, FIXME et XXX. Il renvoie du JSON sur la sortie standard :
# .claude/skills/inventaire-todo/scripts/scan.py (extrait)PATTERN = re.compile(r"\b(TODO|FIXME|XXX)\b[:\s]*(.*)")
def scan(root: Path) -> dict: findings = [] for path in root.rglob("*.py"): if any(part in SKIP_DIRS for part in path.parts): continue for n, line in enumerate(path.read_text().splitlines(), 1): if m := PATTERN.search(line): findings.append({"file": str(path.relative_to(root)), "line": n, "marker": m.group(1), "text": m.group(2).strip()[:120]}) return {"total": len(findings), "findings": findings}Le SKILL.md orchestre, sans refaire le travail du script :
---name: inventaire-tododescription: Inventorie et priorise les marqueurs TODO, FIXME et XXX du projet Python. À utiliser quand l'utilisateur veut faire le point sur la dette technique ou les tâches en suspens dans le code.allowed-tools: Bash(python3 .claude/skills/inventaire-todo/scripts/scan.py:*)---
1. Lance `python3 .claude/skills/inventaire-todo/scripts/scan.py .`2. Mets en forme le JSON en suivant `references/criteres.md`3. Termine par une recommandation : quel marqueur traiter en premierLancé seul, le script produit un résultat déterministe :
{ "total": 3, "by_marker": { "TODO": 1, "FIXME": 1, "XXX": 1 }, "findings": [ { "file": "app/__init__.py", "line": 4, "marker": "FIXME", "text": "gerer le cas panier vide avant total" } ]}Maintenant le test qui compte : déclencher la skill sans la nommer, par une simple demande en langage naturel.
> fais le point sur la dette technique du code, les todo et fixme# Inventaire dette technique
## FIXME (priorité 1 - bug connu)- app/__init__.py:4 - gerer le cas panier vide avant total
## XXX (priorité 2 - code fragile)- app/__init__.py:5 - arrondi monetaire a revoir (flottants)
## TODO (priorité 3 - amélioration)- app/__init__.py:3 - paginer la liste des produits
## RecommandationAttaquer le FIXME en premier : c'est un bug fonctionnel.Trois mécanismes se sont enchaînés : la skill a été activée par sa description, elle a exécuté le script (dont le code n'est jamais entré dans le contexte), puis elle a lu references/criteres.md pour prioriser FIXME avant XXX avant TODO. Le travail de comptage est fait par Python ; l'agent ne fait que l'interpréter.
Charger des ressources à la demande
Section intitulée « Charger des ressources à la demande »Le fichier references/criteres.md n'est lu que lorsque la skill s'exécute. Il porte les règles de priorisation :
## Ordre de priorité1. FIXME : un bug connu. À traiter en premier.2. XXX : code fragile ou hack assumé.3. TODO : amélioration sans urgence.C'est le bon endroit pour tout ce qui est détaillé mais pas toujours nécessaire : un format de sortie long, une table de correspondance, une convention d'équipe. En le sortant du SKILL.md, vous gardez ce dernier court et vous ne payez le coût de la référence que quand elle sert.
Écrire une description qui déclenche
Section intitulée « Écrire une description qui déclenche »Le déclenchement repose entièrement sur la description, sans aucun routage par mots-clés. Une description efficace décrit la tâche et le moment où l'utiliser, avec des termes concrets.
| Description | Problème |
|---|---|
Aide pour le code | Trop vague, ne se déclenche jamais |
Analyse les endpoints Flask pour injections SQL PostgreSQL | Trop étroite, rate les cas généraux |
Inventorie les marqueurs TODO, FIXME, XXX. À utiliser pour faire le point sur la dette technique | Tâche + moment d'usage concrets |
Testez toujours avec des phrases réelles (« fais le point sur la dette technique »), pas avec « déclenche ma skill ». Si elle ne part pas, resserrez la description vers le vocabulaire que vous emploieriez vraiment.
Sécurité : restreindre allowed-tools à la commande exacte
Section intitulée « Sécurité : restreindre allowed-tools à la commande exacte »Le champ allowed-tools pré-autorise des commandes pendant l'exécution de la skill. La tentation est d'écrire Bash(*) pour ne plus être interrompu. Ne le faites pas : une skill avec Bash(*) peut lancer n'importe quoi sans confirmation, ce qui est exactement le vecteur d'abus des skills tierces.
Restreignez au chemin exact du script :
allowed-tools: Bash(python3 .claude/skills/inventaire-todo/scripts/scan.py:*)Cette ligne autorise le script de la skill, et rien d'autre. C'est le même principe de moindre privilège qu'ailleurs en sécurité, appliqué aux skills. Un deny du settings.json reste prioritaire sur allowed-tools : ne pré-autorisez jamais dans une skill ce qui est refusé au niveau du projet.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Correction |
|---|---|---|
| Le script n'est pas trouvé | Chemin relatif erroné | Référencer depuis la racine du projet, vérifier le chemin réel |
| La skill redemande une autorisation | allowed-tools ne couvre pas la commande exacte | Aligner le motif sur la commande lancée |
references/ jamais utilisé | Le SKILL.md n'y renvoie pas | Ajouter une étape explicite « suis references/... » |
| Sortie du script ignorée | Skill traitée comme un guide, pas une tâche | Formuler en impératif (« Lance », « Mets en forme ») |
| Le script se compte lui-même | Dossier .claude/ non exclu du scan | Exclure les dossiers d'outillage dans le script |
À retenir
Section intitulée « À retenir »- Tout ce qui est calculable doit être un script : déterministe, et son code n'entre jamais dans le contexte.
- Une skill avancée se structure en
scripts/(exécutable),references/(à la demande),assets/(gabarits). - Le
SKILL.mdorchestre, il ne refait pas le travail du script. - Gardez le
SKILL.mdmince et déportez le détail dansreferences/. - La
descriptionest la seule règle de déclenchement : concrète, testée avec de vraies phrases. - Restreignez
allowed-toolsà la commande exacte, jamaisBash(*).