Claude Code s'est discrètement imposé comme l'agent de codage IA standard dans de nombreuses équipes d'ingénierie, et en 2026, les équipes les plus efficaces ne le configurent plus développeur par développeur. Elles empaquettent leurs commandes slash, sous-agents, skills, hooks et serveurs MCP dans des plugins, les publient sur une marketplace de plugins hébergée dans un simple dépôt Git, et les déploient pour tout le monde avec une seule entrée de configuration.
Dans ce tutoriel, vous allez construire de zéro un plugin de qualité production nommé team-toolkit, le tester localement, le publier sur GitHub sous forme de marketplace, puis l'activer automatiquement pour une équipe entière. À la fin, vous comprendrez chaque fichier du format de plugin et saurez exactement comment les pièces s'assemblent.
Prérequis
Avant de commencer, assurez-vous d'avoir :
- Claude Code installé et authentifié (exécutez
claude --versionpour vérifier ; toute version 2.x prend en charge les plugins) - Node.js 20 ou plus récent
- Un compte GitHub (ou tout hébergeur Git que votre équipe peut cloner)
- Une familiarité de base avec les concepts de Claude Code comme les commandes slash et
CLAUDE.md
Aucune expérience préalable des plugins n'est requise.
Ce que vous allez construire
Vous allez créer un plugin nommé team-toolkit qui regroupe cinq capacités :
- Une commande slash
/team-toolkit:changelogqui rédige une entrée de changelog à partir des commits récents - Un sous-agent
code-auditorqui vérifie le code selon les conventions de votre équipe - Un skill
conventional-commitsque Claude charge automatiquement lors de la rédaction de messages de commit - Un hook qui exécute votre formateur après chaque modification de fichier
- Une configuration de serveur MCP embarquée pour accéder à un dossier de documentation partagé
Vous créerez ensuite un second dépôt qui servira de marketplace, afin que n'importe quel membre de votre équipe puisse installer le plugin en une seule commande.
Étape 1 : comprendre l'anatomie d'un plugin
Un plugin Claude Code n'est qu'un répertoire avec un manifeste. Chaque composant est optionnel — un plugin peut n'embarquer qu'un hook, que des commandes, ou tout à la fois. La structure complète ressemble à ceci :
team-toolkit/
├── .claude-plugin/
│ └── plugin.json # Manifeste (obligatoire)
├── commands/ # Commandes slash (fichiers Markdown)
│ └── changelog.md
├── agents/ # Sous-agents (fichiers Markdown)
│ └── code-auditor.md
├── skills/ # Skills (dossiers avec SKILL.md)
│ └── conventional-commits/
│ └── SKILL.md
├── hooks/
│ └── hooks.json # Gestionnaires d'événements
├── scripts/ # Scripts utilisés par les hooks
│ └── format.sh
└── .mcp.json # Serveurs MCP embarquésDeux règles comptent plus que tout le reste :
- Le manifeste se trouve dans
.claude-plugin/plugin.json— à l'intérieur du répertoire caché, pas à la racine du dépôt. - Les répertoires de composants (
commands/,agents/,skills/,hooks/) se trouvent à la racine du plugin, pas dans.claude-plugin/.
Confondre ces deux règles est la cause la plus fréquente d'un plugin qui se charge mais dont les commandes n'apparaissent jamais.
Étape 2 : créer la structure et le manifeste
Créez l'arborescence et le manifeste :
mkdir -p team-toolkit/.claude-plugin
mkdir -p team-toolkit/commands team-toolkit/agents
mkdir -p team-toolkit/skills/conventional-commits
mkdir -p team-toolkit/hooks team-toolkit/scripts
cd team-toolkitCréez maintenant .claude-plugin/plugin.json :
{
"name": "team-toolkit",
"description": "Noqta engineering conventions: changelog command, code auditor, commit skill, format-on-edit hook",
"version": "1.0.0",
"author": {
"name": "Noqta Engineering",
"email": "dev@noqta.tn"
},
"keywords": ["conventions", "review", "changelog"]
}Seul name est strictement obligatoire, mais description et version apparaissent dans l'interface du gestionnaire de plugins : traitez-les donc comme obligatoires en pratique. Le name doit être en kebab-case sans espaces — il devient le préfixe d'espace de noms de chaque commande fournie par le plugin.
Étape 3 : ajouter une commande slash
Les commandes slash d'un plugin sont des fichiers Markdown dans commands/. Le nom du fichier devient le nom de la commande, préfixé par le plugin : commands/changelog.md devient /team-toolkit:changelog. Ce préfixage garantit que les commandes de votre plugin n'entrent jamais en collision avec celles d'un autre.
Créez commands/changelog.md :
---
description: Draft a changelog entry from recent commits
argument-hint: [version] [since-tag]
allowed-tools: Bash(git log:*), Bash(git diff:*), Read
---
Draft a changelog entry for version $1.
1. Run `git log --oneline $2..HEAD` to list commits since tag $2.
If no tag argument was given, use the most recent tag.
2. Group the commits into Added, Changed, Fixed, and Removed sections
following the Keep a Changelog format.
3. Rewrite each line as a user-facing sentence — drop internal refactor
noise unless it affects behavior.
4. Output the entry as Markdown ready to paste into CHANGELOG.md.
Do not modify any files.Trois détails méritent attention :
argument-hintest ce que voient les utilisateurs lors de l'autocomplétion de la commande.$1et$2reçoivent les arguments positionnels ;$ARGUMENTSrecevrait la chaîne d'arguments entière.allowed-toolspré-approuve des motifs d'outils spécifiques pour que la commande s'exécute sans demandes de permission — restreignez-le autant que possible.
Étape 4 : ajouter un sous-agent
Les sous-agents sont des assistants spécialisés dotés de leur propre prompt système, de restrictions d'outils et d'une fenêtre de contexte indépendante. Claude leur délègue automatiquement quand une tâche correspond à leur description, ou vous pouvez les invoquer explicitement.
Créez agents/code-auditor.md :
---
name: code-auditor
description: Reviews code changes against Noqta engineering conventions. Use proactively after significant edits or before committing.
tools: Read, Grep, Glob, Bash
model: inherit
---
You are a strict but pragmatic code auditor for a TypeScript/Next.js team.
When invoked:
1. Run `git diff HEAD` to see pending changes.
2. Check every changed file against these conventions:
- No console.log in production code (a logger must be used)
- No empty catch blocks
- Files stay under 300 lines
- Repeated logic is extracted into shared utilities
3. Report findings ordered by severity. For each finding include
the file path, line number, and a concrete suggested fix.
4. If everything passes, say so explicitly and list what you checked.
Never modify files yourself. You are read-only by convention.Le champ description est ce que Claude lit pour décider de déléguer — des formules comme « use proactively » influencent réellement le comportement de délégation. Définir model: inherit maintient le sous-agent sur le même modèle que la conversation principale ; vous pouvez aussi épingler un modèle spécifique comme haiku pour les vérifications mécaniques peu coûteuses.
Étape 5 : ajouter un skill
Les skills diffèrent des commandes sur un point fondamental : les commandes sont invoquées par l'utilisateur, les skills sont chargés par Claude lui-même quand la tâche correspond. Un skill est un dossier contenant un SKILL.md dont le frontmatter indique à Claude quand le charger.
Créez skills/conventional-commits/SKILL.md :
---
name: conventional-commits
description: Format git commit messages using the team's conventional commit standard. Use whenever writing, amending, or reviewing a commit message.
---
# Conventional Commits — Team Standard
## Format
type(scope): subject
body (optional)
footer (optional)
## Types
feat, fix, docs, style, refactor, test, chore
## Rules
1. Subject in imperative mood, lowercase, no trailing period
2. Scope is the affected module: auth, api, ui, content, build
3. One logical change per commit — never batch unrelated edits
4. Reference issues in the footer: "Refs #123" or "Closes #123"
5. Body explains the why for any non-obvious change
## Examples
feat(auth): add password reset flow
fix(api): handle null values in user profile endpoint
The endpoint returned 500 when optional fields were null.
Added null checks with sensible defaults.
Closes #456Comme le skill est livré dans le plugin, chaque développeur qui installe team-toolkit obtient des conventions de commit identiques appliquées automatiquement — fini le copier-coller de directives dans le CLAUDE.md de chaque projet.
Étape 6 : ajouter un hook
Les hooks exécutent des commandes shell lors d'événements du cycle de vie — une automatisation déterministe qui ne dépend pas d'une décision du modèle. Nous allons formater les fichiers après chaque modification.
Créez hooks/hooks.json :
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh"
}
]
}
]
}
}Et le script dans scripts/format.sh :
#!/usr/bin/env bash
# Reads the hook payload from stdin, formats the edited file if supported.
set -euo pipefail
payload=$(cat)
file_path=$(echo "$payload" | jq -r '.tool_input.file_path // empty')
if [[ -z "$file_path" ]]; then
exit 0
fi
case "$file_path" in
*.ts|*.tsx|*.js|*.jsx|*.json|*.css|*.md)
if command -v prettier >/dev/null 2>&1; then
prettier --write "$file_path" >/dev/null 2>&1 || true
fi
;;
esac
exit 0Rendez-le exécutable :
chmod +x scripts/format.shLe détail crucial est ${CLAUDE_PLUGIN_ROOT} — une variable d'environnement qui pointe vers l'emplacement d'installation du plugin à l'exécution. Ne codez jamais de chemins en dur dans les hooks d'un plugin ; le plugin sera installé à un endroit que vous ne contrôlez pas sur la machine de chaque utilisateur. Parmi les événements utiles au-delà de PostToolUse : PreToolUse (bloquer des actions avant leur exécution), UserPromptSubmit (injecter du contexte à chaque prompt), SessionStart et Stop.
Étape 7 : embarquer un serveur MCP
Les plugins peuvent livrer des configurations de serveurs MCP qui s'activent quand le plugin est activé. Créez .mcp.json à la racine du plugin :
{
"mcpServers": {
"team-docs": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"${CLAUDE_PLUGIN_ROOT}/docs"
]
}
}
}Cet exemple expose un dossier docs/ livré dans le plugin lui-même — pratique pour les architecture decision records ou les références d'API que toute l'équipe devrait pouvoir interroger. En déploiement réel, vous pointerez plus souvent vers un serveur MCP interne (passerelle de base de données, gestionnaire de tickets, API d'observabilité). La même règle s'applique : utilisez ${CLAUDE_PLUGIN_ROOT} pour tout chemin relatif, et des variables d'environnement pour les secrets — ne codez jamais d'identifiants en dur dans .mcp.json.
Créez un fichier de départ pour que le dossier existe :
mkdir -p docs
echo "# Team Engineering Docs" > docs/README.mdÉtape 8 : tester le plugin localement
Avant de publier quoi que ce soit, validez la structure. Claude Code embarque un validateur :
claude plugin validate .Corrigez toute erreur de manifeste ou de schéma signalée. Testez ensuite le comportement réel avec une marketplace locale. Le schéma le plus propre consiste à garder les plugins dans un dépôt de marketplace dès le premier jour, alors mettez cela en place maintenant :
cd ..
mkdir -p noqta-claude-plugins/.claude-plugin
mv team-toolkit noqta-claude-plugins/plugins/team-toolkitAttendez avant de créer le manifeste de la marketplace — c'est l'étape 9. Pour un test local rapide, vous pouvez ajouter directement le répertoire de la marketplace :
claude
# puis dans la session :
/plugin marketplace add ./noqta-claude-plugins
/plugin install team-toolkit@noqta-claude-pluginsRedémarrez la session quand on vous le demande, puis vérifiez chaque composant :
- Tapez
/team-toolkit:changelog 1.2.0— la commande doit apparaître dans l'autocomplétion et s'exécuter. - Demandez « vérifie mes modifications en attente pour des violations de conventions » — Claude doit déléguer à
code-auditor. - Demandez à Claude de committer quelque chose — le skill
conventional-commitsdoit façonner le message. - Modifiez n'importe quel fichier TypeScript — Prettier doit s'exécuter automatiquement via le hook.
- Exécutez
/mcp— le serveurteam-docsdoit être listé et connecté.
Si un composant n'apparaît pas, lancez claude --debug et observez la sortie de chargement des plugins au démarrage ; elle nomme chaque manifeste analysé et toute erreur rencontrée.
Étape 9 : créer la marketplace et publier
Une marketplace est n'importe quel dépôt Git contenant .claude-plugin/marketplace.json. Créez noqta-claude-plugins/.claude-plugin/marketplace.json :
{
"name": "noqta-claude-plugins",
"owner": {
"name": "Noqta Engineering",
"email": "dev@noqta.tn"
},
"metadata": {
"description": "Internal Claude Code plugins for the Noqta team",
"version": "1.0.0"
},
"plugins": [
{
"name": "team-toolkit",
"source": "./plugins/team-toolkit",
"description": "Team conventions: changelog command, code auditor, commit skill, format-on-edit hook",
"version": "1.0.0",
"category": "productivity"
}
]
}Le champ source accepte un chemin relatif (le plugin vit dans ce dépôt), une référence GitHub ou une URL Git — une marketplace peut donc aussi agréger des plugins d'autres dépôts. Validez et poussez :
cd noqta-claude-plugins
claude plugin validate .
git init && git add -A
git commit -m "feat: add team-toolkit plugin and marketplace manifest"
gh repo create noqta/claude-plugins --private --source . --pushToute personne ayant accès peut maintenant l'installer :
/plugin marketplace add noqta/claude-plugins
/plugin install team-toolkit@noqta-claude-pluginsPour les mises à jour : incrémentez version dans plugin.json et dans l'entrée de la marketplace, poussez, et les utilisateurs récupèrent les changements avec /plugin marketplace update noqta-claude-plugins.
Étape 10 : déployer pour toute l'équipe
La vraie force, c'est le déploiement automatique. Dans n'importe quel dépôt, committez un fichier .claude/settings.json qui déclare la marketplace et active le plugin :
{
"extraKnownMarketplaces": {
"noqta-claude-plugins": {
"source": {
"source": "github",
"repo": "noqta/claude-plugins"
}
}
},
"enabledPlugins": {
"team-toolkit@noqta-claude-plugins": true
}
}Désormais, chaque développeur qui ouvre ce dépôt avec Claude Code reçoit une seule invite pour faire confiance à la marketplace, puis le plugin s'installe et s'active tout seul. L'onboarding d'un nouveau coéquipier passe d'une page wiki d'étapes de configuration à un simple git clone.
Tester votre implémentation
Parcourez cette liste pour confirmer que tout fonctionne de bout en bout :
claude plugin validate .passe dans le dépôt du plugin comme dans celui de la marketplace/pluginafficheteam-toolkitcomme installé et activé/team-toolkit:changelog 1.0.0produit un brouillon de changelog groupé- Le sous-agent
code-auditorapparaît dans/agents - Modifier un fichier
.tsdéclenche Prettier (vérifiez que le formatage du fichier change) /mcplisteteam-docscomme connecté- Un clone frais d'un dépôt contenant le
.claude/settings.jsonde l'étape 10 propose d'installer le plugin
Dépannage
Les commandes n'apparaissent pas après l'installation. Vérifiez la structure des répertoires : plugin.json dans .claude-plugin/, mais commands/ à la racine du plugin. Redémarrez Claude Code après l'installation — les composants s'enregistrent au démarrage de la session.
Le hook ne se déclenche jamais. Vérifiez que format.sh est exécutable (chmod +x) et que vous avez utilisé ${CLAUDE_PLUGIN_ROOT} plutôt qu'un chemin relatif. Lancez claude --debug pour voir les journaux d'enregistrement et d'exécution des hooks.
Le serveur MCP ne se connecte pas. Exécutez /mcp pour voir l'erreur. La cause la plus fréquente est une commande absente du PATH dans l'environnement où s'exécute Claude Code — préférez npx -y package-name aux binaires installés globalement.
L'ajout de la marketplace échoue avec une erreur de manifeste. Le fichier doit se trouver exactement dans .claude-plugin/marketplace.json, et chaque chemin source doit exister relativement à la racine du dépôt. claude plugin validate . détecte les deux cas.
Le plugin fonctionne chez vous mais pas chez vos collègues. C'est presque toujours un chemin codé en dur ou une dépendance manquante (comme jq ou prettier) sur leur machine. Les hooks doivent se dégrader proprement — notez comment format.sh sort avec le code 0 quand Prettier est absent.
Prochaines étapes
- Ajoutez une commande
/team-toolkit:releasequi enchaîne le brouillon de changelog avec l'incrément de version et le tag - Livrez votre runbook de déploiement comme second skill pour que la réponse aux incidents se charge à la demande
- Explorez notre guide sur la rédaction de fichiers SKILL.md efficaces pour affiner les descriptions de skills
- Construisez un serveur MCP personnalisé en TypeScript et embarquez-le dans le plugin
- Comparez avec le Claude Agent SDK quand vous avez besoin d'agents programmatiques plutôt que d'outillage interactif
Conclusion
Vous avez construit un plugin Claude Code complet — commande slash, sous-agent, skill, hook et serveur MCP embarqué — vous l'avez validé, publié via une marketplace hébergée sur Git, et câblé le déploiement automatique en équipe via les paramètres du dépôt. La force du format de plugin tient au fait que chaque pièce est du simple Markdown ou JSON dans un dépôt versionné : l'outillage IA de votre équipe évolue désormais par pull requests, revue de code et releases, comme n'importe quel autre logiciel. Commencez petit avec une commande et un hook, puis faites grandir la boîte à outils à mesure que les conventions se consolident.