phux docs

Coding agents

phux tracks the coding agents running in its panes, so you can see which one needs you and answer it without hunting for its tab. Agents can also use phux themselves: to run commands in other panes, read their output, and wait for things to happen.

phux agent list                                   # every pane's agent and state
phux agent wait --any --until blocked --timeout 600  # until any agent needs you

In the terminal UI, the sidebar lists agents with their state, C-a A opens the agents view, and C-a q jumps to the next pane whose agent is waiting for you (C-a Q jumps back).

Agent states

Every pane has an agent record: the agent’s kind (claude, codex, pi, and so on), an optional name, and a state:

StateMeans
workingRunning a turn.
blockedWaiting on you: a permission prompt or a question.
idleAt its prompt, nothing pending.
doneFinished and said so.
unknownNo agent found, or the agent left.

phux uses the best evidence it has. In order, that is what the agent declares through its integration or phux agent set, the events its integration reports, the program’s own OSC 7501 status reports, its hooks, the program in the foreground, and finally the screen matched against built-in rules. When the agent exits or another program takes over the pane, the state goes back to unknown.

Screen rules ship for Claude Code, Codex, OpenCode, pi, Oh My Pi, Grok, Amp, Cursor, Gemini CLI, Goose, and Aider. A screen that matches no rule reads as idle, never blocked. To add or override rules, put them in ~/.config/phux/agent-rules/ (or $PHUX_AGENT_RULES_DIR).

phux agent show @7        # one pane
phux agent explain @7     # the evidence behind the state

phux agent list prints one line per agent: the pane, the agent’s kind, its %name address (or why it has none), its state, how confident phux is, and a short explanation. --json prints the same as a document.

Agent setup

Install the integration for your agent. Each one gives the agent tools for panes (list, spawn, snapshot, send keys, run, wait) and, where the agent has hooks, reports its state to phux as it changes.

AgentInstall
Claude Codeclaude plugin marketplace add no-phux/phux, then claude plugin install phux@phux
pipi install npm:@phux/pi
Oh My Piomp plugin install @phux/omp
OpenCodeopencode plugin add @phux/opencode
Grokgrok plugin marketplace add no-phux/phux, then grok plugin install phux@phux --trust
Anything that speaks MCPSee MCP.

Start a new agent session inside a phux pane to use it.

Claude Code from any terminal

phux agent install-claude makes a plain claude command start inside a phux pane with its hooks wired up, even when you run it from a terminal outside phux:

phux agent install-claude

It puts a small wrapper named claude in ~/.local/share/phux/shims and adds one marked block to your shell’s rc file (~/.zshrc, ~/.bashrc, or fish’s config.fish) that puts that directory first on PATH. It never replaces the real claude. Pass --shell or --real PATH when it guesses wrong. phux agent uninstall-claude removes both, and phux doctor reports when the wrapper is out of date.

Teaching an agent phux

phux skill prints a guide to driving phux from the command line, built into the binary, so it always matches the installed version. Any agent that can run commands can read it:

phux skill quick       # the core loop and safety rules
phux skill             # everything

phux mcp --skill prints the same guide for the MCP tools. Both are also installable as skills with npx skills add no-phux/skills.

MCP

phux mcp serves phux as MCP tools over stdio. Register it the way your agent registers any stdio server. For Claude Code:

claude mcp add phux -- phux mcp

The plugins above register it for you. phux mcp --schema prints every tool with its input schema. Each tool mirrors one phux command and is marked read-only or destructive the same way the server treats it. Tools that kill, detach, send a destructive signal, or approve something require confirm: true.

Driving an agent in a pane

Address an agent’s pane by %name or @N:

phux agent wait --until blocked --timeout 600 %reviewer   # until it needs you
phux agent prompt %reviewer 'run the tests again'          # hand it one line of work
phux agent answer --id Q7 --choice 2 %reviewer             # answer its question

agent wait waits for a change. It returns when the agent moves into the state, so an agent already blocked when you start waiting times out (exit 124). Use phux agent show to read the current state.

agent prompt sends one line and gets a receipt. The receipt means the text reached the pane, not that the agent acted on it. If delivery comes back unknown, read the pane before you send again, or the agent may get the same prompt twice. Two prompts at once to the same pane are refused.

