LeastGrant

compatibility

What survives the trip to your agent

The same policy runs everywhere. What reaches you at the other end does not. One agent turns an unanswerable question into a prompt, another into a refusal, and a third cannot see the tool call at all. This page says which, for each one, and how we know.

read the gaps, not the ticks

This is the page most likely to talk you out of using LeastGrant with your agent, and it is written that way on purpose. Finding out after you install that your editor has no event for file writes is worse than not installing.

Generated from compatibility/ in the repository. Nothing here is typed by hand.
Agent Overall allow ask deny on hook error shellreadswritesdeletesMCP
Claude Code 2.1.240 partial yes degrades yes runs anyway gatedgatedgatedgatedgated
Codex CLI 0.152.0 degraded ignored none yes runs anyway gatedgatedgatedgatedgated
Cursor 3.18.25 unverified yes partial yes unknown gatedafter the factnot seennot seengated
GitHub Copilot CLI 1.0.82 partial yes degrades yes refuses gatedgatedgatedunknownunknown
Google Antigravity 2.11.0 none
OpenCode 1.18.26 none

How the evidence is graded

Every claim on this page carries how it was established, because the grades are not interchangeable and the difference has already mattered here.

  • probed — someone ran the real agent and watched this happen.
  • read — someone read the shipped binary. Strong evidence about the contract, none at all about the integration.
  • documented — the vendor says so. Weakest, and it never alone justifies the word verified: Cursor's own documentation says its hooks fail open by default, and reading what ships shows that depends on the failure kind.
  • unknown — nobody has checked. Printed as unknown rather than left blank, because a blank reads as fine.

partial

Claude Code

Verified against Claude Code 2.1.240 on win32. Untested on darwin, linux.

  • deny is enforced, including in the most permissive mode
  • an ask degrades — reaches a human when a human is there.
  • if the hook errors or times out, the call runs anyway — a LeastGrant that cannot start enforces nothing
  • verified against Claude Code 2.1.240 on win32

What the agent itself cannot do

  • Managed policy `disableAllHooks: true` switches every hook off, including managed ones, with no signal LeastGrant can see. It is silently absent.
  • Fails open on crash and on timeout, so a LeastGrant that cannot start enforces nothing.
  • A hook ask in non-interactive mode is a deny, not a prompt.
  • The public docs list PreModelSwitch and PostModelSwitch, which do not exist in the installed 2.1.240 binary.

What LeastGrant has not done yet

  • Only PreToolUse and PostToolUse are registered, so failed calls are never observed and their pending entries are never resolved.
  • Verified on Windows only. macOS and Linux run the same code path but nobody has driven the real binary there.

Last checked 2026-09-02 · adapter src/adapters/claude-code/hook.ts

degraded

Codex CLI

Verified against Codex CLI 0.152.0 on win32. Untested on darwin, linux.

  • deny is enforced, including in the most permissive mode
  • no ask exists here, so LeastGrant is a veto rather than a prompt
  • if the hook errors or times out, the call runs anyway — a LeastGrant that cannot start enforces nothing
  • verified against Codex CLI 0.152.0 on win32

What the agent itself cannot do

  • No ask verdict exists at all. On Codex, LeastGrant is a veto rather than a prompt.
  • A handler declared `"async": true` cannot apply control effects: its deny, its exit-2 block and its updatedInput are all silently ignored. A single wrong word in the config is a total, unsignalled bypass.
  • Hook trust is bound to a hash of the definition, so upgrading or reinstalling re-flags the hook and it stops running until re-trusted in /hooks.
  • On Windows the trust hash covers only `commandWindows` and on POSIX only `command`, so one hooks.json has different hashes on different machines.
  • `codex exec` has no trust review and no warning: an untrusted or modified handler is simply never added to the handler set, and nothing says so.
  • Fails open on crash and on timeout.
  • `[features] hooks = false` and `allow_managed_hooks_only = true` disable user hooks entirely.

What LeastGrant has not done yet

  • PermissionRequest has never fired in a real session. `codex exec` runs unattended, where by definition nothing prompts, so that path is contract-tested only.
  • Verified on Windows only.

