Construire Switchboard
Comment Switchboard décide ce qu’un plugin peut faire
Un manifeste, un aperçu de confiance, un interrupteur par commande et un journal d’audit : les quatre barrières entre un agent et les apps de votre Mac.


Switchboard est un daemon local et une CLI. Un agent lance switchboard <plugin> <commande> comme n’importe quel autre outil en ligne de commande et découvre ce qui existe avec --help. Les plugins sont du JavaScript en bac à sable, un isolat par plugin, exécuté dans le daemon sur votre Mac. La question qui compte est donc ce qu’un plugin a le droit de faire, et la réponse se décide à quatre endroits.
1. Le manifeste
Chaque plugin livre un manifest.json à côté de son dist/plugin.js empaqueté. Il nomme le plugin, les plateformes où il tourne, les capabilities que son code appelle et les noms d’hôte network qu’il peut interroger. Le plugin de référence, echo, déclare emit, storage et timers, et une liste réseau vide.
Le daemon applique le manifeste à la frontière de l’API hôte. Un plugin qui appelle host.fetch sans la capacité fetch échoue à l’exécution. Une liste network vide signifie que fetch est refusé partout, même si la capacité est déclarée. Une entrée couvre cet hôte et ses sous-domaines, la liste est revérifiée à chaque redirection, et les requêtes vers les adresses locales, de lien local et privées sont refusées sauf si l’adresse exacte est déclarée, ce qui la fait apparaître dans l’aperçu de confiance.
Les capacités qui touchent le système d’exploitation ou une autre app (imessage, mail, slack, calendar, macos, applescript, screencapture, mcp, bridge, entre autres) n’existent que dans le noyau Go. Un plugin ne peut pas embarquer son propre client de protocole pour elles; il déclare la capacité et passe par l’hôte.
2. L’aperçu de confiance
switchboard install <nom> prend un plugin dans le registre. L’index du registre est signé en ed25519, et un index non signé ou altéré est refusé. Le SHA-256 du paquet est vérifié contre l’entrée de l’index. L’installation affiche ensuite un aperçu de confiance, les capacités et les accès réseau déclarés, et attend une confirmation. Un chemin local passe par la même barrière. Un plugin qui ne prend pas en charge votre système est refusé d’emblée, avec la liste des plateformes qu’il prend en charge.
Le registre comptait 22 plugins au 20 août 2026, dont Mail, Messages, Calendrier, Keynote, Safari, Slack, Discord, WhatsApp, Figma, Asana, Trello et Hetzner Cloud. Les plugins qui utilisent une capacité hôte ou un serveur MCP s’installent désactivés : rien ne tourne avant que vous les activiez.
3. La politique par commande
Chaque commande d’un plugin porte un indicateur write : modifie-t-elle un état externe ou pose-t-elle une action vers l’extérieur. Pour les outils relayés depuis le serveur MCP d’une app, une annotation readOnlyHint retire l’indicateur; tout le reste compte comme une écriture, ce qui est la valeur sûre par défaut.
La politique se règle par instance de plugin et se conserve dans policy.json, dans le répertoire d’état du daemon. Vous pouvez désactiver une seule commande, dans l’app, dans l’interface web ou avec switchboard policy disable <plugin> <commande>; le daemon refuse alors cette invocation au lieu de simplement la cacher. switchboard policy readonly <plugin> bloque d’un coup toutes les commandes d’écriture. switchboard policy cap-disable <plugin> <capacité> coupe une capacité entière pour cette instance (accès réseau, identifiants enregistrés, ou une intégration hôte comme Slack ou le contrôle du Mac), et chaque appel host.<cap> que le plugin tente lève une erreur.

4. Les secrets et le journal d’audit
Les identifiants d’un plugin se conservent par plugin avec switchboard secrets set <plugin> <clé>; la valeur est lue sur l’entrée standard. Sur macOS, la valeur va dans votre trousseau de session par la CLI security, et seuls les noms de clés sont indexés sur disque. Un plugin lit ses propres secrets avec host.secrets.get, dans son espace de noms, et chaque lecture est consignée. Sur les autres plateformes, ou avec SWITCHBOARD_SECRETS_BACKEND=file, les valeurs tombent dans un fichier en chmod 0600 qui n’est pas chiffré au repos, et le daemon le dit au démarrage.
Le journal d’audit consigne chaque invocation de plugin, chaque exécution de flux ou de règle, y compris les sauts et leur raison, et chaque accès aux secrets : ce qui a tourné, qui l’a déclenché, si ça a réussi et combien de temps ça a pris. Les valeurs des secrets n’y apparaissent jamais. switchboard audit l’affiche, du plus récent au plus ancien.
Ce que cela ne couvre pas
- Le daemon écoute sur un socket unix et sur
127.0.0.1:7378. Il n’atteint le réseau que si vous lancezswitchboard server enable, qui écoute sur0.0.0.0:7378derrière un jeton. - Les permissions que macOS gère lui-même, comme l’accès complet au disque pour les bases de Messages et de Mail, l’automatisation, l’accessibilité, les calendriers et l’enregistrement de l’écran, sont les invites du système. Switchboard les demande quand un plugin en a besoin.
- Les autorisations entre Mac jumelés sont sur la branche principale, mais pas dans la version publiée.
- Les étapes d’agent dans les flux et la génération de plugins passent par Claude Code, Codex, Kimi Code ou Grok. Tout agent capable de lancer une commande shell peut appeler la CLI.
- Les plugins WhatsApp et Discord pilotent des sessions non officielles; le README énonce le risque pour le compte avant le jumelage.
Switchboard exige macOS 26 ou plus récent.



