Utilisez le préfixe ! pour exécuter des commandes shell dans vos slash commands et injecter automatiquement diffs, contenu de fichiers et résultats de tests
La plupart des slash commands ressemblent à ceci :
Examine la qualité du code dans les modifications actuelles et donne des suggestions concrètes.
Ça fonctionne, mais avec une limitation fondamentale : Claude doit déduire par lui-même ce que sont « les modifications actuelles ». Si votre command injecte activement le contexte, les résultats sont radicalement différents.
Cet article explique comment transformer les commands en instructions dotées de « vision » — qui lisent automatiquement le contenu des fichiers, l'état de git et les informations du projet au moment du déclenchement, injectant tout cela dans le prompt pour que Claude n'ait pas à deviner.
!`commande` injecte la sortie du ShellLes slash commands personnalisés permettent d'incorporer des commandes shell dans le prompt. La syntaxe consiste à entourer la commande de backticks et à la préfixer d'un point d'exclamation : !`commande`. Au déclenchement, la commande s'exécute d'abord, sa sortie remplace le placeholder, et Claude reçoit le prompt final déjà assemblé.
Voici le git diff actuel :
!`git diff HEAD`
Examine ces modifications, en te concentrant sur les erreurs de logique et les problèmes de sécurité.
Pour les commandes multi-lignes, utilise un bloc de code délimité commençant par
```!:```! node --version git status --short ```
Quand /review est déclenché, ce que Claude reçoit réellement ressemble à ceci :
Voici le git diff actuel :
diff --git a/app/models/user.rb b/app/models/user.rb
index 3a2f1c8..9b4e2d1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -12,6 +12,9 @@ class User < ApplicationRecord
...
Examine ces modifications, en te concentrant sur les erreurs de logique et les problèmes de sécurité.
Aucun copier-coller manuel : à l'instant où le command se déclenche, le diff est déjà à l'intérieur.
---
allowed-tools: Bash(cat:*)
---
Voici le contenu complet du fichier courant :
!`cat $ARGUMENTS`
Trouve tous les problèmes de performance potentiels dans ce fichier. Donne des numéros de ligne et des correctifs concrets.
Utilisation : /perf app/models/order.rb
$ARGUMENTS reçoit le chemin du fichier, et cat lit le contenu pour l'injecter. Claude reçoit le vrai code, pas une description floue du genre « regarde le fichier courant ».
allowed-toolsdans le frontmatter pré-autorise la commandecat, donc aucune confirmation de permission n'apparaît au déclenchement. Sans cette ligne, il faudrait cliquer manuellement sur « Autoriser » à chaque exécution. Tous les exemples ci-dessous ont besoin de la même déclaration.
Branche courante et état des modifications :
!`git status --short`
!`git log --oneline -10`
À partir de ces informations, génère une description de PR concise couvrant ce qui a changé et pourquoi.
Ce command /pr ne te demande pas de décrire « ce que j'ai changé » — il va le lire lui-même.
Stack technique du projet :
!`cat .claude/context/stack.md`
Schéma actuel de la base de données (tables clés) :
!`head -100 db/schema.rb`
Avec ce contexte, écris un script de migration pour $ARGUMENTS qui respecte les conventions du projet.
Mets les informations contextuelles du projet dans .claude/context/ à l'avance, et le command les lira à la demande au déclenchement, sans avoir à redécrire le projet à chaque fois.
Dernière exécution de tests :
!`bundle exec rspec --format progress 2>&1 | tail -30`
Ce sont les tests en échec. Analyse la cause racine et propose des correctifs. Ne touche pas aux tests eux-mêmes.
Quand /fix-tests se déclenche, il lance les tests et récupère les résultats — Claude voit les vrais messages d'erreur.
En combinant tout ce qui précède, /review peut devenir remarquablement précis :
---
description: Examine les modifications actuelles, injecte automatiquement le diff et le contexte
allowed-tools: Bash(git diff:*), Bash(cat:*)
---
## Modifications actuelles
!`git diff HEAD`
## Liste des fichiers modifiés
!`git diff HEAD --name-only`
## Standards de code du projet
!`cat .claude/context/coding-standards.md 2>/dev/null || echo "(aucun fichier de standards)"`
---
Examine les modifications ci-dessus :
1. Exactitude logique : cas limites non gérés, erreurs de logique
2. Sécurité : injection SQL, vérifications d'autorisation, exposition de données sensibles
3. Conformité aux standards : respecte-t-on les standards de code du projet ?
4. Lisibilité : nommage, commentaires, structure
Pour chaque problème, indique le fichier, le numéro de ligne et une suggestion concrète. S'il n'y a aucun problème, dis-le ; n'invente rien pour faire du remplissage.
Ce command ne demande aucune préparation de ta part — au déclenchement, le diff, la liste des fichiers et les standards de code sont tous injectés automatiquement.
Les commandes shell peuvent échouer (fichier inexistant, commande absente du PATH, etc.). Utilise || pour fournir une valeur par défaut et éviter d'interrompre le command :
!`git diff HEAD 2>/dev/null || echo "(aucune modification git ou pas dans un dépôt git)"`
!`cat .env.example 2>/dev/null || echo "(.env.example introuvable)"`
!`which rspec > /dev/null 2>&1 && bundle exec rspec --dry-run 2>&1 | head -20 || echo "(RSpec non détecté)"`
Quand une commande échoue, Claude reçoit un message explicite plutôt qu'un blanc, et peut adapter sa réponse en conséquence.
Toute la sortie des commandes ! entre dans la fenêtre de contexte. Quelques pièges classiques :
Ne fais pas cat sur un gros fichier entier
# Dangereux : peut injecter des dizaines de milliers de lignes
!`cat db/schema.rb`
# Mieux : n'extraire que ce dont on a besoin
!`grep -A 5 "create_table \"orders\"" db/schema.rb`
Limite les fichiers de log par nombre de lignes
!`tail -50 log/development.log`
Tronque la sortie des tests
!`bundle exec rspec 2>&1 | tail -40`
Plus le contexte est précis, meilleures sont les réponses de Claude. Lui balancer tout le code source ne le rendra pas plus intelligent — ça le perdra dans le bruit.
Question fréquente : les informations de contexte projet doivent-elles aller dans CLAUDE.md ou être injectées dynamiquement avec ! ?
Critère de décision :
| Type d'information | Où le mettre |
|---|---|
| Contexte projet toujours nécessaire (stack, structure des dossiers, conventions) | CLAUDE.md |
| État qui évolue dans le temps (diff courant, résultats de tests, contenu de fichiers) | Injection dynamique avec ! |
| Contexte spécifique à une tâche (doc de conception d'un module particulier) | !cat à la demande |
CLAUDE.md, c'est la connaissance de fond persistante ; !, c'est un instantané pris au moment de la tâche. Les deux se complètent, ne fais pas de doublons.
.claude/commands/ complet.claude/
├── commands/
│ ├── review.md # Revue : injecte diff + standards
│ ├── test.md # Écriture de tests : injecte le fichier cible
│ ├── fix-tests.md # Correction de tests : injecte les échecs
│ ├── pr.md # Description de PR : injecte git log + status
│ ├── explain.md # Explication de code : injecte le contenu du fichier
│ └── migrate.md # Écriture de migration : injecte des extraits de schéma
├── context/
│ ├── stack.md # Description de la stack technique
│ └── coding-standards.md # Standards de codage
└── settings.json
Le dossier context/ contient les fichiers de contexte statiques que les différents commands lisent à la demande. Cette structure se commit telle quelle dans git et se partage en équipe.
Command statique :
Examine les modifications de code actuelles.
Claude doit d'abord demander « où sont les modifications ? », ou les chercher lui-même — résultats inconsistants.
Command conscient du contexte :
Voici le diff (contenu réel inclus), voici les standards pertinents (contenu réel inclus), examine.
Claude passe directement à l'analyse. Réponses précises, pas de blabla, pas d'allers-retours.
La différence ne tient pas aux capacités de Claude, mais à la quantité d'informations réelles que tu lui donnes.