agent answer types only an answer the agent offered. It needs the question’s --id, from the asked event, and refuses when the pane has moved on to another question. --text with --allow-unlisted sends your own answer.

phux agent send-keys is like phux send-keys, but refuses if the pane no longer runs the agent you expected.

Starting agents

phux launch opens a new pane running an agent:

phux launch --list                        # integrations you can launch
phux launch claude-code -- --model opus   # extra arguments follow --

Launch commands come from plugins. The starter distribution includes them for the agents above; phux config init --distro starter turns it on.

phux agent start starts an agent in a shell pane you already have, and returns once the agent is ready for input:

phux agent start reviewer --kind claude --target @3

What agents see about each other

The pi, Oh My Pi, and OpenCode plugins add a short summary of the other agents (their names, folders, and states) to each request the agent sends, then only what changed. They never send screen contents, prompts, or credentials.

Another agent’s name, folder, and state are data, not instructions. Anyone who can name a pane can put text in them. PHUX_CONTEXT_AWARENESS=0 turns the summary off.

Mail and path claims

Agents can leave each other messages and mark which files they are working on. Both are stored on this machine and survive server restarts.

phux mail send @7 -m 'rebased onto main; rerun tests' -t fix-login
phux mail read
phux claim take src/auth/ --note 'fixing login redirect'
phux claim list

An address is a pane (@749), a labelled pane (pi@749), or a plain name for something outside a pane. You speak as --as, else $PHUX_AGENT_ADDRESS, else your pane, else $USER. Addresses are panes on this machine; host/@N is refused.

For a send that may need recovery, choose a fresh unique nonzero 32-hex operation ID and keep the original sender, recipients, thread and body:

phux mail send @7 -m 'rebased onto main; rerun tests' -t fix-login \
  --operation-id 12345678123456781234567812345678 --json

The reply includes operation_id, scope.kind: "work_store", and replayed. If omitted, an ID is generated for that invocation. A keeper exchange can fail after committing mail: an uncertain error preserves that ID in error.recovery. Reconcile first; an explicit identical send with the original ID against the same work store replays its receipt, without creating another Mail. Changing the payload under the same ID is refused. Do not blindly retry with a fresh durable ID.

MCP’s phux_mail_send accepts the same durable operation_id. Its optional idempotency_key is a different identity: an invocation in one adapter’s in-memory ledger. Adapter receipt documents expose adapter_receipt_id (the old operation_id field remains its alias) and scope.kind: "mcp_adapter". Retrying the same adapter key returns its cached outcome, including failure. Explicit durable recovery may use a new adapter key with the original mail operation ID and identical arguments; restarting the adapter does not erase the work-store receipt.

Sending mail only stores it. Nothing is ever typed into the recipient’s pane: its harness takes the mail and puts it in the agent’s conversation, once, framed as a message from another agent rather than from the user.

HarnessHow mail arrives
pi, Oh My Pia phux.mail follow-up message; starts a turn when the agent is idle
OpenCodea queued synthetic message in the session the pane shows; resumes it when idle
Claude Code (plugin)hook context on session start, prompt submit and after each tool; a block at stop so the agent goes on and handles it
Grokhook context after each tool, and a block at stop

Claude Code and Grok only have hooks, so an agent idle at its prompt sees its mail at its next hook. Workers whose conversation an SDK controller owns (PHUX_AGENT_REPORTING=0) get no mail from their hooks either: the controller decides what enters that conversation.

The harness side is three commands. phux mail wait --json holds until there is mail and takes it; with --until-stdin-closes it gives up, taking nothing, when the harness that started it exits, however abruptly. phux mail hook-context --event EVENT prints the hook reply. A harness that took mail but could not inject it returns it with phux mail release ID..., and mail whose output cannot be written is released by the command itself, as is a take whose reply the keeper could not send. Taken mail still shows as unread in phux mail read.

claim take grants every path or none, and exits 1 naming the holders on a conflict. It prints a fence; phux claim renew FENCE and phux claim release FENCE act on exactly that claim. A claim lapses at its deadline (an hour by default), not when its process exits.

Claims and addresses are advisory. They tell agents who is working where. Nothing stops a write, and an address is not proof of who sent a message.

Plan usage

phux agent usage prints the AI plan limits this machine can see: Claude Code’s 5-hour and weekly windows, Codex’s limits, and Grok Build’s allowance, with how much is used and when each resets.

