agentjail logs tells you what happened one tool call at a time. That is useful
when you are watching a session or investigating one denial. It is a poor way
to answer a broader question:
What has AgentJail actually done on this machine?
v1.2.0 adds the missing summary:
agentjail stats
It also fixes an update bug in the opt-in PATH shim. If you had enabled the shim before Codex and Cursor support landed, updating the AgentJail binaries could leave you with the old Claude-only wrapper. Both manual and automatic updates now rebuild the complete wrapper set from the consent you already gave.
The report
The default report reads the local SQLite store and covers all recorded activity:
AgentJail Activity (all time)
════════════════════════════════════════════════════════════
Total outcomes: 1004
Sessions: 4
Allowed / Asked / Blocked: 930 / 2 / 72
Active days: 5 (2026-07-25 → 2026-07-29)
Latency (p50/p90/p95/p99/max): 1.2ms / 2.4ms / 2.7ms / 4.2ms / 23.5ms
Block rate: █░░░░░░░░░░░░░░░░░░░░░░░ 7.2%
Below the totals, ranked tables show the policy rules that denied calls, which agents generated activity, and which audit events occurred. This is all local. The command opens the existing database through AgentJail’s read-only store interface. It does not send a report anywhere.
For a smaller window:
agentjail stats --since 24h
agentjail stats --since 7d
For scripts and dashboards:
agentjail stats --json
--top N controls the number of rows in each ranked table, and --db can point
at another AgentJail decision database.
Count what finally happened
AgentJail records more than one action because enforcement has layers.
Policy can return allow, ask, or deny. An agent adapter may need to turn
an ask into a fail-closed denial when its hook protocol cannot open an
approval prompt. The OS sandbox can then block something policy allowed.
Those are different facts:
| Field | Question |
|---|---|
policy_action | What did policy decide? |
effective_action | What answer did the agent protocol receive? |
final_action | What ultimately happened? |
The headline stats count final_action. If policy allowed a read but Landlock
or Seatbelt blocked it, the report counts a block. The “Top Policy Deny Rules”
table stays tied to policy_action, so a sandbox block does not get invented
as a policy rule.
Older rows without the newer fields still work. The queries fall back to the original action column.
Notice when recording goes quiet
A quiet report can mean a quiet agent. It can also mean the shield launched while decision recording stopped.
The report compares days with shield.activated audit events against days
with recorded decisions. If a day has shield launches and zero decisions, it
prints a coverage warning and points you to agentjail doctor.
This is a signal, not a verdict. An agent might genuinely launch and make no tool calls. The useful part is that the gap is now visible instead of hiding inside an otherwise healthy-looking total.
Missing agent identity gets the same treatment. New rows with no attributable
agent are stored as unknown, not an empty string that disappears into a
grouped report.
PATH-shim consent now survives every update path
The PATH shim remains opt-in:
agentjail install --with-path-shim
That command installs wrappers for:
claude
codex
agent
The shell-profile block is the durable record that you asked for those
wrappers. The scripts under ~/.agentjail/bin are derived files and can be
rebuilt.
Install already understood that distinction. The two updater paths did not. They swapped the real binaries and repaired AgentJail’s role symlinks, but never regenerated PATH wrappers. Tests stayed green because they checked the binaries, not the derived launchers.
v1.2.0 gives install, doctor, uninstall, manual update, and daemon auto-update one shared shim contract. After a binary swap, an updater checks for an existing wrapper or the shell-profile consent marker. If either exists, it rebuilds all three wrappers from the current template.
If you never opted in, an update still does nothing to your shell profile.
Upgrade
Use the same channel you installed from:
brew upgrade agentjail
# or
agentjail update
Then run:
agentjail stats --since 24h
agentjail doctor
The first command shows what the guard did. The second checks that the guard and its launch paths are still intact.