Generated from
compatibility/copilot.json,
the same record leastgrant doctor reads. Last verified 2026-09-01.
GitHub Copilot CLI
the real agent ran with LeastGrant installed and enforcement was observed happening.
How it attaches
A Claude-format hook file at ~/.copilot/hooks/leastgrant.json. Copilot speaks Claude Code's wire format, so the same handler drives both.
Install it with leastgrant install copilot. Configuration is written to
~/.copilot/hooks/leastgrant.json, alongside anything
already there — LeastGrant never removes a hook it did not add.
What a verdict does here
The three verdicts do not travel equally well. This is the table that decides whether LeastGrant is a prompt, a veto, or a suggestion on this agent.
| verdict | lands? | what actually happens |
|---|---|---|
| allow | yesprobe | |
| ask | degradesprobe | Honoured interactively. A non-interactive run (copilot -p) has nobody to ask and Copilot turns an ask into a deny — its choice, not LeastGrant's, and the safe direction. |
| deny | yesprobe |
Interactive and unattended
This agent does not tell the hook which mode it is in, so LeastGrant cannot distinguish an attended session from an unattended one and treats every session as unattended.
When the hook breaks
The question nobody asks until it matters: if LeastGrant crashes, times out, or cannot start, does the tool call still run?
- On crash — the call is refused. (probe) The only agent here that fails closed: if the hook errors, Copilot denies the call rather than running it. Discovered the hard way — a broken hook command blocked everything.
- On timeout — not established, after unknowns by default.
- Can it be made to fail closed? — yes. It is the default and is not optional.
What it can see
A verdict is only worth as much as the set of actions it is asked about. gated means LeastGrant is consulted before the thing happens; seen after means it is told afterwards and can at best withhold the result; not covered means the action happens with LeastGrant never hearing about it.
| tool class | coverage | detail |
|---|---|---|
| shell commands | gatedprobe | |
| file reads | gatedprobe | |
| file writes | gatedprobe | |
| deletions | unknownunknown | |
| MCP calls | unknownunknown | |
| subagent spawn | unknownunknown | |
| network / web | unknownunknown |
What has actually been run
Four different things, deliberately not collapsed into one badge. Reproducing an agent's invocation is not running the agent; a passing conformance suite says our side is right and nothing about whether the host ever calls us.
- Live agent test — Real `copilot -p` runs with the hook installed at ~/.copilot/hooks/leastgrant.json; all three verdicts honoured, and a hook error observed failing closed. 1.0.82 · win32 · 2026-09-02
- Real transport probed — Copilot runs hook commands through PowerShell on Windows; the same quoting failure as Codex was observed, there blocking every call rather than none. 1.0.82 · win32 · 2026-09-02
- Contract read from the shipped build — Claude-format hooks in snake_case with hookSpecificOutput out; confirmed against the installed CLI. 1.0.82 · win32 · 2026-09-02
- Conformance suite — Driven by test/conformance.test.ts. 1.0.82 · win32 · 2026-09-02
Not exercised on darwin, linux.
What it cannot do
Not a disclaimer. The point of everything above is that this list exists and is specific.
- No permission mode is sent, so LeastGrant cannot tell an attended run from an unattended one and records observation rather than approval. Copilot therefore learns more slowly, deliberately.
- Failing closed means a broken or missing LeastGrant blocks all work rather than silently permitting it. Safer, and much louder.
- Speaks Claude Code's wire format, so it shares that adapter. A divergence upstream would surface as Copilot-shaped bugs in a file named for Claude.
- This file's unknown fields need a dedicated binary read; the research pass for it did not complete.
- Verified on Windows only.