Last checked 2026-09-02 · adapter src/adapters/codex/hook.ts

unverified

Cursor

The contract was read from Cursor 3.18.25 as shipped. Nobody has run LeastGrant inside it. Untested on win32, darwin, linux.

  • deny is enforced, including in the most permissive mode
  • an ask reaches a person only on some channels — A real forced prompt on beforeShellExecution and beforeMCPExecution only, and there it beats the most permissive mode.
  • nobody has established what happens when the hook errors
  • not intercepted at all: file writes, deletions
  • seen only after the fact, not gated: file reads
  • never run inside a real Cursor — the contract is read from what ships, the integration is untested

What the agent itself cannot do

  • File reads are observed after the fact, not gated. A deny stops the content reaching the model but the file has already been read.
  • Writes, edits and deletes have no pre-execution event and are not intercepted at all.
  • An ask on preToolUse is rejected as unsupported and the tool call errors, which is neither a prompt nor a clean degradation.
  • No permission mode reaches the hook, so LeastGrant cannot tell an attended session from an unattended one.
  • Cursor also ingests Claude Code hooks from .claude/settings.json and ~/.claude/settings.json, so installing both adapters may double-fire.

What LeastGrant has not done yet

  • Never run inside a live Cursor session. The contract is verified against the shipped 3.18.25 bundle; the integration is not verified at all.
  • The installer does not set failClosed, so LeastGrant fails open on its own crash where Cursor would allow it to fail closed.
  • Reads and MCP calls are covered; writes are not, so the support level is partial rather than enforcing.

Last checked 2026-09-02 · adapter src/adapters/cursor/hook.ts

partial

GitHub Copilot CLI

Verified against GitHub Copilot CLI 1.0.82 on win32. Untested on darwin, linux.

  • deny is enforced, including in the most permissive mode
  • an ask degrades — honoured interactively.
  • if the hook errors, the call is refused rather than run
  • verified against GitHub Copilot CLI 1.0.82 on win32

What the agent itself cannot do

  • 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.

What LeastGrant has not done yet

  • 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.

Last checked 2026-09-01 · adapter src/adapters/claude-code/hook.ts

none

Google Antigravity

Verified against Google Antigravity 2.11.0 on win32. Untested on darwin, linux.

What the agent itself cannot do

  • Fails open and silently on crash, deletion or timeout: it logs and proceeds.
  • A plain `ask` is satisfied by a cached 'Always allow', so only force_ask is a guaranteed prompt.
  • Hook config is workspace-scoped at <repo>/.agents/hooks.json, discovered by walking up from cwd. A repository can therefore ship hook configuration, which is a supply-chain surface LeastGrant's threat model does not currently cover.
  • CustomizationConfig carries a switch that can disable the hook engine, and LeastGrant has no way to express 'installed but switched off at the host'.

What LeastGrant has not done yet

  • No adapter ships yet. This file records a completed evaluation.
  • If an adapter is written, force_ask is the primitive that should back an abstract ASK, and it must be exposed as a capability rather than hardcoded by agent name.

Last checked 2026-09-02 · no adapter ships

none

OpenCode

Verified against OpenCode 1.18.26 on win32. Untested on darwin, linux.

What the agent itself cannot do

  • permission.ask is declared in the plugin types and never fired. Building on it would produce an adapter that appears installed and enforces nothing.
  • A plugin that fails to load is silently skipped, with no warning, and the agent runs unpoliced.
  • No hook timeout of any kind, so a slow hook hangs the agent rather than failing.
  • POST /session/{id}/shell runs commands with no permission check and no event.
  • Mutating tool args in a plugin changes what the permission engine evaluates, so plugin order decides the verdict.

What LeastGrant has not done yet

  • No adapter ships. This file records a completed evaluation, not a supported integration.
  • Revisit if OpenCode wires permission.ask to the permission engine, which would make a faithful adapter straightforward.

Last checked 2026-09-02 · no adapter ships