Skip to main content
Mockingbyrd scores many things it doesn’t control. The one thing it actually enforces is the P4 guard: a PreToolUse hook that checks every tool call before the call runs. Where the hook sits is the point. Permission rules live next to general-purpose interpreters, and a deny rule next to a wildcard Python grant stops an honest agent but not a redirected one. The guard reads each command before it runs and blocks the ones that name a protected path.
The guard reads the text of a command. It does not follow interpreters, resolve variables or decode anything, so a command that assembles a path at runtime can pass it. That is why N5 keeps general interpreters off the allow list: the guard is the second line, not the first.It is also a Claude Code hook. Other agents on the same Mac — Codex, for example — run with nothing inspecting them, and the Agent Roster marks them unguarded.

Install

In the app, open Enforcement, click Install / update guard, then click Register as PreToolUse. Or from a shell:
Registering adds the guard to hooks.PreToolUse. Your existing hooks keep their place and order. Before the change, settings.json is copied to settings.json.mbird-<timestamp>.bak.

What it blocks

Four layers, each switchable on its own. The last two exist because each was a way straight past the first two. An agent that can edit the hook can switch the guard off in one write, and a connector call is not a command at all, so the command checks never saw it. The guard blocks a call by exiting with code 2. Every call is recorded in ~/agent/audit/tools.jsonl.
The log keeps metadata — time, tool, session, working directory, and the size of any content — never the content itself. Earlier versions wrote the whole payload, including the full text of every file written. If you are upgrading, --prune-log rewrites those old entries into the same shape; --prune-log --drop removes them instead.

A match found only in content

If a protected path appears only inside the text of a file being written — not in the command, not in a path it names — the prompt says so and offers Allow once but not Allow always. A false alarm of that kind should not be able to open a standing exception.

State

The guard reads ~/.config/mockingbird/enforcement.json again on every call. Pausing and stopping take effect right away, with no restart, re-registration or reinstall.
When enforcement is paused or stopped, a banner appears on every screen and the menu bar icon becomes hollow.

What it checks

The guard reads what a call does, not the data it carries. Otherwise, the guard doesn’t check file contents. A document that mentions a path isn’t accessing it, and checking prose added nothing. Text about a destructive command deletes nothing. A script that contains one is still refused: once when it’s written to an executable path, and again when it runs.

Unrecognized payloads

Unrecognized payloads are handled on the safe side:
  • Valid JSON, but no recognizable fields. The guard still checks every byte for a T0 path, because a T0 path in any argument means something is pointing at an original. It only checks for destructive commands when the tool name suggests it runs things: bash, shell, exec, run, command, terminal, script, osascript, process or eval. That way a search query or message body can still mention those commands.
  • Not JSON at all. The guard checks the whole payload for both patterns.

How it behaves

These calls were tested against a sandboxed HOME, and every case passed: Four rules re-run cases from this table on every scan: the two blocks, the prose that’s allowed and the script that’s refused. They set MB_SELFTEST=1 so the guard responds as if it’s active, whatever the current mode.
A control you’ve never triggered is only an assumption. A control that blocks too much gets switched off, which leaves you in the same place. The self-tests guard against both.

Remove the guard

Click Remove in the Enforcement tab, or run _guard-uninstall.sh. This unregisters the hook and renames the script to t0-guard.removed-<timestamp> instead of deleting it. The doctrine’s N6, never delegate deletion, applies to Mockingbyrd too.