Implante o zn-gate em uma equipe inteira

Coloque os hooks do zn-gate em cada máquina pela configuração gerenciada de cada agente: configurações gerenciadas do Claude Code, hooks corporativos do Cursor e requirements.toml do Codex, e como verificar uma máquina.

Ver .md

Esta página é para quem prepara os notebooks de uma equipe. Em vez de pedir a cada desenvolvedor que rode zn hooks install, você coloca um arquivo de configuração por agente em uma pasta do sistema, com a sua própria ferramenta para isso (gerenciamento de dispositivos, Ansible, uma imagem, um script de login). O agente passa então a rodar os hooks do zn-gate para todos e, no Claude Code e no Codex, você também pode impedir que usuários e projetos os desativem.

O zn-gate não implanta esses arquivos por você: ele é uma proteção local, não um MDM (veja a Visão geral de Team). Tudo o que segue funciona hoje, manualmente.

Os fatos sobre cada agente vêm da documentação do próprio agente, lida em 2026-10-19; consulte-a de novo antes de uma implantação grande, porque essas configurações mudam. Os comandos dos hooks são os que zn hooks install escreve em uma instalação de projeto no zn-gate 1.12.0 ou posterior.

Antes de começar

  1. Instale o zn-gate em cada máquina, na mesma versão em todas. Ele exige Node.js 18 ou posterior: npm install -g zn-gate. Faça isso primeiro. Um hook que não consegue rodar não é inofensivo: o Claude Code e o Codex deixam a chamada da ferramenta seguir sem verificação, e o Cursor bloqueia leituras de arquivos e prompts quando um hook tem failClosed.
  2. Garanta que o agente encontre o zn. Os comandos abaixo chamam zn hook <agent>, então o zn precisa estar no PATH com o qual o agente roda. Aplicativos de desktop nem sempre recebem o PATH do seu terminal. Se tiver dúvida, escreva o caminho completo (command -v zn no macOS e no Linux, where zn no Windows), por exemplo /usr/local/bin/zn hook claude-code.
  3. Teste em uma máquina, verifique-a (veja "Verificar uma máquina" abaixo) e depois implante nas demais.

Claude Code

O Claude Code lê as configurações gerenciadas de uma pasta do sistema:

Sistema Pasta
macOS /Library/Application Support/ClaudeCode/
Linux e WSL /etc/claude-code/
Windows C:\Program Files\ClaudeCode\

A pasta contém managed-settings.json, uma pasta opcional managed-settings.d/ com arquivos *.json e managed-mcp.json. O Claude Code combina primeiro o managed-settings.json e depois os arquivos de managed-settings.d/ em ordem alfabética, e junta as listas de hooks de todos os arquivos. Assim você pode manter os hooks do zn-gate em um arquivo próprio, por exemplo managed-settings.d/50-zn-gate.json, ao lado da política de que outras equipes cuidam.

Hooks e 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" faz o Claude Code bloquear um prompt quando o hook não consegue iniciar. Exige o Claude Code 2.1.295 ou posterior; versões anteriores ignoram o campo.

A partir do zn-gate 1.13.0, o zn-gate também verifica no que se expande uma skill ou um comando digitado. Para isso, adicione esta entrada em hooks: "UserPromptExpansion": [{ "hooks": [{ "type": "command", "command": "zn hook claude-code", "timeout": 15, "onFailure": "block" }] }].

O que o allowManagedHooksOnly faz. Com true, o Claude Code roda apenas os hooks que vêm das configurações gerenciadas (mais os hooks que o Agent SDK registra e os de plugins que suas configurações gerenciadas ativam à força). Ele bloqueia todo o resto: os hooks do ~/.claude/settings.json de um usuário, do .claude/settings.json e do .claude/settings.local.json de um projeto, de outros plugins e do frontmatter de agentes. Há efeitos colaterais: o comando /goal deixa de funcionar e uma linha de status personalizada precisa vir das configurações gerenciadas. Decida de propósito e avise seus desenvolvedores.

