The online scanner answers "is this relay clean?".
This answers the other half: "should this command run?"
No config file to edit by hand β the command merges itself in, and backs up what was there first.
For Codex, use:
/hooks, find agent-police-gate and trust it.
Want it gone? apgate uninstall claude-code removes it cleanly.
These are real rules and real outcomes, not mock-ups.
Blocked outright β there is no benign version of this shape:
Prompted once β probably fine, but worth your eyes:
Left completely alone β everyday commands pass without a single byte of output:
Once approvals are off, nothing prompts. This gate puts that one prompt back, only for the shapes that matter.
Every call joins a hash chain; removing or editing a line breaks verification. apgate report shows the summary.
An indicator published this week can be run against last month's sessions with apgate rescan.
Not inferred from docs. Two findings below are worth knowing before you install.
| Claude Code 2.1.269 | Codex CLI 0.153.4 | |
|---|---|---|
| Blocks on rule match | β | β |
| Ordinary commands untouched | β | β |
| Call recorded in the ledger | β | β |
permission_mode: bypassPermissions, Codex ran a command the gate had answered
ask on β correctly, since there was nobody to prompt. That would make every ask rule a no-op in
exactly the unattended sessions that need it most, so the gate escalates ask to deny when no human
is in the loop. An unanswerable prompt has to fail closed.
.codex/hooks.json and reads only
~/.codex/hooks.json β which is where apgate install codex writes.
The paper measured its own policy gate at 100% bypass by an adaptive attacker, and that number applies here too. What a gate like this catches is the generic, non-adaptive rewriting the 428-relay survey actually found in the wild β worth catching, and not the same as being safe.
Closing the gap properly needs a signed response envelope from the vendor. No major tool-use API or MCP spec provides one.
No. A rule that blocks cannot ship if it fires even once on a corpus of 146 ordinary developer commands β enforced by CI, not promised. The current bundle's blocking false-positive rate on that corpus is 0.
On a clean command the gate prints nothing at all.
No. The hook sees the tool call after it passed through the relay; it never saw what the model actually produced.
The paper measured its own policy gate at 100% bypass by an adaptive attacker, and that number applies here too.
Community rules can never block; they only record. The schema rejects any community rule carrying deny or ask, and CI runs that check on every pull request.
A wrong community rule costs a line in a local log, not a developer whose agent stopped working for a reason they cannot see. That split is what lets an open rule library exist.
Rules are data, not code: a rule picks from a fixed predicate table and supplies literals β no regex, no IO, no subprocess.
Bundles are signed with Sigstore keyless signing via GitHub Actions OIDC, so this project holds no signing key. Each release publishes a Merkle root, so a client can verify the bundle it was served is the bundle everyone else was served β including when the mirror is ours.
No, deliberately. It runs inside an agent with shell access, so an auto-updating code channel would be a remote-execution path onto every user's machine β the same supply-chain shape this project exists to catch.
Code moves through pip install -U, user-initiated and auditable. Only rules update automatically.
No. The ledger is local, mode 0600, never uploaded, and secret-looking tokens are scrubbed before writing.
There is no telemetry in this release. If it is ever added it will be off by default and will never carry command text, prompts, or file contents.