Configuration
amx runs with no config file at all. When you want to change something, write
~/.config/amx/config.toml (or $XDG_CONFIG_HOME/amx/config.toml). The
repository ships a copy with every key explained and every default written
out, assets/config.toml; a copy nobody edits behaves exactly like no file.
| File | What it is |
|---|---|
~/.config/amx/config.toml |
Your settings. |
<repo>/.amx/config.toml |
A project's settings, layered over yours once you run amx allow. |
~/.config/amx/themes/<name>.toml |
Your themes. |
~/.config/amx/agents/<name>.md |
Your roles. See Scripting. |
<repo>/.amx/agents/<name>.md |
A project's roles. |
A config problem never stops an agent from starting:
- An unknown key is a warning; the rest of the file applies.
- A dial value the configured agent would not take is a warning and is dropped.
- A file that cannot be read or parsed, including a key with the wrong type, falls back to the defaults with a warning.
#Keys
| Key | Default | Meaning |
|---|---|---|
agent |
"claude" |
The command new agents run: claude, pi, codex, opencode, or any other command. May include arguments. |
max_agents |
5 |
Live agents allowed in one project before new refuses. |
max_total |
none | Live agents allowed across all projects. |
max_children |
8 |
Live children one parent may have. 0 means no limit. |
subagent_depth |
2 |
How deep a chain of subagents may go. 0 forbids children. |
subagents_may_escalate |
false |
Whether amx sub accepts --permission. |
worktrees |
true |
Give each agent its own worktree inside a repository. |
notifications |
"desktop" |
Where notices go: "desktop", "terminal", "both" or "off". |
trust |
false |
Answer the vendor's folder-trust screen for worktrees amx cuts. |
model |
none | Default model dial. |
permission |
none | Default permission dial. |
effort |
none | Default effort dial. |
summary_command |
none | Command that writes the one-line summary of a turn. |
theme |
"auto" |
Colour theme for the view. |
park_after |
3600 |
Seconds an idle, unwatched agent keeps its pane. 0 never parks. |
copy |
[] |
Files copied from the repository root into a new worktree. |
link |
[] |
Directories in a new worktree symlinked to the repository's own. |
setup |
[] |
Commands run in a new worktree before the agent starts. |
base |
none | What new worktrees are cut from. Default: whatever is checked out. |
diff |
none | Viewer for amx diff at a terminal, such as "delta --paging=always". |
on_waiting |
none | Command run when an agent stops on a question. |
on_idle |
none | Command run when a turn ends and the agent is back at its prompt. |
on_done |
none | Command run when an agent's command exits 0. |
on_failed |
none | Command run when an agent's command exits non-zero. |
on_stopped |
none | Command run when you stop an agent. |
[keys] |
empty | Your own key bindings in the view. |
[claude], [pi], [codex], [opencode] |
empty | Per-vendor models, arguments and environment. |
An example:
agent = "claude"
max_agents = 8
model = "opus"
effort = "high"
base = "main"
copy = [".env"]
link = ["node_modules"]
setup = ["pnpm install"]
diff = "delta --paging=always"
summary_command = "claude -p 'Sum this up in eight words. Answer with the words alone.'"
on_waiting = "curl -sX POST https://hooks.example.com/amx -d @-"
[keys]
"alt+g" = "lazygit"
#Agent limits
max_agents counts live agents in the project the new agent would run in. A
repository at its limit does not stop you from starting agents in another
one. max_total limits the whole machine, and is unset by default.
A live agent here is one that is starting, working or waiting on a question,
with its pane still there. Agents idle at their prompt and command rows do not
count. Subagents do not count toward either limit; max_children and
subagent_depth bound them instead.
At a limit, new, sub, fork and resume exit 2 and name the limit.
#Dials
model, permission and effort set the defaults for new agents of the
configured agent. Leave a key out to let the vendor choose; there is no
value that means "vendor default". The values each vendor takes are on the
Agents page. A flag on the command line beats the config.
#Worktree setup
copy, link, setup and base prepare new worktrees. Details on
Worktrees.
#Summaries
A finished row in the view shows the first line of the agent's answer. Set
summary_command to have a command write a short summary instead:
summary_command = "claude -p 'Sum this up in eight words. Answer with the words alone.'"
When a turn ends, the view runs the command in the agent's directory with the
answer on stdin, AMX_ID set, and AMX_NESTED=1 so a claude it starts does
not report as the agent. The first line it prints goes on the row. While an
agent works, the view also asks the command every three minutes what the turn
is about, feeding it the conversation so far.
Only the view runs it: ls, status and statusline never do. Each
finished turn is summarised once, one at a time, so opening the view on many
old agents queues them. A failing command costs only the summary.
#Parking
park_after is how long an agent idle at its prompt keeps its pane when
nobody is attached. After that amx closes the pane and keeps the record; the
agent comes back on enter, amx attach or amx resume. Pinned agents and
agents you are attached to are never parked. See
Worktrees.
#Notifications
amx posts a notice when an agent stops on a question and when an agent's command finishes. Nothing is posted about a pane you are already looking at.
| Value | Where notices go |
|---|---|
"desktop" |
notify-send on Linux, osascript on macOS. |
"terminal" |
An OSC 777 escape to every client of every tmux server under your tmux socket directory. foot, kitty, WezTerm and Ghostty show it as a desktop notification. |
"both" |
Both. |
"off" |
Nowhere. |
"terminal" is for SSH sessions: run the view inside a tmux on the remote
machine and the notice reaches your local terminal. true and false still
work and mean "desktop" and "off".
#Moment commands
The five on_ keys run a command when an agent reaches a moment:
| Key | When |
|---|---|
on_waiting |
It stops on a question. |
on_idle |
A turn ends and it is back at its prompt. |
on_done |
Its command exits 0. |
on_failed |
Its command exits non-zero. |
on_stopped |
You stop it. |
on_waiting = "curl -sX POST https://hooks.example.com/amx -d @-"
on_done = "notify-send 'amx' \"$AMX_ID $AMX_STATE\""
on_stopped = "echo $AMX_ID stopped >> ~/amx.log"
Each runs through sh -c in the agent's worktree (or its directory), detached.
amx does not wait for it, and its output goes nowhere: redirect it yourself if
you want a log. The event that caused the moment arrives on stdin as one JSON
line.
| Variable | Value |
|---|---|
AMX_ID |
The agent's id. |
AMX_STATE |
The state word, as in amx ls --json. |
AMX_DIR |
The agent's record directory. |
AMX_AGENT_DIR |
The agent's scratch directory. |
AMX_WORKTREE |
Its worktree, when it has one. |
AMX_NESTED |
1. |
AMX_WATCHED |
1 if someone is attached to the pane, else 0. Not set for on_stopped. |
#Your own keys
[keys] binds keys in the view to shell commands:
[keys]
"alt+g" = "lazygit"
"alt+t" = "cargo test 2>&1 | less"
"f5" = "make deploy"
A key is an optional ctrl+ and alt+, in either order, then one character
or f1 to f12. A capital letter means shift; shift+ is not a spelling.
Pressed on an agent's row, the view hands over the terminal and runs the
command through sh -c in the agent's worktree (or directory), with AMX_ID,
AMX_DIR, AMX_AGENT_DIR, AMX_NESTED=1 and AMX_WORKTREE set. When it
exits, the view comes back and reports only failures.
A key the view already uses cannot be rebound: the view says so when it opens
and binds nothing. The keys screen (?) lists your bindings under yours.
#Vendor tables
[claude]
models = ["opus", "sonnet"]
args = ["--add-dir", "/srv/shared"]
[claude.env]
CLAUDE_CONFIG_DIR = "~/.claude-work"
[pi]
models = ["anthropic/claude-opus-4-1", "openai/gpt-5"]
args = ["--approve"]
| Key | Meaning |
|---|---|
models |
The model list used to pick this vendor from --model, replacing the vendor's own. |
args |
Arguments every agent of this vendor gets. A dial amx would set stands down if the same flag is here. |
env |
Environment variables for every agent of this vendor, over the environment you ran amx in. A leading ~ expands to your home. AMX_ID, AMX_BIN, AMX_DIR and AMX_AGENT_DIR cannot be overridden. |
Tables are only accepted for claude, pi, codex and opencode. Any other
table name is a warning.
#Project config
A repository can carry its own .amx/config.toml. It is layered over your
file one key at a time, so a project file with one line changes one key.
Two exceptions: a vendor table like [claude] replaces yours whole, and
[keys] merges binding by binding.
Every worktree of a repository reads the same file, at the repository root. A
directory outside any repository reads <dir>/.amx/config.toml. .amx/ is
excluded from git, so the file stays local unless you commit it.
#amx allow
A project file can name the program a pane runs and shell commands amx runs, so amx ignores it until you allow it:
cd ~/code/app
amx allow # prints the file and records it
amx allow --forget # stops allowing it
amx allow --dir ~/code/other
amx keeps a copy of exactly what it showed you, under
~/.local/state/amx/allowed/. If the file changes afterwards (your edit, a
pull, or an agent's), amx warns once and ignores it until you run amx allow
again.
Even when allowed, a project file cannot set:
permission,trustorsubagents_may_escalate,- in a vendor's
env:PATH,HOME,SHELL,CLAUDE_CONFIG_DIR,CODEX_HOME,OPENCODE_CONFIG_DIR,OPENCODE_CONFIG,OPENCODE_CONFIG_CONTENT, or anyLD_*,DYLD_*orAMX_*variable.
A project's roles in .amx/agents/ need no allow, but cannot set agent or
permission.
#Which file the view reads
amx --dir <path> uses that project's file for the view: its dials, its
theme, and its max_agents in the header. Plain amx shows every agent and
uses your file, counting against max_total if you set one.
#Themes
The view uses colour for six things, and a theme sets those six:
# ~/.config/amx/themes/mine.toml
waiting = "#ffc107" # waiting on a person
done = "#4eba65" # went as intended
failed = "#ff6b80" # attempted and failed
stopped = "#999999" # ended by hand
accent = "cyan" # the next agent's dials, the line you type on
cursor = "#373737" # background of the cursor's row
theme = "mine"
theme value |
Meaning |
|---|---|
auto |
Ask the terminal for its background colour and use light or default. The default. |
default |
Built in, matched to claude's palette, for dark backgrounds. |
light |
Built in, for light backgrounds. |
terminal |
Built in, using only your terminal's named colours. |
| a name | ~/.config/amx/themes/<name>.toml. |
a path containing / |
That file. |
Colours are a name (cyan, bright black), a 256-colour index (134), or
hex (#4eba65). A role you leave out keeps the default's colour. A file that
cannot be read falls back to default with a warning.
auto sends the terminal an OSC 11 query when the view opens and waits up to
200 ms for the reply, then falls back to COLORFGBG, then to default.
The view checks the theme file once a second, so edits show up without a restart. Everything else on the screen uses your terminal's own colours, dim and bold, and a theme cannot change the glyphs or an agent's own output.
#tmux
amx brings no tmux config and uses the tmux server you already run. The
repository's assets/tmux.conf explains each line worth adding; copy what you
want:
# Let shift+enter reach the view as a newline.
set -g extended-keys on
set -g extended-keys-format csi-u
# Agent counts in the status bar.
set -g status-right '#(amx statusline)'
set -g status-interval 5
# prefix a: the agent waiting on you. prefix A: the next one. prefix C-a: back.
bind a run-shell "amx attach --waiting"
bind A run-shell "amx attach --next"
bind C-a run-shell "amx attach --last"
# prefix v: the view in its own window.
bind v run-shell "tmux select-window -t amx 2>/dev/null || tmux new-window -n amx amx"
# When an agent's session ends, move to your previous session instead of detaching.
set -g detach-on-destroy off
You do not need set -g mouse on for the view, and amx binds ctrl+z itself,
only in its own amx-* sessions.