A configuração protege o zn-gate somente se os hooks do zn-gate estiverem nas configurações gerenciadas. Se você ativar allowManagedHooksOnly sem eles, os hooks que um desenvolvedor instala com zn hooks install claude-code ou com o plugin do zn-gate deixam de rodar, e o Claude Code não mostra nenhuma mensagem. O zn-gate avisa o desenvolvedor em zn hooks install claude-code e zn-gate status, e fica em silêncio quando os arquivos gerenciados contêm os hooks do zn-gate.

Lembre-se também:

  • disableAllHooks: true nas configurações gerenciadas desativa todos os hooks, inclusive os seus. Deixe-o sem definir.
  • Se você entrega a política de mais de uma forma (configurações gerenciadas pelo servidor, gerenciamento de dispositivos, registro do Windows e arquivos), o Claude Code usa por padrão a fonte de maior prioridade que define uma política e ignora as outras, então um arquivo pode ser ignorado. Coloque os hooks do zn-gate na fonte que o Claude Code usa naquela máquina. O /status a mostra na linha Setting sources. O zn-gate lê apenas os arquivos.

Servidores MCP (opcional)

Os hooks é que protegem o agente. Se você também quer que os desenvolvedores usem o servidor MCP secrets do zn-gate (ele permite que o agente use um segredo guardado no cofre do zn sem vê-lo), as regras de MCP gerenciado decidem se ele pode iniciar. Cuidado: um arquivo managed-mcp.json assume o controle exclusivo. Assim que ele existe, o Claude Code carrega apenas os servidores desse arquivo (e alguns embutidos), e os usuários não podem adicionar nenhum outro. Liste todos os servidores de que sua equipe precisa, não só o do zn-gate. Com um objeto mcpServers vazio, nenhum servidor é carregado.

O managed-mcp.json usa o mesmo formato de um .mcp.json de projeto:

{
  "mcpServers": {
    "secrets": {
      "type": "stdio",
      "command": "zn",
      "args": ["secrets-mcp", "--agent", "claude-code"]
    }
  }
}

Se você não quer o controle exclusivo, use em vez disso as listas de permissão allowedMcpServers e allowManagedMcpServersOnly nas configurações gerenciadas, e adicione o servidor secrets à lista. Veja a configuração de MCP gerenciado do Claude Code. O zn-gate status avisa o desenvolvedor quando um arquivo ou uma lista gerenciada impede o servidor secrets de iniciar.

Cursor

O Cursor lê os hooks corporativos de um hooks.json do sistema:

Sistema Arquivo
macOS /Library/Application Support/Cursor/hooks.json
Linux e 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" }]
  }
}

É o mesmo conjunto de hooks do zn hooks install cursor, com failClosed nos dois hooks que leem arquivos e prompts. Com failClosed: true, uma falha, um tempo esgotado ou a ausência de resposta do hook bloqueia a ação em vez de deixá-la passar. Por isso o zn-gate precisa estar instalado antes: em uma máquina sem o zn, o Cursor bloquearia leituras de arquivos e prompts.

O que o Cursor faz com várias fontes: ele roda os hooks de cada hooks.json (empresa, equipe, projeto e usuário), com prioridade para o da empresa, e um deny de qualquer um deles prevalece. Assim, os hooks próprios de um desenvolvedor continuam rodando ao lado dos seus. A documentação do Cursor (lida em 2026-10-19) não descreve nenhuma configuração que faça rodar apenas os hooks corporativos, então no Cursor o zn-gate não pode ser tornado obrigatório como no Claude Code e no Codex. O plano enterprise do Cursor também pode distribuir hooks pelo painel web; esta página cobre apenas o arquivo.

O zn-gate não cobre a linha de comando do Cursor (cursor-agent).

Codex CLI

O Codex lê os requisitos do administrador de um requirements.toml do sistema:

Sistema Arquivo
macOS e Linux /etc/codex/requirements.toml
Windows %ProgramData%\OpenAI\Codex\requirements.toml

No macOS, o gerenciamento de dispositivos também pode entregar o mesmo conteúdo como requirements_toml_base64 no domínio com.openai.codex. Veja a configuração gerenciada da 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"

