Traductions communautaires par veiseule.ai — Help improve them on Crowdin
Aller au contenu principal

Plugins (Extensions)¶

Démarrage rapide (nouveau sur les plugins ?)¶

Un plugin est simplement un petit module de code qui étend OpenClaw avec des fonctionnalités supplémentaires (commandes, outils et RPC de la Gateway (passerelle)).

La plupart du temps, vous utiliserez des plugins lorsque vous souhaitez une fonctionnalitĂ© qui n’est pas encore intĂ©grĂ©e au cƓur d’OpenClaw (ou lorsque vous voulez conserver des fonctionnalitĂ©s optionnelles hors de votre installation principale).

Chemin rapide :

  1. Voir ce qui est déjà chargé :
openclaw plugins list
  1. Installer un plugin officiel (exemple : Voice Call) :
openclaw plugins install @openclaw/voice-call
  1. Redémarrez la Gateway (passerelle), puis configurez sous plugins.entries.<id>.config.

Voir Voice Call pour un exemple concret de plugin.

Plugins disponibles (officiels)¶

  • Microsoft Teams est uniquement disponible via plugin depuis le 15/01/2026 ; installez @openclaw/msteams si vous utilisez Teams.
  • Memory (Core) — plugin de recherche de mĂ©moire groupĂ© (activĂ© par dĂ©faut via plugins.slots.memory)
  • Memory (LanceDB) — plugin de mĂ©moire long terme groupĂ© (rappel/capture automatiques ; dĂ©finir plugins.slots.memory = "memory-lancedb")
  • Voice Call — @openclaw/voice-call
  • Zalo Personal — @openclaw/zalouser
  • Matrix — @openclaw/matrix
  • Nostr — @openclaw/nostr
  • Zalo — @openclaw/zalo
  • Microsoft Teams — @openclaw/msteams
  • Google Antigravity OAuth (authentification fournisseur) — groupĂ© en tant que google-antigravity-auth (dĂ©sactivĂ© par dĂ©faut)
  • Gemini CLI OAuth (authentification fournisseur) — groupĂ© en tant que google-gemini-cli-auth (dĂ©sactivĂ© par dĂ©faut)
  • Qwen OAuth (authentification fournisseur) — groupĂ© en tant que qwen-portal-auth (dĂ©sactivĂ© par dĂ©faut)
  • Copilot Proxy (authentification fournisseur) — pont local VS Code Copilot Proxy ; distinct de la connexion intĂ©grĂ©e github-copilot par appareil (groupĂ©, dĂ©sactivĂ© par dĂ©faut)

Les plugins OpenClaw sont des modules TypeScript chargĂ©s Ă  l’exĂ©cution via jiti. La validation de configuration n’exĂ©cute pas le code du plugin ; elle utilise le manifeste du plugin et le schĂ©ma JSON Ă  la place. Voir Plugin manifest.

Les plugins peuvent enregistrer :

  • Des mĂ©thodes RPC de la Gateway (passerelle)
  • Des gestionnaires HTTP de la Gateway (passerelle)
  • Des outils d’agent
  • Des commandes CLI
  • Des services en arriĂšre-plan
  • Une validation de configuration optionnelle
  • Des Skills (en listant des rĂ©pertoires skills dans le manifeste du plugin)
  • Des commandes de rĂ©ponse automatique (exĂ©cutĂ©es sans invoquer l’agent IA)

Les plugins s’exĂ©cutent dans le mĂȘme processus que la Gateway (passerelle) ; traitez-les donc comme du code de confiance. Guide de crĂ©ation d’outils : Plugin agent tools.

Aides Ă  l’exĂ©cution¶

Les plugins peuvent accĂ©der Ă  certaines aides du cƓur via api.runtime. Pour la synthĂšse vocale (TTS) tĂ©lĂ©phonique :

const result = await api.runtime.tts.textToSpeechTelephony({
  text: "Hello from OpenClaw",
  cfg: api.config,
});

Remarques :

  • Utilise la configuration centrale messages.tts (OpenAI ou ElevenLabs).
  • Retourne un tampon audio PCM + un taux d’échantillonnage. Les plugins doivent rééchantillonner/encoder pour les fournisseurs.
  • Edge TTS n’est pas pris en charge pour la tĂ©lĂ©phonie.

