Agents
amx knows four coding agent CLIs by name. Anything else still runs, as a pane amx watches from the outside.
| Agent | Command | Measured against | Reports through |
|---|---|---|---|
| Claude Code | claude |
2.1.276 | a plugin in ~/.claude/skills/amx |
| pi | pi |
0.85.1 | an extension in ~/.pi/agent/extensions/amx.ts |
| Codex CLI | codex |
0.157.1 | hook groups in codex's hooks.json |
| opencode | opencode |
2.0.16 | a TUI plugin in opencode's config directory |
claude is the default. To make another the default, set it in the config:
agent = "pi"
or pick one per agent with amx new --agent codex "...", agent:codex on the
view's task line, or alt+a in the view.
#Setup
Each agent tells amx what it is doing (turn started, tool called, question asked, turn ended with this answer) through a file amx installs:
amx setup claude
amx setup pi
amx setup codex
amx setup opencode
| Agent | What setup writes |
|---|---|
| claude | A plugin directory at ~/.claude/skills/amx: plugin.json, hooks/hooks.json, and the amx skill (SKILL.md). claude loads it as amx@skills-dir for every project. Your settings files are not touched. |
| pi | An extension at ~/.pi/agent/extensions/amx.ts. With --subagent, also amx-subagent.ts, a subagent tool that calls amx sub. |
| codex | Four hook groups merged into hooks.json in $CODEX_HOME (else ~/.codex), and a [hooks.state] entry per group in config.toml marking them trusted, so codex starts without its hooks-review screen. |
| opencode | A plugin at plugins/amx/tui.js in $OPENCODE_CONFIG_DIR (else ~/.config/opencode). No config file is edited. |
Rules that hold for all four:
- Any file of yours at the target path is copied aside before amx writes, and the copy is named in the output.
- Running
setupagain writes nothing if nothing changed. After an upgrade it rewrites what changed. - The installed files call
amx _hookfrom your PATH, so keep oneamxthere. amx uninstallremoves everythingsetupwrote and restores your copies. For codex, if the files changed since, it removes only amx's own entries.setup codexandsetup opencodereadCODEX_HOMEandOPENCODE_CONFIG_DIRfrom the environment they run in. Run them with the same environment your agents get.
Without the wiring, amx reads the agent's state off its screen. That works for
status, but amx has no answer to hand back when a turn ends. amx doctor lists
which agents are unwired.
#What each supports
| claude | pi | codex | opencode | |
|---|---|---|---|---|
| Reports state and answers | yes | yes | yes | yes |
Transcript on the card and in logs |
yes | yes | yes | yes |
resume |
yes | yes | yes | yes |
fork |
yes | yes | yes | no |
adopt |
yes | yes | yes | no |
trust = true answers the folder-trust screen |
yes | yes | not needed | no screen |
Vendor agents (@name at the front of a task) |
yes | no | no | no |
| Live answer text on the card while working | no | yes | no | yes |
A verb the agent cannot do is refused before anything starts, naming what is missing.
#Dials
--model, --permission and --effort (and m:, p:, e: in the view)
become each vendor's own flags. A dial you do not set passes no flag, and the
vendor uses its own default.
| Agent | Model | Permission | Effort |
|---|---|---|---|
| claude | --model: fable, opus, sonnet, haiku, or any model id |
--permission-mode: acceptEdits, auto, bypassPermissions, manual, dontAsk, plan |
--effort: low, medium, high, xhigh, max |
| pi | --model: any provider/id from pi --list-models |
none | --thinking: off, minimal, low, medium, high, xhigh, max |
| codex | --model: any model codex lists |
--sandbox: read-only, workspace-write, danger-full-access |
-c model_reasoning_effort=: low, medium, high, xhigh, max |
| opencode | the model in OPENCODE_CONFIG_CONTENT |
--auto: auto |
none |
A value outside the list, or a dial the vendor lacks, is refused with exit 64 and the valid values:
$ amx new --agent pi --permission plan "x"
amx new: --permission "plan": amx cannot set permission for pi
To pass a flag amx has no dial for, put it after --:
amx new "port it" -- --add-dir /srv/shared
If the vendor's own --model appears after --, amx does not pass its model
dial.
#Models pick the vendor
--model without --agent starts whichever vendor offers that model. amx
checks your configured agent first, then the others:
amx new --model opus "port it" # claude
amx new --model gpt-5-mini "port it" # pi, if pi --list-models has it
Where each list comes from:
| Agent | Model list |
|---|---|
| claude | fable, opus, sonnet, haiku |
| pi | pi --list-models, cached for an hour |
| codex | codex debug models, the ones its own picker shows, cached for an hour |
| opencode | none; use --agent opencode or the config's [opencode] models |
A models list in a vendor's config table replaces the vendor's own. A model
nobody lists is refused, naming what each vendor takes. --agent settles the
vendor, and then the model is just its dial.
#Vendor notes
#claude
amx never passes a session id; claude's first hook names the session. A
message sent mid-turn is folded into the running turn, and the card shows it as
queued until then.
#pi
amx starts pi with --session-id <id> so the session is known from the first
moment. The extension streams the answer being written to the card while a
turn runs, and keeps a heartbeat so long tool calls do not look stalled. pi has
no permission dial and no agents of its own, so @ on a pi task line is always
a file.
#codex
Every codex amx starts runs as codex --no-daemon, with its own app server.
Under the shared server, hooks run in that server's environment, never learn
which agent they belong to, and a turn keeps running after its pane is killed.
codex wires four moments (session start, prompt, tool call, turn end). It has
no notification hook, so amx reads its approval box off the screen, and it
sends nothing for an interrupted or failed turn, so amx reads those endings
from the screen and the rollout file. Skills are $name on the task line.
amx never passes --dangerously-bypass-hook-trust. setup codex writes the
same trust hash codex would write if you approved the hooks yourself, for
amx's own hooks only.
#opencode
Every opencode amx starts runs as opencode --standalone, a server that ends
with its pane. The shared service would run turns in whatever environment first
started it, and keep them running after the pane is gone.
The TUI has no model flag, so amx passes the model as
OPENCODE_CONFIG_CONTENT={"model":"..."} in the pane's environment, on new
agents only. The task goes on --prompt. interrupt presses Escape twice,
since opencode's first press only arms the cancel. stop signals the plugin
to end the turn first, so the shared service does not resume it later.
opencode puts no session variable in the environment of the commands it runs, so it cannot be adopted, and its TUI has no way to fork a session.
#Vendor tables in the config
Each of the four can have a table named after its command:
[claude]
models = ["opus", "sonnet"]
args = ["--add-dir", "/srv/shared"]
[claude.env]
CLAUDE_CONFIG_DIR = "~/.claude-work"
[codex.env]
CODEX_HOME = "~/.codex-work"
| Key | Means |
|---|---|
models |
The models that pick this vendor, replacing its own list. |
args |
Arguments added to every agent of this vendor. A dial stands down if the same flag is here. |
env |
Variables set for every agent of this vendor. A leading ~ is expanded. amx's own AMX_* variables always win. |
env is the way to run agents under a second account or through a proxy. See
Configuration.
#Other agent commands
agent can name any command. One amx has no entry for, such as aider, gets
a pane, a row and a state read from its screen, and nothing more: no dials, no
answers, no resume or fork. Pass its flags after --.
amx new --agent aider "fix the tests"
#Commands as rows
--exec runs a shell command in a pane of its own, beside your agents:
amx new --exec 'cargo test --all'
amx new --exec 'ssh build01 make release && curl -fsS "$HOOK"'
In the view, the same thing is a task line starting with !.
- The whole string goes to
sh -c, so pipes and&&are one row. - It runs in the directory as it is, never in a worktree.
- The dials,
--roleand arguments after--are refused, since there is no vendor. - The row reads
workingwith the last line printed, thendoneorfailedby exit status.exitin the JSON is the code. - Everything it prints is saved to
outputin the record, soamx logs <id>and the card work after the pane is gone.amx resulthas nothing to return for a command; checkamx status <id> --jsoninstead. $AMX_AGENT_DIRpoints at a scratch directory, as in every amx pane.