> ## Documentation Index
> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Créer un mod

> Demandez à Claude d'écrire un mod Claude Code à partir d'une description, ou écrivez-en un vous-même qui compte les appels d'outils et ajoute une commande. Apprenez la boucle de rechargement et de validation.

Un mod est un [plugin](/docs/fr/plugins/overview) Claude Code avec un fichier d'entrée, appelé le module de hooks : un fichier JavaScript ou TypeScript dont les fonctions Claude Code appelle lorsque des événements se produisent. Il y a deux façons d'en créer un :

* **Demander à Claude de l'écrire** : [décrivez ce que vous voulez](#ask-claude-for-a-mod) dans une session Claude Code
* **L'écrire vous-même** : [suivez le tutoriel](#write-a-mod-yourself) pour apprendre comment fonctionne le code d'un mod. Vous n'avez pas besoin de Node.js, d'un bundler ou d'une étape de build, car Claude Code charge les fichiers `.js` et `.ts` directement.

Si vous n'avez pas encore décidé si un mod est le bon outil, lisez d'abord la [comparaison sur la page d'aperçu](/docs/fr/plugins/mods/overview#compare-mods-settings-hooks-skills-and-mcp-servers).

<Note>
  Les mods nécessitent Claude Code v2.1.287 ou ultérieur. Dans votre shell, exécutez `claude --version` pour vérifier. Pour voir si les mods peuvent se charger pour vous, consultez [Vérifier si les mods peuvent se charger](/docs/fr/plugins/mods/troubleshoot#check-whether-mods-can-load).
</Note>

<h2 id="ask-claude-for-a-mod">
  Demander à Claude un mod
</h2>

Décrivez le mod que vous voulez dans une session Claude Code interactive, et Claude l'écrit. Claude fonctionne à partir d'une [skill](/docs/fr/skills) intégrée nommée `plugin-authoring`, qui lui indique où écrire le mod, quels événements et méthodes votre version a, et comment le mod est chargé. Claude peut charger la skill lorsque vous demandez un mod, ou vous pouvez la charger vous-même en exécutant `/plugin-authoring` à l'invite Claude Code.

Le mod s'exécute une fois que vous l'approuvez, sauf dans [les sessions où un mod que Claude écrit ne peut pas se charger](#sessions-that-skip-the-approval).

<Steps>
  <Step title="Décrivez le mod">
    Demandez le mod avec vos propres mots, par exemple `make a mod that shows the current git branch above the prompt`. Claude écrit le mod dans un répertoire qui lui est propre dans le dossier des mods de la session, qui est `~/.claude/dev-mods/` suivi de l'ID de la session. Le chemin complet d'un mod ressemble à `~/.claude/dev-mods/3f2a9c1e-5b7d-4e8a-9c21-6d0f4b8a7e13/git-branch/`.

    <Note>
      Dans les [modes de permission](/docs/fr/permission-modes#protected-paths) `default` et `acceptEdits`, Claude Code demande avant que Claude crée chacun des fichiers du mod, car `~/.claude` est un chemin protégé. Approuvez chaque fichier au fur et à mesure.
    </Note>
  </Step>

  <Step title="Approuvez le mod">
    Lorsque Claude enregistre le premier fichier, Claude Code demande s'il faut activer le rechargement à chaud pour la session. Le rechargement à chaud exécute les mods que Claude écrit dans cette session et récupère chaque modification ultérieure.

    Choisissez l'une de ces réponses :

    * **Activer pour cette session** : les mods dans le dossier des mods de la session se chargent à la fin du tour, et se rechargent à la fin de chaque tour qui les modifie. Votre réponse dure pour la session, y compris après l'avoir reprise.
    * **Pas maintenant** : rien ne se charge pour l'instant. Les fichiers restent où Claude les a écrits, et les mods se chargent la prochaine fois que cette session démarre. Pour empêcher un mod de jamais se charger, supprimez son répertoire.
  </Step>

  <Step title="Vérifiez que le mod s'est chargé">
    Exécutez `/plugin` à l'invite Claude Code et appuyez sur Tab jusqu'à ce que l'onglet **Installed** soit sélectionné. Il liste le mod, et vous pouvez l'éteindre là.
  </Step>

  <Step title="Essayez le mod">
    Utilisez ce que vous avez demandé. Pour l'exemple d'invite, le nom de la branche actuelle apparaît au-dessus de la boîte d'invite. Si le mod ne fait pas ce que vous vouliez, dites à Claude ce qu'il faut changer. Le mod se recharge à la fin de chaque tour qui modifie ses fichiers, vous pouvez donc essayer la modification dès que Claude a terminé.
  </Step>
</Steps>

<h3 id="use-the-mod-in-other-sessions">
  Utilisez le mod dans d'autres sessions
</h3>

Un mod que Claude a écrit ne se charge que dans la session qui l'a créé, et Claude Code supprime le dossier des mods de cette session une fois qu'il est plus ancien que [`cleanupPeriodDays`](/docs/fr/settings-reference#cleanupperioddays). Pour conserver le mod, copiez son répertoire hors du dossier des mods vers un endroit qui vous appartient, comme `~/mods/git-branch`. Ensuite, choisissez comment le charger :

* **Dans une session que vous démarrez** : dans votre shell, exécutez `claude --plugin-dir ~/mods/git-branch`
* **Pour d'autres personnes** : [ajoutez-le à une marketplace](#share-your-mod) pour qu'elles puissent l'installer

<h3 id="sessions-that-skip-the-approval">
  Sessions où un mod que Claude écrit ne peut pas se charger
</h3>

Un mod que Claude écrit ne se charge qu'après que vous l'approuviez, dans un espace de travail de confiance où les mods sont autorisés à s'exécuter. Dans ces sessions, il ne se charge pas :

* **Personne n'est là pour approuver** : la session ne peut pas vous montrer une invite, comme dans une exécution `claude -p` ou en [mode `dontAsk`](/docs/fr/permission-modes)
* **L'espace de travail n'est pas de confiance** : vous n'avez pas accepté l'invite de confiance pour le répertoire
* **Les mods sont arrêtés** : vous avez démarré avec `--safe-mode` ou `--bare`, vous avez défini `disableAllHooks`, ou les [paramètres gérés](/docs/fr/plugins/mods/admin#choose-how-much-to-allow) de votre organisation le bloquent

<h2 id="write-a-mod-yourself">
  Écrivez un mod vous-même
</h2>

Dans ce tutoriel, vous construisez un mod nommé `first-mod` qui compte les appels d'outils que Claude fait, affiche le compte à côté du spinner pendant que Claude travaille, et ajoute une commande `/tally` qui l'imprime. Vous lisez ensuite les déclarations de type que Claude Code écrit à côté de votre mod et exécutez `claude plugin validate`. Ensemble, ils vous montrent les événements et méthodes que votre version offre et ce que Claude Code lit à partir de votre code.

Cet enregistrement montre le mod terminé. Le spinner compte les appels d'outils, `/tally` imprime le compte, et une modification du code prend effet pendant que la session s'exécute :

<Frame>
  <video autoPlay muted loop playsInline controls className="w-full dark:hidden" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-first-mod-light.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=eb561134afa90375777408453ba51c77" aria-label="In a Claude Code session, the prompt 'list the files here and read the README' is typed and sent. The spinner reads 'Thinking · tool calls: 1' and the count rises as Claude works. The /tally command prints 'first-mod: Claude has made 3 tool calls since this mod loaded'. A line says first-mod reloaded and lists its four hooks. On the next prompt the spinner reads 'Thinking · tools used: 1'." data-path="images/mods-first-mod-light.mp4" />

  <video autoPlay muted loop playsInline controls className="w-full hidden dark:block" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-first-mod-dark.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=09779dadc7ef66c2b1e2da0c2e31ac72" aria-label="In a Claude Code session, the prompt 'list the files here and read the README' is typed and sent. The spinner reads 'Thinking · tool calls: 1' and the count rises as Claude works. The /tally command prints 'first-mod: Claude has made 3 tool calls since this mod loaded'. A line says first-mod reloaded and lists its four hooks. On the next prompt the spinner reads 'Thinking · tools used: 1'." data-path="images/mods-first-mod-dark.mp4" />
</Frame>

Vous écrivez trois fichiers :

```text theme={null}
first-mod/
├── .claude-plugin/
│   └── plugin.json
└── hooks/
    ├── hooks.json
    └── register.js
```

* **`plugin.json`** : le [manifeste](/docs/fr/plugins/manifest-reference) du plugin
* **`hooks.json`** : [pointe vers votre fichier de code](/docs/fr/plugins/mods/reference#files)
* **`register.js`** : votre code, appelé le module de hooks

<Steps>
  <Step title="Créez le répertoire du plugin">
    Créez les deux répertoires qui contiennent les fichiers :

    <Tabs>
      <Tab title="Bash ou Zsh">
        ```bash theme={null}
        mkdir -p first-mod/.claude-plugin first-mod/hooks
        ```
      </Tab>

      <Tab title="PowerShell">
        ```powershell theme={null}
        New-Item -ItemType Directory -Force first-mod\.claude-plugin, first-mod\hooks
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Écrivez le manifeste">
    Un mod est un plugin, et un mod a besoin d'un [manifeste](/docs/fr/plugins/manifest-reference). Le manifeste de ce mod n'a pas de champs spéciaux. Enregistrez ceci comme `first-mod/.claude-plugin/plugin.json` :

    ```json first-mod/.claude-plugin/plugin.json theme={null}
    {
      "name": "first-mod",
      "version": "0.1.0",
      "description": "Counts Claude's tool calls, shows the count beside the spinner, and adds a /tally command",
      "author": { "name": "Your Name" }
    }
    ```
  </Step>

  <Step title="Dites à Claude Code où se trouve votre code">
    Lorsque Claude Code charge un plugin, il lit le `hooks/hooks.json` du plugin. La clé `modules` dans ce fichier donne le chemin vers votre code, et l'avoir est ce qui rend le plugin un mod. Listez un chemin, relatif à `hooks.json`. Ici, il pointe vers `register.js`, que vous écrivez à l'étape suivante.

    Enregistrez ceci comme `first-mod/hooks/hooks.json` :

    ```json first-mod/hooks/hooks.json theme={null}
    {
      "description": "The first-mod hooks module",
      "modules": ["./register.js"]
    }
    ```
  </Step>

  <Step title="Écrivez le code">
    Ce fichier est le code du mod, appelé le module de hooks. Lorsque le mod se charge, Claude Code appelle la fonction `register` que le fichier exporte et lui passe une fonction nommée [`on`](/docs/fr/plugins/mods/reference#the-hook-function). Chaque appel à `on` enregistre un gestionnaire d'événement, appelé un hook, pour l'événement qu'il nomme.

    Enregistrez ceci comme `first-mod/hooks/register.js` :

    ```javascript first-mod/hooks/register.js theme={null}
    // The count, shared by the hooks below
    let calls = 0

    // Claude Code calls this once when the mod loads
    export function register(on) {
      // Runs when the session starts, before your first prompt
      on('session.start', async ($, e, next) => {
        // Add the /tally command
        await $.command.register({
          name: 'tally',
          description: 'Show how many tool calls Claude has made',
        })
        // Let the session start as usual
        return next(e)
      })

      // Runs each time Claude is about to use a tool
      on('tool.call', async ($, e, next) => {
        calls += 1
        // Ask Claude Code to draw the interface again, so the new count shows
        $.ui.invalidate('ui.render')
        // Let the tool run as usual
        return next(e)
      })

      // Runs when you type /tally, and only then, because of the matcher
      on('command.run', { command: 'tally' }, async () => {
        // The text to print in the transcript
        return { text: 'Claude has made ' + calls + ' tool calls since this mod loaded' }
      })

      // Runs each time Claude Code draws the spinner
      on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
        // Keep Claude Code's spinner, with the count added after its word
        return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
      })
    }
    ```

    Le fichier garde un compte dans `calls` et enregistre quatre hooks :

    * **[`session.start`](/docs/fr/plugins/mods/reference#session)** s'exécute lorsque la session démarre, avant votre première invite, et à nouveau chaque fois que le mod se recharge. Il ajoute la commande `/tally` à Claude Code.
    * **[`tool.call`](/docs/fr/plugins/mods/reference#tools)** s'exécute chaque fois que Claude est sur le point d'utiliser un outil. Il ajoute un à `calls` et demande à Claude Code de redessiner l'interface.
    * **[`command.run`](/docs/fr/plugins/mods/reference#commands-and-configuration)** s'exécute lorsque vous tapez `/tally`. Il retourne le texte à imprimer.
    * **[`ui.render`](/docs/fr/plugins/mods/reference#interface)** s'exécute chaque fois que Claude Code dessine le spinner. Il ajoute le compte après le mot du spinner.

    [Comment fonctionne le mod d'exemple](#how-the-example-mod-works) explique les trois arguments que chaque hook prend et ce que chacun retourne.
  </Step>

  <Step title="Chargez le mod">
    Démarrez Claude Code avec le drapeau `--plugin-dir`, qui charge un répertoire de plugin pour une session sans l'installer :

    ```bash theme={null}
    claude --plugin-dir ./first-mod
    ```
  </Step>

  <Step title="Essayez le mod">
    Demandez à Claude de faire quelque chose qui prend quelques appels d'outils, comme `list the files here and read the README`. Pendant que Claude travaille, le mot du spinner est suivi d'un compte qui augmente, comme dans `Thinking · tool calls: 2…`. Lorsque Claude a terminé, tapez `/tally` et appuyez sur Entrée. La transcription affiche `first-mod: Claude has made 2 tool calls since this mod loaded`, avec votre propre compte. Claude Code met le nom du plugin devant le texte de la commande.

    Pour vérifier la commande sans une session interactive, exécutez-la en mode non-interactif :

    ```bash theme={null}
    claude -p "/tally" --plugin-dir ./first-mod
    ```

    ```text theme={null}
    first-mod: Claude has made 0 tool calls since this mod loaded
    ```

    Si `/tally` n'est pas dans la liste des commandes, le module ne s'est pas chargé. Consultez [Découvrez pourquoi un mod ne fait rien](/docs/fr/plugins/mods/troubleshoot#find-out-why-a-mod-does-nothing).
  </Step>

  <Step title="Modifiez le code pendant que la session s'exécute">
    Laissez la session ouverte. Dans `register.js`, changez `' · tool calls: '` en `' · tools used: '` dans le hook `ui.render` et enregistrez. La ligne en surbrillance est celle qui change :

    ```javascript first-mod/hooks/register.js {4} theme={null}
      // Runs each time Claude Code draws the spinner
      on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
        // Keep Claude Code's spinner, with the count added after its word
        return next({ ...e, props: { ...e.props, suffix: ' · tools used: ' + calls + '…' } })
      })
    ```

    Une ligne dans la transcription dit que `first-mod` s'est rechargé et liste ses hooks, et le prochain spinner utilise le nouveau texte, comme dans `Thinking · tools used: 1…`.
  </Step>
</Steps>

<h3 id="how-the-example-mod-works">
  Comment fonctionne le mod d'exemple
</h3>

Chaque fonction que vous passez à `on` est un hook, qui est un gestionnaire d'événement. Claude Code passe à chaque hook les trois mêmes arguments :

* **L'API des mods**, nommée `$` : chaque méthode qu'un mod peut appeler pour atteindre l'extérieur de lui-même, dans des [espaces de noms](/docs/fr/plugins/mods/reference#mods-api-methods) tels que `$.ui` et `$.command`
* **L'événement**, nommé `e` : l'[entrée de l'événement](/docs/fr/plugins/mods/reference#events) en tant que données simples, comme le nom et les arguments d'un appel d'outil
* **Le gestionnaire suivant**, nommé [`next`](/docs/fr/plugins/mods/events#how-a-hook-handles-an-event) : une fonction qui transmet l'événement aux autres mods puis au comportement propre de Claude Code, et retourne le résultat

Les hooks dans `first-mod` gèrent leurs événements de trois façons qu'un hook peut :

* **Observer** : le hook `session.start` enregistre la commande, et le hook `tool.call` compte l'appel et demande un redessinage. Les deux retournent `next(e)`, donc la session démarre et l'outil s'exécute comme d'habitude.
* **Répondre** : le hook `command.run` retourne son propre résultat et n'appelle jamais `next`. Le deuxième argument à `on`, `{ command: 'tally' }`, est un filtre, appelé un [matcher](/docs/fr/plugins/mods/events#filter-which-events-a-hook-handles), donc le hook s'exécute uniquement pour `/tally`.
* **Réécrire** : le hook `ui.render` appelle `next` avec une copie de `e` dont `suffix` contient le compte, donc Claude Code dessine son spinner habituel avec votre texte après le mot

Claude Code surveille un répertoire chargé avec `--plugin-dir` et recharge à chaud le module de hooks lorsqu'un fichier dedans change. Chaque rechargement exécute `register` à nouveau, donc `calls` revient à `0` et `/tally` recommence à compter. Pour conserver une valeur entre les rechargements, consultez [Conserver l'état](/docs/fr/plugins/mods/interface#keep-state).

<h2 id="keep-working-on-a-mod">
  Continuez à travailler sur un mod
</h2>

Une fois qu'un mod se charge, vous pouvez demander à Claude de le modifier, vérifier votre code par rapport aux définitions de type pour votre version, lister les événements et appels que Claude Code trouve dedans, et le tester.

<h3 id="change-a-mod-with-claude">
  Modifiez un mod avec Claude
</h3>

Pour modifier un mod que vous avez déjà, démarrez la session avec `--plugin-dir` pointé vers le répertoire du mod, afin que ce que Claude écrit se charge dans la même session :

```bash theme={null}
claude --plugin-dir ./first-mod
```

Ensuite, demandez la modification, par exemple `add a /tally-reset command to this mod that sets the tally back to zero`. Claude édite le module de hooks, exécute `claude plugin validate`, et corrige ce qu'il rapporte. Un répertoire que vous chargez avec `--plugin-dir` est un [chemin protégé](/docs/fr/permission-modes#protected-paths), donc en modes `default` et `acceptEdits` vous êtes invité à approuver chacune des modifications de Claude au mod. Le tableau des chemins protégés donne le résultat pour les autres modes de permission.

Les fichiers que Claude enregistre pendant son tour se rechargent à la fin du tour, vous pouvez donc essayer `/tally-reset` dès que Claude a terminé.

<h3 id="get-the-types-for-your-build">
  Obtenez les définitions de type pour votre version
</h3>

Chaque fois que Claude Code charge ou recharge un mod à partir d'un répertoire que vous passez à `--plugin-dir`, ou un mod [que Claude a écrit pour vous](#ask-claude-for-a-mod), il écrit des fichiers de déclaration TypeScript, se terminant par `.d.ts`, dans `.claude-plugin/types/` à l'intérieur du répertoire du mod. Ils décrivent les événements exacts, les méthodes de l'API des mods, et les éléments dans la version de Claude Code que vous exécutez, afin que votre éditeur puisse autocomplète et vérifier le type de vos hooks. Pour parcourir les déclarations en ligne, lisez [`mods/types/claude-code.d.ts`](https://github.com/anthropics/claude-code/blob/main/mods/types/claude-code.d.ts) dans le référentiel Claude Code, dont la première ligne nomme la version qui l'a écrit. Le répertoire contient ces fichiers :

| Chemin | Ce qu'il déclare |
| :- | :- |
| `claude-code/index.d.ts` | Chaque événement et son entrée et résultat, chaque espace de noms et méthode de l'API des mods, et les éléments que chaque surface peut dessiner |
| `claude-code-tools/index.d.ts` | Les entrées et résultats des outils intégrés, afin que vérifier `e.tool === 'Bash'` réduise `e` |
| `claude-code-mcp/index.d.ts` | Les entrées des outils MCP qui ont été connectés la dernière fois que vous avez enregistré un fichier dans le mod |
| `index.d.ts` dans un répertoire nommé pour un plugin | Ce que ce plugin ajoute à l'API des mods. Il y a un répertoire pour chaque plugin que votre `plugin.json` liste sous `dependencies`. |
| `tsconfig.json` | Les options du compilateur qui conviennent à un module de hooks |

Si votre mod n'a pas son propre `tsconfig.json`, Claude Code en ajoute un à la racine du mod qui étend le généré, afin que votre éditeur et `tsc -p ./first-mod` vérifient le type du mod sans plus de configuration.

Les événements et méthodes peuvent changer entre les versions, donc faites confiance à ces fichiers plutôt qu'à n'importe quelle page, celle-ci incluse, lorsqu'ils ne sont pas d'accord.

`claude-code/index.d.ts` est la référence la plus complète pour votre build, avec un commentaire et un exemple pour chaque méthode de l'API des mods. Pour chercher quelque chose, recherchez le fichier pour son nom, comme `'tool.call'`.

<h3 id="check-what-claude-code-reads-from-your-mod">
  Vérifiez ce que Claude Code lit à partir de votre mod
</h3>

Pour voir votre mod comme Claude Code le voit, sans exécuter votre code ou démarrer une session, utilisez `claude plugin validate`. Il vérifie le manifeste et exécute la même analyse statique sur la source du module de hooks que Claude Code exécute lorsqu'il charge un mod. Dans votre shell, exécutez-le sur le répertoire du mod :

```bash theme={null}
claude plugin validate ./first-mod
```

Pour `first-mod`, la sortie inclut ces lignes.

```text theme={null}
  ❯ ./register.js hooks: session.start, tool.call, command.run{command=tally}, ui.render{component=Spinner}
  ❯ ./register.js calls: $.command.register, $.ui.invalidate

✔ Validation passed
```

La ligne `hooks:` liste les événements que votre module hook, chacun avec son filtre entre accolades. La ligne `calls:` liste chaque méthode de l'API des mods qu'il appelle. Un module qui lit ou définit des variables d'environnement obtient également des lignes `env reads:` et `env writes:`, et un qui utilise [`$.state`](/docs/fr/plugins/mods/interface#keep-state) obtient `state reads:` et `state writes:`.

Si un événement que vous aviez l'intention de hooker manque de la première ligne, Claude Code n'appellera pas ce hook non plus. La cause habituelle est un nom d'événement mal orthographié, que la commande rapporte comme une erreur telle que `"tool.calls" is not an event`.

Suivez ces règles afin que l'analyse statique puisse trouver chaque hook et appel :

* Épellez chaque appel de l'API des mods en entier : `$`, l'espace de noms, puis la méthode, comme dans `$.store.get('notes')`. Vous pouvez passer `$` à une fonction déclarée au niveau supérieur du même fichier, et pour une fonction vôtre nommée `loadNotes`, la ligne `calls:` lit alors `$.store.get (via loadNotes)`. Passer `$` à une méthode, une fonction définie à l'intérieur du hook, ou une fonction que vous importez d'un autre de vos fichiers échoue la validation. Les fonctions `read` et `update` que [`$.state`](/docs/fr/plugins/mods/interface#keep-state) utilise sont les imports qui peuvent le prendre. N'assignez pas `$` ou l'un de ses espaces de noms à une variable, ne le déstructurez pas, ou ne l'indexez pas avec un nom calculé. `const ui = $.ui` échoue avec `$.ui is used as a value`.
* Écrivez le nom de l'événement dans chaque appel `on` comme un littéral de chaîne, comme `'tool.call'`. Une variable, ou une boucle sur une liste de noms, échoue avec `the event name passed to on() is not a string literal`.
* À l'intérieur de `register`, ne déclarez pas une deuxième variable ou paramètre nommé `on`. La validation échoue avec `"on" is declared again (shadowed)`.
* Importez uniquement à partir de fichiers à l'intérieur du répertoire du plugin, par chemin relatif. Le seul import nu autorisé est `claude-code`, pour les types et quelques helpers.
* Utilisez les déclarations `import` en haut du fichier, comme dans `import { name } from './file.js'`. Un `import()` dynamique échoue avec `a dynamic import(); a hooks module imports its own files with an import declaration`.
* Écrivez chaque fichier en tant que module ES, avec `import` et non `require`. La [référence](/docs/fr/plugins/mods/reference#files) liste les extensions de fichier que Claude Code charge.

<h3 id="test-the-mod">
  Testez le mod
</h3>

Vous pouvez écrire des tests automatisés pour un mod et les exécuter à partir de votre shell avec `claude plugin test`, sans session, connexion ou réseau. Un test lève les événements que vos hooks gèrent et vérifie ce que les hooks ont fait.

Ce test lève deux appels d'outils, exécute `/tally`, et vérifie que la réponse compte les deux. Enregistrez-le comme `first-mod/tests/first-mod.test.ts` :

```typescript first-mod/tests/first-mod.test.ts theme={null}
import { expect, test } from 'claude-code/testing'

test('/tally reports the tool calls the mod has seen', async ($, on) => {
  // Answer each tool call in Claude Code's place, so no tool runs
  on('tool.call', () => ({ result: 'ok' }))

  // Raise two tool calls, which the mod's tool.call hook counts
  await $.tool.call({ tool: 'Bash', command: 'ls' })
  await $.tool.call({ tool: 'Read', file_path: 'README.md' })

  // Run /tally and check the text its hook returns
  const answer = await $.command.run({ command: 'tally', args: '' })
  expect(answer.text).toBe('Claude has made 2 tool calls since this mod loaded')
})
```

Dans votre shell, exécutez les tests à partir du répertoire `first-mod` :

```bash theme={null}
claude plugin test
```

La sortie nomme chaque test et s'il a réussi, avec des timings qui varient d'une exécution à l'autre :

```text theme={null}
tests/first-mod.test.ts:
(pass) /tally reports the tool calls the mod has seen [22.87ms]

 1 pass
 0 fail
Ran 1 test across 1 file. [0.19s]
```

[Testez un mod](/docs/fr/plugins/mods/test) couvre le stubbing d'un appel de modèle ou du store, et le test des minuteurs et des dessins.

<h2 id="share-your-mod">
  Partagez votre mod
</h2>

Un mod est un plugin, donc vous le versionnez dans le manifeste et les gens l'installent et le mettent à jour avec les commandes `/plugin`. Pour le donner à d'autres personnes, [ajoutez-le à une marketplace](/docs/fr/plugins/publish).

Avant de le faire, vérifiez le `name` du plugin : `claude plugin validate` échoue un nom qui [ressemble à l'un des propres d'Anthropic](/docs/fr/plugins/manifest-reference#name), comme un qui commence par `claude-`. Les événements et méthodes peuvent changer entre les versions, donc votre README est l'endroit pour dire quelle version de Claude Code vous avez testée.

Continuez à développer contre le répertoire avec `--plugin-dir`, pas contre une copie installée. Claude Code met en cache un plugin installé par version, donc vos modifications n'atteignent pas la copie installée jusqu'à ce que vous augmentiez la version et réinstalliez.

<h2 id="next-steps">
  Prochaines étapes
</h2>

* [Dessinez dans l'interface](/docs/fr/plugins/mods/interface) : ouvrez un volet, dessinez au-dessus de l'invite, et ajoutez des boutons et des champs de texte
* [Réagissez aux événements](/docs/fr/plugins/mods/events) : hooquez les appels d'outils, les invites, et les tours
* [Utilisez l'API des mods](/docs/fr/plugins/mods/api) : ajoutez des commandes et des outils, appelez un modèle, et exécutez du travail sur un minuteur
* [Testez un mod](/docs/fr/plugins/mods/test) : stubifiez ce que Claude Code répondrait, et testez les minuteurs et les dessins
* [Dépannez un mod](/docs/fr/plugins/mods/troubleshoot) : les raisons pour lesquelles un mod ne fait rien, et le journal de débogage
* [Lisez la source des mods intégrés](/docs/fr/plugins/mods/overview#read-the-source-of-built-in-mods) : des plugins complets, chacun avec son module de hooks et ses tests
