zn-gate for Copilot CLI

Install zn's experimental hooks for GitHub Copilot CLI: they block reads and writes of secret files and shell commands that handle secrets, and replace secret values in tool results.

View .md

Copilot CLI support is experimental. Treat it as a first layer: it cannot block a secret that you paste into a prompt, and Copilot lets a call go ahead if a hook is too slow (see Limits below).

You need Node.js 18 or later. Paste each line in a terminal and press Enter after each one:

npm install -g zn-gate
zn hooks install copilot

On macOS and Linux, if npm install -g fails with EACCES, follow npm's guide to fixing permission errors.

Fix it without administrator rights:

mkdir -p ~/.npm-global && npm config set prefix ~/.npm-global
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc

Bash users: write to ~/.bashrc instead of ~/.zshrc.

Then open a new terminal and run npx -y zn-gate init. A Node.js version manager such as nvm also avoids the problem.

Then open a new Copilot CLI session. zn writes its own file, zn-gate.json, in ~/.copilot/hooks/ (or in $COPILOT_HOME/hooks/ if you set a custom Copilot folder) and only edits what it wrote there. Updating later? See Upgrading zn-gate.

For one project only

Run zn hooks install copilot --project inside the project. It writes .github/hooks/zn-gate.json in that project instead of your home folder. The hook runs zn from your PATH, so everyone who opens the project in Copilot CLI needs zn-gate installed, otherwise the hook cannot start. Copilot also asks each person to trust the folder before it runs hooks from a repository.

What you get

  • zn checks every tool call before it runs.
  • Reads and writes of secret files, such as .env files with values, are blocked by file path.
  • Shell commands that handle secrets are blocked. For a command that uses a __ZN_<NAME>__ marker, zn blocks it and tells the model the exact zn run -- ... line to use instead.
  • The agent cannot edit Copilot's own hook and settings files.
  • After a read-type or shell tool runs, zn replaces secret values in a successful result before the model sees it.
  • When a check needs your decision, zn asks you to confirm. Where nobody can answer, in Copilot's cloud agent and in autopilot, Copilot turns that question into a block.
  • zn never approves a call for you. When it has no objection, Copilot's own permission rules apply.

Limits

  • A secret pasted into a typed prompt is not stopped. Copilot does not let a hook block a typed prompt.
  • Copilot lets the call go ahead when a hook takes too long. Copilot waits 30 seconds by default, and zn sets 15 seconds on its hooks. zn also answers with a block when its own check has not finished at 11 seconds.
  • Copilot's own log keeps the original output. The session log (events.jsonl) on your machine holds the tool output before zn replaced anything. zn cleans what goes to the model, not that file.
  • Machine policy hooks run as well. Copilot also loads hook files from /etc/github-copilot/policy.d, which zn cannot see.
  • Some tools may go unchecked. zn cannot always recognise an MCP tool, so its calls may not be checked and its output is not cleaned.
  • Settings can switch the hooks off. "disableAllHooks": true in zn's file, or in the repository's .github/copilot/settings.json or settings.local.json, turns them off. zn-gate check reports it.
  • It has not been tested on Windows.
  • zn was checked against Copilot CLI 1.0.98 with a scripted model, not with every version.

Check that it works

In a new terminal, run zn-gate check. It should show OK for Copilot CLI (experimental). What the output means.

On Windows PowerShell, if npm says "running scripts is disabled on this system", use npm.cmd and zn.cmd instead: see Install.

Remove it

Run zn hooks uninstall copilot in your own terminal (add --project for a project install).