Découverte et priorité¶

OpenClaw analyse, dans l’ordre :

  1. Chemins de configuration
  • plugins.load.paths (fichier ou rĂ©pertoire)
  1. Extensions de l’espace de travail
  • <workspace>/.openclaw/extensions/*.ts
  • <workspace>/.openclaw/extensions/*/index.ts
  1. Extensions globales
  • ~/.openclaw/extensions/*.ts
  • ~/.openclaw/extensions/*/index.ts
  1. Extensions groupées (livrées avec OpenClaw, désactivées par défaut)
  • <openclaw>/extensions/*

Les plugins groupĂ©s doivent ĂȘtre activĂ©s explicitement via plugins.entries.<id>.enabled ou openclaw plugins enable <id>. Les plugins installĂ©s sont activĂ©s par dĂ©faut, mais peuvent ĂȘtre dĂ©sactivĂ©s de la mĂȘme maniĂšre.

Chaque plugin doit inclure un fichier openclaw.plugin.json à sa racine. Si un chemin pointe vers un fichier, la racine du plugin est le répertoire du fichier et doit contenir le manifeste.

Si plusieurs plugins se rĂ©solvent vers le mĂȘme id, la premiĂšre correspondance selon l’ordre ci-dessus l’emporte et les copies de prioritĂ© infĂ©rieure sont ignorĂ©es.

Package packs¶

Un répertoire de plugin peut inclure un package.json avec openclaw.extensions :

{
  "name": "my-pack",
  "openclaw": {
    "extensions": ["./src/safety.ts", "./src/tools.ts"]
  }
}

Chaque entrĂ©e devient un plugin. Si le pack liste plusieurs extensions, l’id du plugin devient name/<fileBase>.

Si votre plugin importe des dépendances npm, installez-les dans ce répertoire afin que node_modules soit disponible (npm install / pnpm install).

Métadonnées du catalogue de canaux¶

Les plugins de canal peuvent annoncer des mĂ©tadonnĂ©es de prise en main via openclaw.channel et des indications d’installation via openclaw.install. Cela permet de garder le catalogue central sans donnĂ©es.

Exemple :

{
  "name": "@openclaw/nextcloud-talk",
  "openclaw": {
    "extensions": ["./index.ts"],
    "channel": {
      "id": "nextcloud-talk",
      "label": "Nextcloud Talk",
      "selectionLabel": "Nextcloud Talk (self-hosted)",
      "docsPath": "/channels/nextcloud-talk",
      "docsLabel": "nextcloud-talk",
      "blurb": "Self-hosted chat via Nextcloud Talk webhook bots.",
      "order": 65,
      "aliases": ["nc-talk", "nc"]
    },
    "install": {
      "npmSpec": "@openclaw/nextcloud-talk",
      "localPath": "extensions/nextcloud-talk",
      "defaultChoice": "npm"
    }
  }
}

OpenClaw peut Ă©galement fusionner des catalogues de canaux externes (par exemple, un export de registre MPM). DĂ©posez un fichier JSON Ă  l’un des emplacements suivants :

  • ~/.openclaw/mpm/plugins.json
  • ~/.openclaw/mpm/catalog.json
  • ~/.openclaw/plugins/catalog.json

Ou pointez OPENCLAW_PLUGIN_CATALOG_PATHS (ou OPENCLAW_MPM_CATALOG_PATHS) vers un ou plusieurs fichiers JSON (délimités par des virgules/points-virgules/PATH). Chaque fichier doit contenir { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }.

IDs de plugin¶

IDs de plugin par défaut :

  • Package packs : package.json name
  • Fichier autonome : nom de base du fichier (~/.../voice-call.ts → voice-call)

Si un plugin exporte id, OpenClaw l’utilise mais avertit lorsqu’il ne correspond pas Ă  l’id configurĂ©.

Configuration¶

{
  plugins: {
    enabled: true,
    allow: ["voice-call"],
    deny: ["untrusted-plugin"],
    load: { paths: ["~/Projects/oss/voice-call-extension"] },
    entries: {
      "voice-call": { enabled: true, config: { provider: "twilio" } },
    },
  },
}

Champs :

  • enabled : interrupteur principal (par dĂ©faut : true)
  • allow : liste d’autorisation (optionnelle)
  • deny : liste de refus (optionnelle ; le refus l’emporte)
  • load.paths : fichiers/rĂ©pertoires de plugins supplĂ©mentaires
  • entries.<id> : interrupteurs par plugin + configuration

Les modifications de configuration nécessitent un redémarrage de la gateway (passerelle).

RĂšgles de validation (strictes) :

  • Les ids de plugin inconnus dans entries, allow, deny ou slots sont des erreurs.
  • Les clĂ©s channels.<id> inconnues sont des erreurs, sauf si un manifeste de plugin dĂ©clare l’id de canal.
  • La configuration du plugin est validĂ©e Ă  l’aide du schĂ©ma JSON intĂ©grĂ© dans openclaw.plugin.json (configSchema).
  • Si un plugin est dĂ©sactivĂ©, sa configuration est conservĂ©e et un avertissement est Ă©mis.

Emplacements de plugin (catégories exclusives)¶

Certaines catĂ©gories de plugins sont exclusives (une seule active Ă  la fois). Utilisez plugins.slots pour sĂ©lectionner quel plugin possĂšde l’emplacement :

{
  plugins: {
    slots: {
      memory: "memory-core", // or "none" to disable memory plugins
    },
  },
}

Si plusieurs plugins déclarent kind: "memory", seul celui sélectionné est chargé. Les autres sont désactivés avec des diagnostics.

Interface de contrÎle (schéma + libellés)¶

L’interface de contrĂŽle utilise config.schema (schĂ©ma JSON + uiHints) pour afficher de meilleurs formulaires.

OpenClaw enrichit uiHints Ă  l’exĂ©cution en fonction des plugins dĂ©couverts :

  • Ajoute des libellĂ©s par plugin pour plugins.entries.<id> / .enabled / .config
  • Fusionne des indications de champs de configuration optionnelles fournies par les plugins sous : plugins.entries.<id>.config.<field>

Si vous souhaitez que les champs de configuration de votre plugin affichent de bons libellés/espaces réservés (et marquent les secrets comme sensibles), fournissez uiHints à cÎté de votre schéma JSON dans le manifeste du plugin.

Exemple :

{
  "id": "my-plugin",
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "apiKey": { "type": "string" },
      "region": { "type": "string" }
    }
  },
  "uiHints": {
    "apiKey": { "label": "API Key", "sensitive": true },
    "region": { "label": "Region", "placeholder": "us-east-1" }
  }
}

CLI¶

openclaw plugins list
openclaw plugins info <id>
openclaw plugins install <path>                 # copy a local file/dir into ~/.openclaw/extensions/<id>
openclaw plugins install ./extensions/voice-call # relative path ok
openclaw plugins install ./plugin.tgz           # install from a local tarball
openclaw plugins install ./plugin.zip           # install from a local zip
openclaw plugins install -l ./extensions/voice-call # link (no copy) for dev
openclaw plugins install @openclaw/voice-call # install from npm
openclaw plugins update <id>
openclaw plugins update --all
openclaw plugins enable <id>
openclaw plugins disable <id>
openclaw plugins doctor

plugins update fonctionne uniquement pour les installations npm suivies sous plugins.installs.

Les plugins peuvent également enregistrer leurs propres commandes de premier niveau (exemple : openclaw voicecall).

API de plugin (aperçu)¶

Les plugins exportent soit :

  • Une fonction : (api) => { ... }
  • Un objet : { id, name, configSchema, register(api) { ... } }

Hooks de plugin¶

Les plugins peuvent fournir des hooks et les enregistrer Ă  l’exĂ©cution. Cela permet Ă  un plugin d’intĂ©grer une automatisation pilotĂ©e par Ă©vĂ©nements sans installation sĂ©parĂ©e de pack de hooks.

Exemple¶

import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";

export default function register(api) {
  registerPluginHooksFromDir(api, "./hooks");
}

Remarques :

  • Les rĂ©pertoires de hooks suivent la structure normale des hooks (HOOK.md + handler.ts).
  • Les rĂšgles d’éligibilitĂ© des hooks s’appliquent toujours (OS/binaires/variables d'environnement/exigences de configuration).
  • Les hooks gĂ©rĂ©s par des plugins apparaissent dans openclaw hooks list avec plugin:<id>.
  • Vous ne pouvez pas activer/dĂ©sactiver les hooks gĂ©rĂ©s par des plugins via openclaw hooks ; activez/dĂ©sactivez le plugin Ă  la place.

Plugins de fournisseur (authentification de modÚle)¶

Les plugins peuvent enregistrer des flux d’authentification de fournisseur de modĂšle afin que les utilisateurs puissent exĂ©cuter la configuration OAuth ou par clĂ© API dans OpenClaw (sans scripts externes).

Enregistrez un fournisseur via api.registerProvider(...). Chaque fournisseur expose une ou plusieurs mĂ©thodes d’authentification (OAuth, clĂ© API, code appareil, etc.). Ces mĂ©thodes alimentent :

  • openclaw models auth login --provider <id> [--method <id>]

Exemple :

api.registerProvider({
  id: "acme",
  label: "AcmeAI",
  auth: [
    {
      id: "oauth",
      label: "OAuth",
      kind: "oauth",
      run: async (ctx) => {
        // Run OAuth flow and return auth profiles.
        return {
          profiles: [
            {
              profileId: "acme:default",
              credential: {
                type: "oauth",
                provider: "acme",
                access: "...",
                refresh: "...",
                expires: Date.now() + 3600 * 1000,
              },
            },
          ],
          defaultModel: "acme/opus-1",
        };
      },
    },
  ],
});

Remarques :

  • run reçoit un ProviderAuthContext avec des aides prompter, runtime, openUrl et oauth.createVpsAwareHandlers.
  • Retournez configPatch lorsque vous devez ajouter des modĂšles par dĂ©faut ou une configuration de fournisseur.
  • Retournez defaultModel afin que --set-default puisse mettre Ă  jour les valeurs par dĂ©faut de l’agent.

Enregistrer un canal de messagerie¶

Les plugins peuvent enregistrer des plugins de canal qui se comportent comme des canaux intégrés (WhatsApp, Telegram, etc.). La configuration du canal se trouve sous channels.<id> et est validée par le code de votre plugin de canal.

const myChannel = {
  id: "acmechat",
  meta: {
    id: "acmechat",
    label: "AcmeChat",
    selectionLabel: "AcmeChat (API)",
    docsPath: "/channels/acmechat",
    blurb: "demo channel plugin.",
    aliases: ["acme"],
  },
  capabilities: { chatTypes: ["direct"] },
  config: {
    listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
    resolveAccount: (cfg, accountId) =>
      cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
        accountId,
      },
  },
  outbound: {
    deliveryMode: "direct",
    sendText: async () => ({ ok: true }),
  },
};

export default function (api) {
  api.registerChannel({ plugin: myChannel });
}

Remarques :

  • Placez la configuration sous channels.<id> (pas plugins.entries).
  • meta.label est utilisĂ© pour les libellĂ©s dans les listes CLI/UI.
  • meta.aliases ajoute des ids alternatifs pour la normalisation et les entrĂ©es CLI.
  • meta.preferOver liste les ids de canal Ă  ignorer pour l’activation automatique lorsque les deux sont configurĂ©s.
  • meta.detailLabel et meta.systemImage permettent aux interfaces d’afficher des libellĂ©s/icĂŽnes de canal plus riches.

Écrire un nouveau canal de messagerie (Ă©tape par Ă©tape)¶

Utilisez ceci lorsque vous souhaitez une nouvelle surface de discussion (un « canal de messagerie »), et non un fournisseur de modÚle. La documentation des fournisseurs de modÚle se trouve sous /providers/*.

  1. Choisir un id + une forme de configuration
  • Toute la configuration du canal se trouve sous channels.<id>.
  • PrĂ©fĂ©rez channels.<id>.accounts.<accountId> pour les configurations multi‑comptes.
  1. Définir les métadonnées du canal
  • meta.label, meta.selectionLabel, meta.docsPath, meta.blurb contrĂŽlent les listes CLI/UI.
  • meta.docsPath doit pointer vers une page de documentation comme /channels/<id>.
  • meta.preferOver permet Ă  un plugin de remplacer un autre canal (l’activation automatique le privilĂ©gie).
  • meta.detailLabel et meta.systemImage sont utilisĂ©s par les interfaces pour le texte/icĂŽnes de dĂ©tail.
  1. Implémenter les adaptateurs requis
  • config.listAccountIds + config.resolveAccount
  • capabilities (types de chat, mĂ©dias, fils, etc.)
  • outbound.deliveryMode + outbound.sendText (pour l’envoi de base)
  1. Ajouter des adaptateurs optionnels selon les besoins
  • setup (assistant), security (politique de message privĂ©), status (santĂ©/diagnostics)
  • gateway (dĂ©marrer/arrĂȘter/connexion), mentions, threading, streaming
  • actions (actions sur les messages), commands (comportement des commandes natives)
  1. Enregistrer le canal dans votre plugin
  • api.registerChannel({ plugin })

Exemple de configuration minimale :

{
  channels: {
    acmechat: {
      accounts: {
        default: { token: "ACME_TOKEN", enabled: true },
      },
    },
  },
}

Plugin de canal minimal (sortant uniquement) :

const plugin = {
  id: "acmechat",
  meta: {
    id: "acmechat",
    label: "AcmeChat",
    selectionLabel: "AcmeChat (API)",
    docsPath: "/channels/acmechat",
    blurb: "AcmeChat messaging channel.",
    aliases: ["acme"],
  },
  capabilities: { chatTypes: ["direct"] },
  config: {
    listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
    resolveAccount: (cfg, accountId) =>
      cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
        accountId,
      },
  },
  outbound: {
    deliveryMode: "direct",
    sendText: async ({ text }) => {
      // deliver `text` to your channel here
      return { ok: true };
    },
  },
};

export default function (api) {
  api.registerChannel({ plugin });
}

Chargez le plugin (rĂ©pertoire d’extensions ou plugins.load.paths), redĂ©marrez la gateway (passerelle), puis configurez channels.<id> dans votre configuration.

Outils d’agent¶

Voir le guide dédié : Plugin agent tools.

Enregistrer une méthode RPC de la gateway (passerelle)¶

export default function (api) {
  api.registerGatewayMethod("myplugin.status", ({ respond }) => {
    respond(true, { ok: true });
  });
}

Enregistrer des commandes CLI¶

export default function (api) {
  api.registerCli(
    ({ program }) => {
      program.command("mycmd").action(() => {
        console.log("Hello");
      });
    },
    { commands: ["mycmd"] },
  );
}

Enregistrer des commandes de réponse automatique¶

Les plugins peuvent enregistrer des commandes slash personnalisĂ©es qui s’exĂ©cutent sans invoquer l’agent IA. C’est utile pour les commandes de bascule, les vĂ©rifications d’état ou les actions rapides qui ne nĂ©cessitent pas de traitement par LLM.

export default function (api) {
  api.registerCommand({
    name: "mystatus",
    description: "Show plugin status",
    handler: (ctx) => ({
      text: `Plugin is running! Channel: ${ctx.channel}`,
    }),
  });
}

Contexte du gestionnaire de commande :

  • senderId : l’id de l’expĂ©diteur (si disponible)
  • channel : le canal oĂč la commande a Ă©tĂ© envoyĂ©e
  • isAuthorizedSender : si l’expĂ©diteur est un utilisateur autorisĂ©
  • args : arguments passĂ©s aprĂšs la commande (si acceptsArgs: true)
  • commandBody : le texte complet de la commande
  • config : la configuration OpenClaw actuelle

Options de commande :

  • name : nom de la commande (sans le / initial)
  • description : texte d’aide affichĂ© dans les listes de commandes
  • acceptsArgs : indique si la commande accepte des arguments (par dĂ©faut : false). Si false et que des arguments sont fournis, la commande ne correspondra pas et le message sera transmis aux autres gestionnaires
  • requireAuth : indique s’il faut exiger un expĂ©diteur autorisĂ© (par dĂ©faut : true)
  • handler : fonction qui retourne { text: string } (peut ĂȘtre async)

Exemple avec autorisation et arguments :

api.registerCommand({
  name: "setmode",
  description: "Set plugin mode",
  acceptsArgs: true,
  requireAuth: true,
  handler: async (ctx) => {
    const mode = ctx.args?.trim() || "default";
    await saveMode(mode);
    return { text: `Mode set to: ${mode}` };
  },
});

Remarques :

  • Les commandes de plugin sont traitĂ©es avant les commandes intĂ©grĂ©es et l’agent IA
  • Les commandes sont enregistrĂ©es globalement et fonctionnent sur tous les canaux
  • Les noms de commande sont insensibles Ă  la casse (/MyStatus correspond Ă  /mystatus)
  • Les noms de commande doivent commencer par une lettre et ne contenir que des lettres, chiffres, tirets et underscores
  • Les noms de commande rĂ©servĂ©s (comme help, status, reset, etc.) ne peuvent pas ĂȘtre redĂ©finis par des plugins
  • L’enregistrement de commandes en double entre plugins Ă©chouera avec une erreur de diagnostic

Enregistrer des services en arriÚre-plan¶

export default function (api) {
  api.registerService({
    id: "my-service",
    start: () => api.logger.info("ready"),
    stop: () => api.logger.info("bye"),
  });
}

Conventions de nommage¶

  • MĂ©thodes de la Gateway (passerelle) : pluginId.action (exemple : voicecall.status)
  • Outils : snake_case (exemple : voice_call)
  • Commandes CLI : kebab ou camel, mais Ă©vitez les conflits avec les commandes du cƓur

Skills¶

Les plugins peuvent fournir un skill dans le dĂ©pĂŽt (skills/<name>/SKILL.md). Activez-le avec plugins.entries.<id>.enabled (ou d’autres verrous de configuration) et assurez-vous qu’il est prĂ©sent dans les emplacements de skills de votre espace de travail/skills gĂ©rĂ©s.

Distribution (npm)¶

Conditionnement recommandé :

  • Paquet principal : openclaw (ce dĂ©pĂŽt)
  • Plugins : paquets npm sĂ©parĂ©s sous @openclaw/* (exemple : @openclaw/voice-call)

Contrat de publication :

  • Le package.json du plugin doit inclure openclaw.extensions avec un ou plusieurs fichiers d’entrĂ©e.
  • Les fichiers d’entrĂ©e peuvent ĂȘtre .js ou .ts (jiti charge TS Ă  l’exĂ©cution).
  • openclaw plugins install <npm-spec> utilise npm pack, extrait dans ~/.openclaw/extensions/<id>/ et l’active dans la configuration.
  • StabilitĂ© des clĂ©s de configuration : les paquets scopĂ©s sont normalisĂ©s vers l’id non scopĂ© pour plugins.entries.*.

Exemple de plugin : Voice Call¶

Ce dĂ©pĂŽt inclut un plugin d’appel vocal (Twilio ou repli sur journalisation) :

  • Source : extensions/voice-call
  • Skill : skills/voice-call
  • CLI : openclaw voicecall start|status
  • Outil : voice_call
  • RPC : voicecall.start, voicecall.status
  • Configuration (twilio) : provider: "twilio" + twilio.accountSid/authToken/from (statusCallbackUrl, twimlUrl optionnels)
  • Configuration (dev) : provider: "log" (sans rĂ©seau)

Voir Voice Call et extensions/voice-call/README.md pour l’installation et l’utilisation.

Remarques de sécurité¶

Les plugins s’exĂ©cutent dans le mĂȘme processus que la Gateway (passerelle). Traitez-les comme du code de confiance :

  • N’installez que des plugins de confiance.
  • PrĂ©fĂ©rez les listes d’autorisation plugins.allow.
  • RedĂ©marrez la Gateway (passerelle) aprĂšs les modifications.

Tester les plugins¶

Les plugins peuvent (et doivent) fournir des tests :

  • Les plugins dans le dĂ©pĂŽt peuvent conserver des tests Vitest sous src/** (exemple : src/plugins/voice-call.plugin.test.ts).
  • Les plugins publiĂ©s sĂ©parĂ©ment doivent exĂ©cuter leur propre CI (lint/build/test) et valider que openclaw.extensions pointe vers le point d’entrĂ©e compilĂ© (dist/index.js).