Déployer zn-gate dans toute une équipe
Placez les hooks de zn-gate sur chaque machine grâce à la configuration gérée de chaque agent : paramètres gérés de Claude Code, hooks d'entreprise de Cursor et requirements.toml de Codex, et comment vérifier une machine.
Cette page s'adresse à la personne qui prépare les ordinateurs portables d'une équipe. Au lieu de demander à chaque développeur d'exécuter zn hooks install, vous placez un fichier de configuration par agent dans un dossier système, avec votre propre outil pour cela (gestion des appareils, Ansible, une image, un script d'ouverture de session). L'agent exécute alors les hooks de zn-gate pour tout le monde et, pour Claude Code et Codex, vous pouvez aussi empêcher les utilisateurs et les projets de les désactiver.
zn-gate ne déploie pas ces fichiers à votre place : c'est un garde-fou local, pas un MDM (voir la Vue d'ensemble de Team). Tout ce qui suit fonctionne dès aujourd'hui à la main.
Les informations sur chaque agent proviennent de la documentation propre à cet agent, lue le 2026-10-19 ; relisez-la avant un déploiement important, car ces paramètres évoluent. Les commandes des hooks sont celles que zn hooks install écrit pour une installation de projet avec zn-gate 1.12.0 ou plus récent.
Avant de commencer
- Installez zn-gate sur chaque machine, avec la même version partout. Il nécessite Node.js 18 ou plus récent :
npm install -g zn-gate. Faites-le d'abord. Un hook qui ne peut pas s'exécuter n'est pas anodin : Claude Code et Codex laissent passer l'appel d'outil sans contrôle, et Cursor bloque les lectures de fichiers et les prompts lorsqu'un hook afailClosed. - Vérifiez que l'agent trouve
zn. Les commandes ci-dessous appellentzn hook <agent>, donczndoit se trouver dans le PATH avec lequel l'agent s'exécute. Les applications de bureau ne reçoivent pas toujours le PATH de votre terminal. En cas de doute, écrivez le chemin complet (command -v znsous macOS et Linux,where znsous Windows), par exemple/usr/local/bin/zn hook claude-code. - Essayez sur une machine, vérifiez-la (voir « Vérifier une machine » plus bas), puis déployez sur le reste.
Claude Code
Claude Code lit ses paramètres gérés dans un dossier système :
| Système | Dossier |
|---|---|
| macOS | /Library/Application Support/ClaudeCode/ |
| Linux et WSL | /etc/claude-code/ |
| Windows | C:\Program Files\ClaudeCode\ |
Le dossier contient managed-settings.json, un dossier facultatif managed-settings.d/ de fichiers *.json, et managed-mcp.json. Claude Code fusionne d'abord managed-settings.json, puis les fichiers de managed-settings.d/ par ordre alphabétique, et réunit les listes de hooks de tous les fichiers. Vous pouvez ainsi garder les hooks de zn-gate dans leur propre fichier, par exemple managed-settings.d/50-zn-gate.json, à côté de la politique dont d'autres équipes ont la charge.
Hooks et allowManagedHooksOnly
{
"allowManagedHooksOnly": true,
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|PowerShell|Monitor|Read|Grep|LSP|Edit|MultiEdit|Write|NotebookEdit|WebFetch",
"hooks": [{ "type": "command", "command": "zn hook claude-code", "timeout": 15 }]
}
],
"PostToolUse": [
{
"matcher": "^(Bash|PowerShell|Monitor|Read|Grep|LSP|WebFetch|ReadMcpResourceTool)$|^mcp__.*",
"hooks": [{ "type": "command", "command": "zn hook claude-code", "timeout": 15 }]
}
],
"UserPromptSubmit": [
{
"hooks": [{ "type": "command", "command": "zn hook claude-code", "timeout": 15, "onFailure": "block" }]
}
]
}
}
"onFailure": "block" fait bloquer un prompt par Claude Code lorsque le hook ne peut pas démarrer. Cela nécessite Claude Code 2.1.295 ou plus récent ; les versions antérieures ignorent le champ.
À partir de zn-gate 1.13.0, zn-gate contrôle aussi ce en quoi se développe une skill ou une commande saisie. Pour cela, ajoutez cette entrée sous hooks : "UserPromptExpansion": [{ "hooks": [{ "type": "command", "command": "zn hook claude-code", "timeout": 15, "onFailure": "block" }] }].
Ce que fait allowManagedHooksOnly. Avec true, Claude Code n'exécute que les hooks issus des paramètres gérés (plus les hooks que l'Agent SDK enregistre et ceux des plugins que vos paramètres gérés activent d'office). Il bloque tout le reste : les hooks du ~/.claude/settings.json d'un utilisateur, du .claude/settings.json et du .claude/settings.local.json d'un projet, des autres plugins et du frontmatter des agents. Il a des effets de bord : la commande /goal cesse de fonctionner, et une ligne d'état personnalisée doit provenir des paramètres gérés. Décidez-le en connaissance de cause et prévenez vos développeurs.
Le paramètre ne protège zn-gate que si les hooks de zn-gate figurent dans les paramètres gérés. Si vous activez allowManagedHooksOnly sans eux, les hooks qu'un développeur installe avec zn hooks install claude-code ou avec le plugin zn-gate cessent de s'exécuter, et Claude Code n'affiche aucun message. zn-gate le signale au développeur dans zn hooks install claude-code et zn-gate status, et reste silencieux lorsque les fichiers gérés contiennent les hooks de zn-gate.
Gardez aussi en tête :
disableAllHooks: truedans les paramètres gérés désactive tous les hooks, les vôtres compris. Laissez-le non défini.- Si vous distribuez la politique de plusieurs façons (paramètres gérés par le serveur, gestion des appareils, registre Windows et fichiers), Claude Code utilise par défaut la source de plus haut rang qui définit une politique et ignore les autres : un fichier peut donc être ignoré. Placez les hooks de zn-gate dans la source que Claude Code utilise sur cette machine.
/statusl'affiche sur la ligneSetting sources. zn-gate ne lit que les fichiers.
Serveurs MCP (facultatif)
Ce sont les hooks qui protègent l'agent. Si vous souhaitez aussi que les développeurs utilisent le serveur MCP secrets de zn-gate (il permet à l'agent d'utiliser un secret conservé dans le coffre de zn sans le voir), ce sont les règles MCP gérées qui décident s'il peut démarrer. Attention : un fichier managed-mcp.json prend le contrôle exclusif. Dès qu'il existe, Claude Code ne charge que les serveurs de ce fichier (et quelques serveurs intégrés), et les utilisateurs ne peuvent en ajouter aucun autre. Listez tous les serveurs dont votre équipe a besoin, pas seulement celui de zn-gate. Avec un objet mcpServers vide, aucun serveur n'est chargé.
managed-mcp.json utilise le même format qu'un .mcp.json de projet :
{
"mcpServers": {
"secrets": {
"type": "stdio",
"command": "zn",
"args": ["secrets-mcp", "--agent", "claude-code"]
}
}
}
Si vous ne voulez pas du contrôle exclusif, utilisez plutôt les listes d'autorisation allowedMcpServers et allowManagedMcpServersOnly dans les paramètres gérés, et ajoutez le serveur secrets à la liste. Voir la configuration MCP gérée de Claude Code. zn-gate status prévient le développeur lorsqu'un fichier ou une liste gérée empêche le démarrage du serveur secrets.
Cursor
Cursor lit les hooks d'entreprise dans un hooks.json système :
| Système | Fichier |
|---|---|
| macOS | /Library/Application Support/Cursor/hooks.json |
| Linux et WSL | /etc/cursor/hooks.json |
| Windows | C:\ProgramData\Cursor\hooks.json |
{
"version": 1,
"hooks": {
"beforeMCPExecution": [{ "command": "zn hook cursor", "timeout": 30 }],
"beforeReadFile": [{ "command": "zn hook cursor", "timeout": 30, "failClosed": true }],
"beforeShellExecution": [{ "command": "zn hook cursor", "timeout": 30 }],
"beforeSubmitPrompt": [{ "command": "zn hook cursor", "timeout": 30, "failClosed": true }],
"postToolUse": [{ "command": "zn hook cursor", "timeout": 30 }],
"preToolUse": [{ "command": "zn hook cursor", "timeout": 30, "matcher": "Grep|Write|Delete" }]
}
}
C'est le même ensemble de hooks que zn hooks install cursor, avec failClosed sur les deux hooks qui lisent les fichiers et les prompts. Avec failClosed: true, un plantage, un délai dépassé ou l'absence de réponse du hook bloque l'action au lieu de la laisser passer. C'est pourquoi zn-gate doit être installé d'abord : sur une machine sans zn, Cursor bloquerait les lectures de fichiers et les prompts.
Ce que fait Cursor avec plusieurs sources : il exécute les hooks de chaque hooks.json (entreprise, équipe, projet et utilisateur), l'entreprise étant prioritaire, et un deny de l'un d'eux l'emporte. Les hooks propres à un développeur continuent donc de s'exécuter à côté des vôtres. La documentation de Cursor (lue le 2026-10-19) ne décrit aucun paramètre qui fasse n'exécuter que les hooks d'entreprise ; zn-gate ne peut donc pas être rendu obligatoire dans Cursor comme dans Claude Code et Codex. l'offre enterprise de Cursor peut aussi distribuer des hooks depuis son tableau de bord web ; cette page ne traite que du fichier.
zn-gate ne couvre pas la ligne de commande de Cursor (cursor-agent).
Codex CLI
Codex lit les exigences de l'administrateur dans un requirements.toml système :
| Système | Fichier |
|---|---|
| macOS et Linux | /etc/codex/requirements.toml |
| Windows | %ProgramData%\OpenAI\Codex\requirements.toml |
Sous macOS, la gestion des appareils peut aussi fournir le même contenu sous la forme requirements_toml_base64 dans le domaine com.openai.codex. Voir la configuration gérée d'OpenAI.
allow_managed_hooks_only = true
[features]
hooks = true
[hooks]
managed_dir = "/opt/example-managed-hooks"
windows_managed_dir = 'C:\ProgramData\ExampleCorp\managed-hooks'
[[hooks.PreToolUse]]
matcher = "^(Bash|apply_patch)$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = "zn hook codex"
command_windows = "zn hook codex"
timeout = 30
statusMessage = "zn: checking for secrets"
[[hooks.PostToolUse]]
matcher = ".*"
[[hooks.PostToolUse.hooks]]
type = "command"
command = "zn hook codex"
command_windows = "zn hook codex"
timeout = 30
statusMessage = "zn: checking for secrets"
[[hooks.UserPromptSubmit]]
[[hooks.UserPromptSubmit.hooks]]
type = "command"
command = "zn hook codex"
command_windows = "zn hook codex"
timeout = 30
statusMessage = "zn: checking for secrets"
Ce que font les clés, d'après la documentation de Codex :
allow_managed_hooks_only = truefait ignorer à Codex les hooks des utilisateurs, des projets, des sessions et des plugins, et ne charger que les hooks gérés.[features] hooks = truemaintient les hooks activés même pour un utilisateur qui les a désactivés dans son propreconfig.toml.managed_diretwindows_managed_dirdoivent être des chemins absolus de dossiers existants, sinon Codex ne charge pas les hooks gérés. zn-gate n'a besoin d'aucun script dedans : un dossier vide que vous créez suffit.- Les hooks gérés sont considérés comme approuvés par la politique : contrairement aux hooks qu'un développeur installe, ils n'exigent pas la revue dans
/hooks, et l'utilisateur ne peut pas les y désactiver.
Si le hook ne peut pas démarrer, Codex laisse passer l'appel (et le prompt) ; la même règle s'applique donc : installez d'abord zn-gate.
Vérifier une machine
zn-gate check en version 1.12.0 lit la configuration propre à chaque utilisateur, pas les fichiers gérés. Sur une machine où zn-gate n'est déployé que par la configuration gérée, il affiche « zn is not set up for this agent », même si les hooks gérés fonctionnent. Ne le prenez pas pour un échec de votre déploiement. Utilisez plutôt ces vérifications.
-
Demandez à l'agent quels paramètres il utilise.
- Claude Code : exécutez
/statuset lisez la ligneSetting sources. Elle doit mentionner les paramètres gérés d'entreprise (pour les fichiers, « file »).claude doctorliste ce que Claude Code a écarté. - Cursor : ouvrez l'onglet Hooks dans Customize, ainsi que le canal de sortie Hooks pour voir les hooks exécutés et les erreurs éventuelles.
- Codex : exécutez
/hooks. Les hooks gérés sont marqués comme gérés.
- Claude Code : exécutez
-
Exécutez
zn-gate statussur une machine avec Claude Code. Il signale, en une ligne, un paramètre géré qui empêche les hooks de zn-gate ou son serveursecrets(disableAllHooks,allowManagedHooksOnlysans les hooks de zn-gate,managed-mcp.jsonsans le serveur, une liste d'autorisation ou de blocage MCP). Pas de ligne signifie qu'il n'en a trouvé aucun dans les fichiers ; il ne voit pas une politique fournie par les paramètres gérés par le serveur, la gestion des appareils ou le registre. -
Testez la commande du hook elle-même. Sous macOS ou Linux, dans un dossier vide, créez un fichier
.envde test avec une fausse clé et demandez au hook de le lire, comme le fait l'agent :printf 'ZN_CHECK_EXAMPLE_KEY=zn-check-fake-value-not-a-real-key\n' > .env printf '{"hook_event_name":"PreToolUse","session_id":"test","cwd":"%s","tool_name":"Read","tool_input":{"file_path":"%s/.env"}}' "$PWD" "$PWD" | zn hook claude-codeLa réponse doit contenir
"permissionDecision":"deny". Pour un fichier ordinaire commeREADME.txt, elle ne doit pas la contenir. Le même test pour Codex est un appelBashavec"command":"cat .env"envoyé àzn hook codex; pour Cursor, c'est{"hook_event_name":"beforeReadFile","cwd":"…","file_path":"…/.env","content":"x","workspace_roots":["…"]}envoyé àzn hook cursor, qui répond"permission":"deny". Cela prouve que la commande que vous avez écrite démarre et que les règles de zn bloquent le fichier. Cela ne prouve pas que l'agent l'appelle : ce sont les étapes 1 et 2 qui le montrent. -
Voyez-le de bout en bout. Dans un dossier jetable qui ne contient que le faux
.envci-dessus, demandez à l'agent de le lire. Il doit être refusé avec un message qui commence parzn:.
Le maintenir en état de marche
- Mettez à jour toutes les machines ensemble. Installez la même version de zn-gate partout et ne modifiez les fichiers gérés que pour les aligner sur ce dont cette version a besoin ; le changelog indique quand les entrées de hooks changent (par exemple, la 1.13.0 ajoute une entrée pour Claude Code).
- Rejoignez l'organisation. Les hooks gérés exécutent les contrôles ; la politique de l'organisation et la piste d'audit exigent que chaque machine rejoigne l'organisation avec
zn team join. Voir Rejoindre une machine et Politique de l'organisation. - Pour retirer zn-gate, supprimez les entrées des fichiers gérés ;
zn hooks uninstallne retire que ce qu'il a écrit lui-même.
Ce que cette page ne couvre pas
OpenCode, et les agents que zn-gate ne prend pas encore en charge (voir Documentation pour agents IA). Les fichiers Cursor et Codex n'ont pas été testés sous Windows. Écrivez-nous à support@usezn.com si quelque chose ici ne correspond pas à ce que vous voyez.