We called Codex and Cursor supported before v1.1.0. That was true, but it wasn’t the whole story.
Their tool calls could pass through agentjail policy, but each agent speaks a different hook protocol. They don’t agree on event names, input shapes, or what an ask verdict means. A bare codex or Cursor agent command also didn’t get the same PATH-based OS sandbox launch available to Claude Code.
v1.1.0 closes that gap. Claude Code, Codex, and Cursor now share one policy model and one shield, with a typed adapter for each agent’s protocol. The release also makes protection state visible inside Codex and tightens the boundary around custom Rego rules.
TL;DR
- The PATH shim now covers all three agent CLIs. If you opt in, ordinary
claude,codex, and Cursoragentcommands enter the OS sandbox without a special launch command. - Codex and Cursor get complete hook adapters. Shell commands, file reads, patches, MCP calls, approvals, and outcomes are normalized before policy sees them.
- Policy intent and protocol behavior are recorded separately. An
askthat a hook can’t display is still stored asask, even when the safe response sent to the agent isdeny. - Codex reports live protection state at session boundaries. Startup, resume, clear, compact, and stop events show whether the sandbox and policy daemon are actually active.
- Custom Rego can add rules, but can’t rewrite the resolver. agentjail validates the Rego AST when a rule is added and again when the daemon loads it.
The command you already type can enter the shield
The hook layer checks calls the agent reports. The OS sandbox is the second layer. It limits files, executables, and network access even if a hook is skipped.
agentjail’s opt-in PATH shim already wrapped claude. In v1.1.0 it also wraps codex and Cursor’s agent command:
agentjail install --with-path-shim
After opening a new shell, the commands you already use launch through the shield:
claude
codex
agent
The shim remains opt-in. A piped installer shouldn’t silently take over commands in your shell profile. Hooks are still installed without it, and you can launch any agent explicitly with agentjail run -- <command>.
If you opted into the shim before this release, upgrading regenerates it with all three wrappers. Uninstall removes the wrappers and the shell profile block together.
One policy, three protocols
The policy vocabulary is small on purpose: allow, ask, or deny. Agent hook protocols are not.
Claude Code can surface an approval from its pre-tool hook. Cursor can ask for shell and MCP events, but its file-read hook needs a binary answer. Codex can open its own native permission request, but its PreToolUse hook can’t create one.
That difference used to blur the audit trail. If policy returned ask and the adapter had to send deny, a log could look as if the policy itself denied the call. v1.1.0 stores both facts:
| Recorded field | What it tells you |
|---|---|
policy_action | The canonical allow, ask, or deny returned by policy |
effective_action | The answer the agent protocol actually received |
adapter | Which agent-specific adapter translated the result |
translation_reason | Why the effective action differs from policy intent |
final_action | What ultimately happened after policy and sandbox enforcement |
For example, a Codex PreToolUse event can now read as policy_action=ask and effective_action=deny. That is deliberate. The hook can’t open an approval prompt, and allowing the call would fail open. The record still tells you the rule asked for human approval.
The same normalization happens on the way in. Cursor’s shell, MCP, and file-read events, Codex patches and permission requests, and Claude Code tool calls all arrive at policy in one canonical shape. A rule about a protected file means the same thing whichever agent tries to touch it.
Protection state where you’ll see it
A green badge isn’t useful if it only proves that one process started. agentjail has two enforcement layers to check:
- The OS sandbox is active around the agent.
- The policy daemon is reachable and evaluating hooks.
Codex doesn’t currently offer a persistent custom status command, so v1.1.0 uses its supported systemMessage channel at session boundaries. Startup, resume, clear, compact, and stop now report one of three states:
sandbox + policy active
sandbox active, policy daemon offline
OS sandbox inactive
That catches the moments when context changes and a stale assumption about protection is most dangerous. Cursor gets a persistent status badge, and agentjail preserves any status command you already had. On uninstall, the original command is restored byte for byte.
Custom rules can extend policy, not replace it
Custom Rego is useful because it lets a project add local rules. It is also code loaded into the same policy package as the baseline.
Checking custom rules with text matching wasn’t enough. Rego allows a module to add another body to an existing predicate, so a rule could interfere with the resolver or suppress a locked baseline rule without declaring a replacement in the obvious way.
v1.1.0 parses custom modules with OPA’s AST and accepts only partial candidate entries. A custom rule can contribute an allow, ask, or deny candidate. It can’t declare resolver helpers, change priority, remove locked candidates, or mutate the evaluation path.
Validation runs when you use policy add and when the daemon loads rules from disk. A manually installed invalid rule is quarantined without weakening the built-in baseline.
Fewer misleading records
Several smaller fixes in this release have the same goal: record what happened, not what a string happened to resemble.
agentjail logs --latest Nnow selects the newest matching decisions, then prints them in chronological order.--no-followwalks every matching SQLite page instead of stopping after 1,000 rows.- A successful tool result that mentions
EPERMor a sandbox denial is no longer marked as blocked. Sandbox attribution now requires failure evidence from the agent protocol. - Static text in
git commit -mno longer trips the sensitive-path rule. Shell expansions, chained commands, and protected paths in other arguments still do. - Daemon restart now goes through the installed supervisor, and uninstall checks the daemon socket under the home directory you actually targeted.
Upgrading
Upgrade with the same path you used to install:
brew upgrade agentjail
# or
agentjail update
Existing policy files keep working. If you want ordinary agent commands to enter the OS sandbox automatically, run agentjail install --with-path-shim once, then open a new shell.
One policy should not change its meaning because you changed agents. v1.1.0 makes that true from the hook input through the final audit record, with the same sandbox underneath.