It reads each vendor’s own sign-in on this machine and sends it only to that vendor:

VendorReadsSends, and only to
Claude CodeKeychain item Claude Code-credentials, else ~/.claude/.credentials.json; ~/.claude.jsonThe access token, to api.anthropic.com
Codex~/.codex/sessions/**/rollout-*.jsonl and ~/.codex/auth.jsonWhen those logs are over 10 minutes old: the access token and account id, to chatgpt.com
Grok Build~/.grok/auth.jsonThe session token and user id, to cli-chat-proxy.grok.com

Tokens are never refreshed, written, or logged, and travel only over HTTPS. An expired sign-in shows as unavailable until you use that agent again. Requests to one vendor are at least two minutes apart, with longer waits after a rate limit.

The usage plugin, part of the starter distribution, runs phux agent usage --publish when a client attaches or an agent changes state. That shares the numbers with every client allowed to see the whole server, including paired devices such as a phone. It shares an anonymous account fingerprint, never an email or a token.

Agents without an integration

Any program can report its state by writing an escape sequence to its terminal, with no integration and no socket:

printf '\033]7501;state=blocked:kind=permission:app=mytool\033\\'

The program protocol specifies it, and program sequences covers the phux-ask question title and the other sequences phux reads.

A tool phux’s agent rules recognize can also report through an agent session:

phux agent session open --provider mytool @7
phux agent emit --type prompt --data '{"text":"fix the login bug"}' @7
phux agent emit --type ask --data '{"id":"q1","question":"Allow?","suggestions":["yes","no"]}' @7
phux agent emit --type stop @7
phux agent session close @7

prompt and tool_start mean working, ask means blocked, and stop means done. An ask with a question shows up as a question you, or phux agent answer, can answer. Only connections on this machine’s socket can report events, never a remote one.

Without a session, phux agent set --name NAME --kind KIND @7 tells phux who is in the pane, and phux agent report-state @7 working reports state from a hook. Events and hook reports reach the pane’s state only for a program phux recognizes; any other program can declare its state with phux agent set --state.

Agents phux runs for you

Some agents, OpenCode first, can run under phux through the Agent Client Protocol instead of in a terminal. See ACP sessions.

Safety

The focused pane belongs to a person. Scripts and agents should address panes by @N, never .. The integrations refuse to type into the pane their own agent runs in.

Take the wheel when you need it. phux take @7, or C-a W in the terminal UI, gives you exclusive input to a pane until you release it with phux give @7 or C-a g, or detach. Agents and automation can’t take a pane a person holds. phux signal @7 freeze pauses an agent mid-step, and resume lets it continue.

Destructive commands ask first. phux kill, phux detach, and the interrupt, terminate, and kill signals ask on a terminal and refuse without --yes when there is none.

An agent started with phux agent start gets a narrower key. It can list, read, and type into panes in its own session, but not create, kill, signal, or reorganize anything, and never more than you can. The key ends when the session is deleted or the server stops (an in-place phux upgrade keeps it). This is not a sandbox. Any program running as your user can still reach the server’s main socket with full access.

Held actions wait for you. A device or automation key enrolled with ?signal in its scope has its kills and signals held until a person decides:

phux approvals          # what is waiting
phux approve ID
phux deny ID

Nothing on this machine’s own socket is ever held. See Remote machines for keys and scopes.

Commands agents use

The commands an agent drives phux with. The command line reference has their arguments, and the parity reference names the MCP tool for each or says why it is command-line only.

agent answer, agent prompt, agent send-keys, agent wait, approvals, ask, channel, config agents, config run, host add, host discover, host ls, host renew, host upgrade, kill, launch, logs, ls, mcp, new, organize, play, rec mark, relaunch, resize, resource methods, resource show, resource wait, restore, rm, run, signal, snapshot, spawn, status, update, wait, watch, whoami, mail send, mail read, mail ack, claim take, claim renew, claim release, claim list.

Debugging

  • phux agent explain @7 shows which evidence decided the state, and what each rule saw.
  • phux agent explain --file screen.txt --kind claude tests rules against a saved screen without a server.
  • phux watch --json @7 shows the events, such as agent_state and asked, as they arrive.
  • phux agent log @7 prints an agent session’s events.
  • phux doctor checks the Claude Code wrapper.