Skip to main content
Mockingbird 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. A deny rule next to a wildcard Python grant stops an honest agent, but not one that has been redirected. The guard reads the command string no matter which interpreter would run it.

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

The guard blocks a call by exiting with code 2. Every call is added to ~/agent/audit/tools.jsonl with the current enforcement mode, so you can see afterwards what ran while the guard was paused.

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 Mockingbird too.