Harness permissions
ax agent setup, ax agent move and ax admin processing enable write
permission rules for the harness, so that an agent can fetch and reply without
an approval prompt. The sections below show the rules each harness receives
and how to change them. The opencode rules are described in opencode
permissions.
Claude permissions
Claude Code's own permission settings decide what a Claude session may run. ax adds no permission flags. Without a rule, a live session would stop for an approval prompt on every fetch, and a launched session runs non-interactively and cannot answer one.
So these commands add four rules to permissions.allow in the workspace's
.claude/settings.local.json:
ax agent setupfor a Claude agentax agent moveto a new workspaceax admin processing enablefor a Claude mailbox
They create the file if needed and keep every other setting:
{
"permissions": {
"allow": [
"Bash(ax messages fetch:*)",
"Bash(ax messages inbox:*)",
"Bash(ax messages status:*)",
"Bash(ax reply:*)"
]
}
}
The rules allow fetching and replying, plus the two read-only mailbox checks,
inbox and status. ax messages retry and ax messages watch still ask
for approval. retry can re-send any message retained on this machine,
including the owner's, and watch streams events until stopped.
ax adds whichever of the four rules are missing and never removes a rule. A
file from an earlier ax that allowed only fetch and reply gains inbox and
status, and a broader rule you added yourself stays.
The Claude permissions line (claude_permissions in JSON) says whether the
rules were written, were already present, or could not be written. ax never
rewrites a file that is not a JSON object. Instead, it names what to add by
hand. When some rules were already present, the line lists the rules ax added
and then the rules that were already there. added in JSON lists what this run added, and the
Codex and opencode lines report the same way. Repeat setup reports the rules
as already present. Disabling processing leaves the file alone. A manual or
Codex agent gets no file.
ax agent remove does not undo what ax wrote for the harness: the Claude
rules, the Codex rules file and the Codex trust entry, or the opencode rules.
Another agent may share the workspace, you may rely on the trust entry for
your own Codex use, and ax cannot tell whether it or you wrote an entry. Once
no other agent of the same harness is registered in the workspace, remove
prints a Left in place: line (left_in_place in JSON) for each file and
entry still there, saying how to remove it by hand.
- Claude Code honours these rules only in a workspace it already trusts. Open
the workspace in Claude Code interactively once and accept the trust prompt.
ax cannot do that for you. In an untrusted workspace Claude prints
Ignoring N permissions.allow entries. - A denied command does not fail the run. The fetch is refused and nothing is
picked up.
ax messages status MESSAGE_IDshows the messageheldwith the reasonincomplete_handoffand aHeld because:line naming the attempt and its Exec job. - To let the agent do more, add rules to the same file. For example,
"Bash(ax send:*)"lets it send mail,"Bash(ax messages:*)"allows everyax messagescommand includingretryandwatch,"Bash(cargo test:*)"runs a project's tests, and"Edit"lets it edit files. Claude Code's permission mode and its other settings files still apply. See Claude Code's permission documentation. - Codex and opencode agents get rules for
ax messages fetchandax replyonly. See Codex permissions.
In Claude Code, Bash(ax messages:*) allows a
command written as ax messages … but not one written with an absolute path.
For that reason every command ax tells a session to run, in notices and in
launch instructions, names bare ax, and the launch PATH resolves it to the
running binary.
Notices held by Claude Code
Claude Code checks every message written to a session's socket. Sessions that ask before running commands receive ax notices. A session that bypasses permission prompts is stricter, and what it accepts depends on the platform:
- On macOS it accepts an ax notice when ax presents that session's own socket
token, which ax records when the session runs
ax agent setup. ax has no token for a session that was resumed in a new process after setup, or for a session that has not run setup and is offered a mailbox (see Mail for a mailbox with no session). - On Linux it holds every ax notice.
Claude Code prints this line in the session for a notice it holds:
Held peer message — from an unidentified session; preview: «A message is
waiting for this session. Fetch it with:» … — not delivered to Claude (1 held).
The sender did not attest its permission mode and this session bypasses
prompts. Review it below, or set "crossSessionInbound" to "accept".
The message stays pending in ax, and ax messages inbox lists it. Approve the
held notice in the session to pass it to the agent. On macOS, after a resume,
run ax agent setup again in the session with the same name and workspace,
and later notices arrive without an approval. The crossSessionInbound
setting named in the line accepts messages from every local session,
including ax, on both platforms.
Codex permissions
Codex runs every tool command in a sandbox that can read the disk but cannot
connect to the ax socket. A live or launched Codex session therefore gets
Operation not permitted from ax messages fetch. A Codex rules file lets
exactly those commands run outside the sandbox.
These commands make sure <workspace>/.codex/rules/ax.rules holds the two
rules below:
ax agent setupfor a Codex agentax agent moveto a new workspaceax admin processing enablefor a Codex mailbox
They create the file if needed, and add only the missing lines to an existing one:
prefix_rule(pattern=["ax", "messages", "fetch"], decision="allow", justification="ax supervised mailbox fetch")
prefix_rule(pattern=["ax", "reply"], decision="allow", justification="ax supervised reply")
Codex then runs a command that starts with those words outside its sandbox without asking. Every other command stays sandboxed. The rules apply to every Codex session in that workspace, including sessions ax did not start.
The Codex permissions lines (codex_permissions in JSON) say whether the
rules were written, were already present, or could not be written, and whether
Codex trusts the workspace. ax refuses a symlinked .codex, .codex/rules or
rules file, and names the lines to add by hand.
Workspace trust
Codex reads <workspace>/.codex/ only in a trusted workspace. Trust is an
entry [projects."<path>"] with trust_level = "trusted" in
$CODEX_HOME/config.toml (default ~/.codex/config.toml), either for the
workspace itself or, inside a Git repository, for the repository root. A
trusted parent of a workspace outside a repository does not count.
- When neither entry trusts the workspace, ax adds the one Codex would add:
for the repository root inside a Git repository, otherwise for the
workspace. It prints
Codex trust: ax trusted <path> for Codex in <config>(trustin JSON is{"state": "trusted", "written": true, "config": …, "project": …}). The table is appended to the end of the file and every other byte is kept. A missing file is created holding just that table, private to the account. - ax does this as the account that owns the workspace: in setup, from the
agent's own session, and for
ax admin processing enable HOST/AGENT, through the host's ownax. - ax never changes an entry that is already there. A folder set to
trust_level = "untrusted"stays untrusted, and the output says so. - A config that is not valid TOML is reported as
unknown. A symlinked config, or one ax cannot write, is reported asnot_trustedwith the reason. In both cases the output names the entry to add by hand. You can also opencodexin the folder once and accept the trust prompt. - To undo it, delete the
[projects."<path>"]table ax added. The output names it. Codex then asks again the next time it starts in the folder.
Commands the rules cover
- Codex checks each command of a chain joined by
&&,||,;or|separately. A$…expansion, backticks, a redirection, a heredoc or an environment assignment in front makes Codex run the whole command in the sandbox, where it fails. Notices and launch instructions therefore give the reply asax reply MESSAGE_ID 'TEXT' --workspace … --from …, with the text in single quotes. In launch instructions it also carries--attempt. - To allow more, add
prefix_rule(...)lines to the same file or to another file in.codex/rules. For example,prefix_rule(pattern=["ax", "messages", "status"], decision="allow")lets sessions check a message's status. ax keeps lines it did not write. A rule runs its command outside the sandbox without asking. - Of the ax commands, only
ax messages fetchandax replyare guaranteed never to start the ax service, because a harness may run them outside its sandbox. When the service is stopped, for example straight after a reboot before anything else ran, they fail withthe ax host service is not listeningand a hint. Run any other ax command, such asax admin status, or start ax, then repeat. - ax never launches Codex with
--ignore-rules,--ignore-user-config, a--dangerously-*flag or a full-access sandbox. The rules and the account's Codex configuration apply to launched sessions too. - A launched Codex session whose fetch was refused ends without picking the
message up.
ax messages status MESSAGE_IDshows itheldwithincomplete_handoffand aHeld because:line.
With this file, codex exec runs ax messages fetch and ax reply outside
its sandbox without a prompt, and other commands stay sandboxed. To run setup
from a live Codex session, follow The first setup inside
Codex.
The first setup inside Codex
ax agent setup writes the rules file itself, so the first setup in a Codex
workspace runs before any rule allows it. The sandbox refuses its connection
to the ax socket. ax reports this as access to the ax host service socket at … was denied, rather than reporting a stopped service. Under Codex's default
approval policy the session cannot ask to run the command outside the sandbox,
so approve that one command yourself:
- In the Codex session, open
/permissionsand choose "Ask for approval". - Run
ax agent setup --name NAME --workspace /absolute/pathand approve it when Codex asks. - Setup trusts the folder in Codex's
config.toml(theCodex trust: ax trusted …line). If it reports that it could not, trust the folder when Codex asks. Codex asks once<workspace>/.codex/exists, even when a parent folder is already trusted.
Sessions started after the workspace is trusted run ax messages fetch and
ax reply without a prompt, including sessions ax launches with codex exec.
Next
- Mailboxes and sessions: run
ax agent setupand see what it writes for each harness. - opencode sessions lists the rules ax writes for opencode.
- Let mail start a session explains
ax admin processing enable, which writes the same rules. - Security model explains how ax separates message authority from execution authority.