O que as chaves fazem, segundo a documentação do Codex:

  • allow_managed_hooks_only = true faz o Codex ignorar os hooks de usuários, projetos, sessões e plugins, e carregar apenas os hooks gerenciados.
  • [features] hooks = true mantém os hooks ativados mesmo para um usuário que os desativou no próprio config.toml.
  • managed_dir e windows_managed_dir devem ser caminhos absolutos de pastas que existam, ou o Codex não carrega os hooks gerenciados. O zn-gate não precisa de nenhum script nelas, então basta uma pasta vazia que você mesmo crie.
  • Os hooks gerenciados contam como confiáveis por política: ao contrário dos hooks que um desenvolvedor instala, eles não exigem a revisão em /hooks, e o usuário não pode desativá-los lá.

Se o hook não consegue iniciar, o Codex deixa a chamada (e o prompt) seguir, então vale a mesma regra: instale o zn-gate primeiro.

Verificar uma máquina

O zn-gate check na versão 1.12.0 lê a configuração própria de cada usuário, não os arquivos gerenciados. Em uma máquina em que o zn-gate é implantado apenas pela configuração gerenciada, ele diz "zn is not set up for this agent", mesmo que os hooks gerenciados funcionem. Não trate isso como uma falha da sua implantação. Use estas verificações no lugar.

  1. Pergunte ao agente quais configurações ele usa.

    • Claude Code: rode /status e leia a linha Setting sources. Ela deve listar as configurações gerenciadas da empresa (para arquivos, "file"). O claude doctor lista o que o Claude Code descartou.
    • Cursor: abra a aba Hooks em Customize e o canal de saída Hooks para ver os hooks que rodaram e eventuais erros.
    • Codex: rode /hooks. Os hooks gerenciados aparecem marcados como gerenciados.
  2. Rode zn-gate status em uma máquina com Claude Code. Ele informa, em uma linha, uma configuração gerenciada que impede os hooks do zn-gate ou seu servidor secrets (disableAllHooks, allowManagedHooksOnly sem os hooks do zn-gate, managed-mcp.json sem o servidor, uma lista de permissão ou de bloqueio de MCP). Nenhuma linha significa que ele não encontrou nenhuma nos arquivos; ele não vê a política que chega por configurações gerenciadas pelo servidor, gerenciamento de dispositivos ou registro.

  3. Teste o próprio comando do hook. No macOS ou Linux, em uma pasta vazia, crie um arquivo .env de teste com uma chave falsa e peça ao hook que o leia, como o agente faz:

    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-code

    A resposta deve conter "permissionDecision":"deny". Para um arquivo comum como README.txt, não deve conter. O mesmo teste para o Codex é uma chamada Bash com "command":"cat .env" enviada ao zn hook codex; para o Cursor, é {"hook_event_name":"beforeReadFile","cwd":"…","file_path":"…/.env","content":"x","workspace_roots":["…"]} enviado ao zn hook cursor, que responde "permission":"deny". Isso prova que o comando que você escreveu inicia e que as regras do zn bloqueiam o arquivo. Não prova que o agente o chama: isso é o que os passos 1 e 2 mostram.

  4. Veja de ponta a ponta. Em uma pasta descartável que contenha apenas o .env falso acima, peça ao agente que o leia. Ele deve ser recusado com uma mensagem que começa com zn:.

Mantendo tudo funcionando

  • Atualize todas as máquinas juntas. Instale a mesma versão do zn-gate em todas e altere os arquivos gerenciados apenas para acompanhar o que essa versão precisa; o changelog informa quando as entradas de hooks mudam (por exemplo, a 1.13.0 adiciona uma entrada para o Claude Code).
  • Entre na organização. Os hooks gerenciados executam as verificações; a política da organização e a trilha de auditoria exigem que cada máquina entre com zn team join. Veja Conectar uma máquina e Política da organização.
  • Para remover o zn-gate, apague as entradas dos arquivos gerenciados; o zn hooks uninstall remove apenas o que ele mesmo escreveu.

O que esta página não cobre

O OpenCode e os agentes que o zn-gate ainda não suporta (veja Documentação para agentes de IA). Os arquivos do Cursor e do Codex não foram testados no Windows. Escreva para support@usezn.com se algo aqui não corresponder ao que você vê.