phux CLI reference
The complete phux command surface: one section per invocation path, each carrying the exact long help of the binary that generated it.
Full source summary
The complete phux command surface: one section per invocation path, each carrying the exact long help of the binary that generated it. Rendered from the argument parser itself, so the flags, defaults, and descriptions shown here are the ones the binary enforces.
Each section below is the verbatim --help text for one invocation path, rendered by the same argument parser the binary runs — flags, defaults, value names, and descriptions here are the ones the binary enforces. Hidden internal subcommands are omitted, exactly as they are from --help itself.
phux
phux — a terminal multiplexer you can drive by hand or script.
Run `phux` with no arguments to attach to your session (auto-starting a
server if needed). The control verbs below read and drive panes without a
TTY, and most accept `--json` for clean, scriptable output.
ATTACH / SERVE
attach Attach to a session (interactive)
server Run a server in the foreground
mcp Run the bundled MCP stdio adapter
host Register the machines phux talks to: remotes and satellites
service Keep a server running across logout and reboot
update Update phux to the latest release, keeping sessions alive
upgrade Hot-swap the running server binary, keeping sessions alive
INSPECT
ls List sessions
status Report the running server: pid, uptime, version, clients, logs
perf Show the server's performance telemetry, live or as a snapshot
snapshot Capture a pane's screen as JSON or a boxed view
watch Stream a pane's live events (bell, title, output, lifecycle)
rec Record a pane to an asciinema cast, a GIF, or an APNG
play Play a recording back as a live pane
agent Observe agents, send prompts, answer questions, and wait for turns
DRIVE
new Create a session
spawn Create a pane without attaching
launch Start a configured agent integration in a new pane
kill Kill a session, window, pane, or the server itself
detach Detach clients from a session
insert-pane Insert an already-created pane into a layout
move-pane Move an existing pane beside another, across sessions too
swap-pane Swap two existing pane leaves
rename Rename a session
resize Set a pane's grid size, with no TTY
send-keys Send keys to a pane
paste Paste text into a pane (bracketed when the pane asks)
run Run a command in a pane and capture its exit code
wait Block until a pane meets a condition
ask Report an agent ask event for a pane
SUPERVISE
take Seize exclusive input authority over a pane
give Release the input authority taken with `take`
signal Send a POSIX signal to a pane's process group
ORGANIZE
tag Read and write a pane's tags (address them with #tag)
skill Print the agent skill this binary ships with
completion Print a shell completion script for phux
doctor Diagnose the install: config, socket, server, plugins
logs Show where phux's logs live, or tail one of them
config Inspect config and run configured plugin actions
plugin Manage local plugin manifests in config
workspace Inspect worktrees and save/restore session archives
worktree Create, open, list, and remove worktree-bound sessions
FEDERATION
pair Mint, rotate, or revoke remote credentials
relay Run a standalone relay, or enroll a route with it
TARGET is a session name, `name:window`, `name:window.pane`, `@id`,
`#tag`, or `.` (focused). `=` is reserved for the
attached view's focus history. The same selectors work across
kill/snapshot/send-keys/run/wait/ask.
Usage: phux [OPTIONS] [COMMAND]
--rec <PATH>
Record this session while it runs and write the result to PATH.
The format follows the extension (.cast, .gif, .png, .apng); pass
--rec-format to override. A path with no extension gets `.gif`.
Examples:
phux --rec demo.gif
phux attach work --rec demo.cast
--rec-format <FMT>
Output format for --rec, overriding the extension
Possible values:
- cast: asciinema cast — the archival, re-renderable artifact
- gif: Animated GIF — shareable and embeddable anywhere
- apng: Animated PNG — truecolor, no quantization, larger files
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--skill [<SCOPE>]
Print compiled agent guidance, optionally scoped, then exit
Possible values:
- quick: Essential read-act-wait-verify guidance and safety rules
- agent: Quick guidance plus agent identity and lifecycle supervision
- terminal: Quick guidance plus terminal screen and input mechanics
- full: The complete guide and command inventory
--remote <[USER@]HOST[:PORT]>
Attach to a phux server on another machine, ssh-style: `phux --remote me@mini`. Belongs to the naked `phux` attach alone; `phux attach --remote` carries its own copy (and the `--code` / `--no-enroll` modifiers that go with it)
--capabilities
Print machine-readable capabilities with `--json`, then exit
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
EXIT STATUS
0 Success.
1 Failure: no server, no such target, or the verb itself failed.
2 Usage error, or the server refused the request.
3 Unanswerable: the selector was resolved against a partial view
of the fleet (a federation satellite was unreachable). Retry
once the link is back — unlike 1, the target may exist.
124 `phux wait` gave up because `--timeout` expired.
125 `phux run` gave up because `--timeout` expired; otherwise
`run` mirrors the exit code of the command it ran, so
`phux run … && next` composes like a shell.
ENVIRONMENT
PHUX_SOCKET UDS path for the CLI verbs and the server. A `--socket`
flag overrides it; default is
$XDG_RUNTIME_DIR/phux/phux.sock (or /tmp/phux-$USER/...).
PHUX_WS_ADDR Also accept WebSocket clients on HOST:PORT. Equivalent to
`phux server --listen`, which overrides it.
PHUX_WS_SECURE Force TLS + token auth on a loopback --listen address
(exercise the remote path locally).
PHUX_WS_TLS_CERT Operator-supplied server cert/key (PEM), instead of the
PHUX_WS_TLS_KEY auto-provisioned self-signed pair used off-loopback.
PHUX_WS_TOKENS Pairing-token store the server reads and `phux pair` writes.
PHUX_QUIC_ADDR Also accept QUIC clients on HOST:PORT. Equivalent to
`phux server --quic`, which overrides it.
PHUX_WT_ADDR Also accept WebTransport (HTTP/3 over QUIC) clients on
HOST:PORT. Equivalent to `phux server --webtransport`.
PHUX_SSH OpenSSH-compatible program a federation hub spawns to
dial ssh:// satellites (default: `ssh` on PATH).
PHUX_TAILSCALE Tailscale-compatible CLI `phux pair` runs to detect the
overlay address (default: `tailscale` on PATH).
PHUX_AUTO_SPAWN_EXIT_AFTER_IDLE
Give an auto-spawned server an idle limit in seconds
(1..=86400), as if it were started with
`phux server --exit-after-idle`. Unset means no limit,
which is the multiplexer default. For test harnesses and
CI jobs that cannot guarantee their own cleanup runs.
PHUX_LOG Write logs to this file (server tees; client writes here).
PHUX_LOG_FORMAT text (default) or json — log line format.
RUST_LOG tracing level filter, e.g. phux=debug.
Run `phux server --listen 127.0.0.1:8787` to expose a port; see
`phux help server` for the remote/TLS details.
phux agent
List, show, explain, set, or clear per-pane agent state.
Inference (`list`/`show`/`explain`) reports the agent phux infers is running in each pane. `set`/`clear` write and delete an explicit per-pane agent identity that overrides inference.
Usage: phux agent [OPTIONS] <COMMAND>
Commands:
list List every pane's detected or declared agent and current state [aliases: ls]
show Show inferred state for one pane
explain Explain the evidence behind one pane's state
set Declare the agent identity and state associated with a pane
report-state Report hook-sourced lifecycle evidence to the pane's detector
wait Block until a pane's agent TRANSITIONS into a lifecycle state
prompt Hand an agent a turn's worth of work, with a delivery receipt
send-keys Send keys to a pane, but only if it still hosts the expected agent
answer Answer a pane's pending agent question by validated choice
start Start an agent INSIDE an existing shell pane, and return when it is ready for input
clear Clear a pane's declared agent identity
install-claude Make plain `claude` launch inside phux and declare its identity
uninstall-claude Remove the claude-in-phux shim and shell activation
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux agent answer
Answer a pane's pending agent question by validated choice.
The `asked` event carries the question AND the suggestions the asking agent itself published, so an orchestrator can reply with a string the agent named instead of a blind keystroke. That is the contract: the bytes phux types are always one of the agent's own published answers, unless you pass `--allow-unlisted`.
`--id` is required, and the pane must still be asking that exact question. Answering one the agent already moved past would type into whatever is on screen now, which is the failure this verb exists to prevent — so a stale id, an unidentified ask, and a pane that is not asking at all are all refusals with nothing written.
The answer rides one acknowledged, idempotent input batch: a trusted paste followed by Enter, written and confirmed as a single operation.
Usage: phux agent answer [OPTIONS] --id <ID> <TARGET>
Arguments:
<TARGET>
Target selector (resolves to one pane)
Options:
--id <ID>
The id of the ask being answered, as carried by the `asked` event. Required: answering "whatever is being asked right now" is a level read, and a level read cannot tell one question from the next
--choice <N>
Send the Nth published suggestion, 1-based, verbatim
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--text <TEXT>
Send exactly this text. Refused when the ask published a suggestion set and this is not in it (see `--allow-unlisted`)
--allow-unlisted
Permit a `--text` answer outside the ask's published suggestions
--json
Emit machine-readable JSON instead of the one-line confirmation
-h, --help
Print help (see a summary with '-h')
phux agent clear
Clear a pane's declared agent identity
Usage: phux agent clear [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target selector (resolves to one pane). Omit for the focused pane
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux agent explain
Explain the evidence behind one pane's state.
With `--file` this runs OFFLINE: it evaluates the compiled detection manifests against a captured screen and contacts no server at all. That is the mode for authoring and debugging a manifest, because it prints the text every region resolved to on that screen — a rule scoped to a region that comes back empty can never match, and nothing else makes that visible (the detector fails safe to `idle`, silently).
The capture is `phux snapshot --json` output or a plain text screen, one viewport row per line; `-` reads stdin. A capture carries no OSC title, so pass `--title` to exercise title-scoped rules.
Usage: phux agent explain [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target selector (resolves to one pane). Omit for the focused pane. Not used in offline (`--file`) mode
Options:
--json
Emit machine-readable JSON instead of the table
--file <PATH>
Evaluate a captured screen offline instead of querying the server. `-` reads stdin
--kind <KIND>
Agent kind whose manifest to evaluate, or one of its binary aliases. Required with `--file`: offline there is no foreground process group to identify the agent from
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--title <TEXT>
OSC 0/2 title to evaluate `title`-scoped rules against. Captures do not carry one, so it defaults to empty
--format <FORMAT>
How to read `--file`. `auto` picks JSON when the first non-whitespace byte is `{`
[possible values: auto, json, text]
-h, --help
Print help (see a summary with '-h')
phux agent install-claude
Make plain `claude` launch inside phux and declare its identity
Usage: phux agent install-claude [OPTIONS]
Options:
--shell <SHELL>
Shell rc file to activate (auto-detected from SHELL)
[possible values: zsh, bash, fish]
--real <PATH>
Absolute path to the real Claude executable (auto-detected from PATH)
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux agent list
List every pane's detected or declared agent and current state
Usage: phux agent list [OPTIONS]
Options:
--json
Emit machine-readable JSON instead of the table
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux agent prompt
Hand an agent a turn's worth of work, with a delivery receipt.
The prompt text and Enter ride ONE acknowledged, idempotent operation, so a caller that does not get an answer can ask again under the same operation id without risking a duplicate turn — the failure fire-and-forget input cannot avoid, because its only recovery is a resend. Enter is last, so a partial write can only drop the submission and leave unsubmitted text, never submit a truncated prompt.
The acknowledged path is required, not preferred: an older server or a satellite target is refused rather than downgraded, because a success code that means "the bytes are in the kernel queue" on one host and "accepted, maybe dropped" on another is not branchable.
An OK is a kernel-queue receipt, not a consumption receipt. If delivery comes back UNKNOWN, do not resend: read the pane.
With `--wait` the same process holds one connection across the submit, so every state change it sees is strictly post-write, and the gate is satisfied only by an observed TRANSITION — never by a level read of the current state, which a crashed agent also reads as.
The server has ONE acknowledged input lane, so do not prompt a fleet in parallel: serialize it, or all but one caller collides.
Usage: phux agent prompt [OPTIONS] <TARGET> <TEXT>
Arguments:
<TARGET>
Target selector (resolves to one pane)
<TEXT>
The prompt text. Single-line: a raw newline is refused, because a pane that has not enabled bracketed paste turns each one into a separate submission and no client can observe that mode
Options:
--expect-agent <NAME>
Require the pane's declared agent name to be this one
--expect-kind <KIND>
Require the pane's declared agent kind slug to be this one
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--wait
After delivering, block until the agent transitions into a lifecycle state
--until <STATE>
Lifecycle state to wait for; repeat to OR several. Defaults to `idle`, `blocked`, `done`. Requires `--wait`
[possible values: idle, working, blocked, done]
--timeout <SECS>
Give up waiting after this many seconds and exit 124. The prompt was still delivered. Requires `--wait`
--json
Emit the machine-readable result document instead of staying quiet on success
-h, --help
Print help (see a summary with '-h')
phux agent report-state
Report hook-sourced lifecycle evidence to the pane's detector
Usage: phux agent report-state [OPTIONS] <TARGET> <STATE>
Arguments:
<TARGET>
Target selector (resolves to one pane)
<STATE>
Lifecycle evidence from the integration hook
[possible values: working, blocked, done]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux agent send-keys
Send keys to a pane, but only if it still hosts the expected agent.
The agent-addressed sibling of top-level `phux send-keys`, and it differs from it in exactly one way: it re-checks the pane's declared agent identity immediately before writing and refuses if the occupant changed. `phux send-keys` addresses a pane and deliberately checks no identity; use that one when a pane is what you mean.
Every key is validated before any byte is written, so a typo in the third key cannot leave the first two delivered — and since the whole batch now rides ONE acknowledged operation, that all-or-nothing promise covers delivery as well as validation. A caller that loses the answer can ask again under the same operation id instead of guessing whether the keys landed. For prose you want an agent to act on, `phux agent prompt` is the verb.
Usage: phux agent send-keys [OPTIONS] <TARGET> <KEYS>...
Arguments:
<TARGET>
Target selector (resolves to one pane)
<KEYS>...
Key specs: named keys (`Enter`, `C-c`, `M-x`, `Up`) or literal text. A literal run immediately before `Enter` is sent as one submission-safe paste
Options:
--expect-agent <NAME>
Require the pane's declared agent name to be this one
--expect-kind <KIND>
Require the pane's declared agent kind slug to be this one
--json
Emit machine-readable JSON instead of staying quiet on success
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux agent set
Declare the agent identity and state associated with a pane
Usage: phux agent set [OPTIONS] --name <NAME> [TARGET]
Arguments:
[TARGET]
Target selector (resolves to one pane). Omit for the focused pane
Options:
--name <NAME>
Human-facing agent name (required, non-empty)
--kind <KIND>
Open-vocabulary kind slug, e.g. "claude" or "codex"
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--state <STATE>
Declared lifecycle state
[possible values: unknown, idle, working, blocked, done]
--attention <ATTENTION>
Declared attention priority (defaults derive from state)
[possible values: none, low, normal, high]
--session <SESSION>
Free-form association label (fleet/job name)
-h, --help
Print help
phux agent show
Show inferred state for one pane
Usage: phux agent show [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target selector (resolves to one pane). Omit for the focused pane
Options:
--json
Emit machine-readable JSON instead of the table
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux agent start
Start an agent INSIDE an existing shell pane, and return when it is ready for input.
The layout-free sibling of `phux launch`: it creates, splits, and moves nothing. `launch` returns a Terminal id ("a pane now exists"); this returns a readiness assertion about a pane that already existed, which is a different success statement and therefore a different verb. The launch resolver is shared — the same integration template, the same argv, the same provider-native session identity — only the delivery differs: the pane's child is a live shell, so the command is typed as one quoted line and submitted as one acknowledged `APPLY_INPUT` batch.
Ready is the FIRST detector publication after submit, not `state == idle`. No shipped detection manifest asserts `idle` positively — it is the fail-safe fallthrough — so a gate built on it would report ready for a pane where nothing launched. `--json` therefore reports the provenance of the answer (which rule matched, or that none did) rather than an opaque word.
A `--kind` with no detection manifest is refused up front: without one the readiness contract is unenforceable and the verb could only time out, after having typed into the pane. `phux launch` and `phux spawn` keep working for any agent whatsoever, because neither promises readiness.
Usage: phux agent start [OPTIONS] --kind <KIND> --target <TARGET> <NAME> [-- <ARGS>...]
Arguments:
<NAME>
Human-facing agent name to bind to the pane. Must match `^[a-z][a-z0-9_-]{0,31}$`
[ARGS]...
Extra arguments appended to the integration's launch command
Options:
--kind <KIND>
Detection-manifest kind the started agent must identify as (`claude`, `codex`, ...). `phux agent explain --file` lists the loaded roster
--target <TARGET>
Existing pane to start into. Never created, split, or moved
--integration <ID>
Launch integration id. Defaults to the unique enabled integration whose `[agent_identity] kind` matches `--kind` (so `--kind claude` resolves `claude-code`), else the kind slug itself; two claimants are refused by name
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--timeout <SECS>
Give up waiting for readiness after this many seconds and exit 124. The command was still typed
--no-wait
Submit and return without claiming readiness (exit 0, `ready: false`)
--force
Skip the available-shell precondition. Types the launch command into the pane whatever is running there
--json
Emit the machine-readable result document instead of a line
-h, --help
Print help (see a summary with '-h')
phux agent uninstall-claude
Remove the claude-in-phux shim and shell activation
Usage: phux agent uninstall-claude [OPTIONS]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux agent wait
Block until a pane's agent TRANSITIONS into a lifecycle state.
Satisfied only by an observed transition, never by a level read of the current state. That distinction is the point of the verb: `idle` is normally the detector's fail-safe fallthrough. Claude's OSC 9;4 remove signal can assert it positively, but a level still cannot prove that the transition happened after this wait's baseline. A gate that fired on a level would return success on a corpse, instantly, and on any pane with no manifest at all.
The consequence is deliberate: a pane already resting in a target state when the wait begins times out (124) rather than succeeding. `phux agent show` is the level read; this verb reports transitions.
Subscribes before reading the baseline, so no transition is lost in between, and re-reads on the `phux wait` cadence to recover an edge a dropped notification never delivered. A record that goes away mid-wait ends it as a departure (exit 1), which is not a completion.
Usage: phux agent wait [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target selector (resolves to one pane). Omit for the focused pane
Options:
--until <STATE>
Lifecycle state to wait for; repeat to OR several. Defaults to `idle`, `blocked`, `done` — the three ways a turn ends. `unknown` is not spellable: it is departure, not a state
[possible values: idle, working, blocked, done]
--timeout <SECS>
Give up after this many seconds and exit 124. Unbounded when omitted, matching `phux wait` — always pass one in a script
--json
Emit the machine-readable result document instead of a line
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux ask
Report that an agent in a pane is waiting on a human answer.
This is the opt-in hook contract for configured integrations: it emits the same `asked` event as the `phux-ask` title sentinel without writing escape sequences into the target terminal. TARGET is resolved client-side and the command neither attaches nor resizes the pane.
Examples:
phux ask work:1.0 --id deploy --suggest Yes --suggest No "Deploy?"
phux ask @3 --json "Need approval"
Usage: phux ask [OPTIONS] <TARGET> <QUESTION>
Arguments:
<TARGET>
Target selector: session, session:window, session:window.pane, @id, or `.` (focused). `=` is unsupported by headless commands
<QUESTION>
Human-facing question text
Options:
--id <ID>
Stable question id for answer correlation
[default: ""]
--suggest <TEXT>
Suggested answer. Repeat to preserve display order
--elapsed-seconds <SECS>
Seconds the agent has already been waiting
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux attach
Attach to a session (interactive).
With no name, attaches to the most-recently-focused session, auto-spawning a server if none is running. Requires a TTY.
A name enrolled in the host registry (`phux host enroll`, `phux host add`) shadows a local session of the same name: `phux attach NAME` dials the registered host instead of the local socket. Pass `--socket` to force the local reading of the name.
Usage: phux attach [OPTIONS] [SESSION]
Arguments:
[SESSION]
Session name (matches the name used at creation time).
Omit to attach to the most-recently-focused session.
Options:
--quic <HOST:PORT>
Attach over QUIC to a remote `phux server --quic` listener at this `HOST:PORT` instead of the local Unix socket. HOST may be an IP literal or a DNS name (e.g. a Tailscale `MagicDNS` name), resolved before dialing. QUIC is always TLS 1.3-encrypted. A target resolving to loopback trusts the server's self-signed cert for local dev; any routable address requires `--cert-fingerprint` (the value `phux pair` prints on the server host)
--ws <URL>
Attach over WebSocket to a `phux server --listen` endpoint. Use `ws://HOST:PORT` for loopback dev, or `wss://HOST:PORT` with `--token` and `--cert-fingerprint` for routable remote attach. This is the TCP fallback when UDP/QUIC is blocked
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--token <TOKEN>
Bearer pairing token (hex) for an authenticated QUIC listener, as minted by `phux pair`. QUIC sends it as the stream's opening preamble; WebSocket sends it as `Authorization: Bearer`. Requires `--quic` or `--ws`
--cert-fingerprint <FP>
Pin the QUIC server's certificate by its SHA-256 fingerprint (the value `phux pair` prints). Required to dial any non-loopback `--quic`/`--ws wss://` address. Requires `--quic` or `--ws`
--tls-server-name <NAME>
TLS server name (SNI) to offer the remote listener. QUIC defaults to `localhost`; WebSocket defaults to the URL host. Requires `--quic` or `--ws`
--remote <[USER@]HOST[:PORT]>
Attach to a phux server on another machine, ssh-style: `--remote me@mini`. Resolves to a registered host when there is one, otherwise pairs the host first (over a `--code`, or over your existing ssh trust) and registers the result, so every later attach is a direct QUIC dial with no ssh in the path.
PORT defaults to 8788, the port a server auto-binds on its overlay address. The `user@` half names the ssh destination used to pair; it is not sent on the wire.
--code <LINK>
Pair `--remote` from a `https://phux.phall.io/connect?...` link (or its `phux://connect?...` spelling) instead of over ssh — the same link `phux pair` prints and `phux pair --qr` renders. Quote it: it contains `&`
--no-enroll
Never shell out to ssh for `--remote`. An unregistered host is refused with its remedies named instead of paired
--rec <PATH>
Record this session while it runs and write the result to PATH.
The format follows the extension (.cast, .gif, .png, .apng); pass
--rec-format to override. A path with no extension gets `.gif`.
Examples:
phux --rec demo.gif
phux attach work --rec demo.cast
--rec-format <FMT>
Output format for --rec, overriding the extension
Possible values:
- cast: asciinema cast — the archival, re-renderable artifact
- gif: Animated GIF — shareable and embeddable anywhere
- apng: Animated PNG — truecolor, no quantization, larger files
-h, --help
Print help (see a summary with '-h')
phux completion
Print a shell completion script on stdout.
The script is generated from the binary's own argument parser, so it always matches the verbs this build actually accepts. It contacts no server and reads no config, which is what makes it safe to run from a shell startup file.
Regenerate after upgrading phux; a stale script completes verbs the installed binary no longer has.
Install it the way your shell prefers. Examples:
phux completion zsh > ~/.zfunc/_phux (~/.zfunc must be on $fpath)
phux completion bash > ~/.local/share/bash-completion/completions/phux
phux completion fish > ~/.config/fish/completions/phux.fish
Usage: phux completion [OPTIONS] <SHELL>
Arguments:
<SHELL>
Shell dialect to generate for
[possible values: bash, elvish, fish, powershell, zsh]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux config
Inspect, scaffold, and reload the phux config file.
phux is config-driven: defaults ship in the binary and your `config.toml` is a sparse overlay merged on top. These subcommands never touch a running server, except `reload`, which signals attached clients to re-read their config in place.
Usage: phux config [OPTIONS] <COMMAND>
Commands:
init Write a commented starter config to the canonical path
path Print the resolved config path. Pure path math — prints the path whether or not the file exists
check Validate the config and report every problem, with full key paths
show Print the effective config (shipped defaults + your overrides) as TOML. With `--default`, print the shipped defaults verbatim instead, ignoring any user config. With `--layers`, print which layer of the `extends` stack set each effective key instead of the values
plugins List plugin manifests declared by `[[plugins]]`
agents List configured agents, merged with live pane state when a server is running
reload Re-read the layered config and apply it to running clients in place
run Execute one action declared by a configured plugin manifest
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux config agents
List configured agents, merged with live pane state when a server is running
Usage: phux config agents [OPTIONS]
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux config check
Validate the config and report every problem, with full key paths.
The loader already refuses an unknown key, but it names only the leaf field (`unknown field 'enabledd'`) and stops at the first one. This reports `sidebar.enabledd`, names the layer file that introduced it, and finds every problem in one pass — so a config with four typos takes one edit, not four.
Exits 0 when clean and 1 when anything was found, so it can gate a dotfiles CI run.
Usage: phux config check [OPTIONS] [PATH]
Arguments:
[PATH]
Config file to check. Defaults to the resolved config path
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux config init
Write a commented starter config to the canonical path.
The file is the shipped defaults, fully commented out: inert until you uncomment a line, so the binary's defaults stay authoritative. Refuses to overwrite an existing config unless `--force`.
With `--distro`, the scaffold additionally carries one active `extends` line layering the named starter distribution (a bundled name like `herdr`, or a path to a distro layer `.toml`) between the shipped defaults and your file.
Usage: phux config init [OPTIONS]
Options:
--force
Overwrite an existing config file instead of refusing
--distro <NAME_OR_PATH>
Starter distribution to extend: a bundled name (resolved under `$PHUX_DISTROS_DIR`, the XDG data dir, or the repo checkout) or a path to a distro layer `.toml` / directory
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux config path
Print the resolved config path. Pure path math — prints the path whether or not the file exists
Usage: phux config path [OPTIONS]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux config plugins
List plugin manifests declared by `[[plugins]]`
Usage: phux config plugins [OPTIONS]
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux config reload
Re-read the layered config and apply it to running clients in place.
Validates the config locally first (a broken file fails here, with the parse error, and nothing is signalled), then rings the `phux.config.reload/v1` doorbell on the server so every attached client re-reads its own config file and rebuilds keybindings, theme, and status bar without restarting. Clients whose re-read fails keep their previous config. Deliberately explicit — the config file is never watched.
Usage: phux config reload [OPTIONS]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux config run
Execute one action declared by a configured plugin manifest
Usage: phux config run [OPTIONS] <PLUGIN> <ACTION>
Arguments:
<PLUGIN>
Configured plugin id
<ACTION>
Plugin-local action id
Options:
--timeout <SECS>
Give up after this many seconds. Omit to wait indefinitely
--cwd <PATH>
Override the action cwd. Relative paths resolve under plugin root
--json
Emit the structured action result as JSON
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux config show
Print the effective config (shipped defaults + your overrides) as TOML. With `--default`, print the shipped defaults verbatim instead, ignoring any user config. With `--layers`, print which layer of the `extends` stack set each effective key instead of the values
Usage: phux config show [OPTIONS]
Options:
--default
Show the shipped defaults verbatim, not the merged result
--layers
Attribute each effective key to the layer that set it (embedded defaults / `extends` layers / your config file)
--json
With --layers: emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux detach
Detach clients from a session, from outside the attach UI.
The CLI counterpart to the `C-a d` keybinding. With `SESSION`, detaches every client attached to that session; with no argument, detaches every attached client on the server. Each target client's TUI exits cleanly. Useful for scripting or reclaiming a session that's attached (or wedged) elsewhere.
Usage: phux detach [OPTIONS] [SESSION]
Arguments:
[SESSION]
Session to detach clients from. Omit to detach every attached client on the server
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux doctor
Diagnose a phux install: config, socket, server, plugins.
Composes the checks that already exist as separate verbs and reports one verdict, because knowing which four commands to run and how to read each one is exactly what someone debugging phux does not have.
Read-only. Exits 1 if any check failed; warnings alone exit 0, since a stopped server is a normal state and not a broken install.
Usage: phux doctor [OPTIONS]
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux give
Give back the input wheel of a pane.
Releases the input lease taken with `phux take`, returning the pane to open input. A no-op if you do not hold the lease. TARGET is a selector.
Usage: phux give [OPTIONS] <TARGET>
Arguments:
<TARGET>
Target selector (resolves to one pane)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux host
Register the machines phux talks to: remotes and satellites.
One namespace over both machine registries. `--role remote` (the default) manages the servers `phux attach <name>` dials; `--role satellite` manages the peers a federation hub dials for its users. The two registries stay separate in config (`[[remote]]` vs `[[satellites]]`) because they encode opposite trust directions; this verb absorbs the split into a flag.
Usage: phux host [OPTIONS] <COMMAND>
Commands:
add Register a machine, or replace an entry with the same name
enroll Set up a machine over ssh, end to end, and register it
ls List registered machines from both registries [aliases: list]
rm Remove a registered machine. Its token file is left in place [aliases: remove]
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux host add
Register a machine, or replace an entry with the same name.
`--role remote` (the default) registers a server `phux attach <name>` can dial; `--role satellite` registers a peer this hub dials for its users. Updating replaces the whole entry, so repeat `--token-file` / `--cert-fingerprint` when re-adding a name or the auth material is cleared.
Usage: phux host add [OPTIONS] <NAME> <ENDPOINT>
Arguments:
<NAME>
Local label for the machine
<ENDPOINT>
Endpoint URI: `quic://HOST:PORT`, `wss://HOST:PORT`, or `ssh://HOST`. `ssh://` rides your existing ssh trust and needs no pairing; the other two need a token and a certificate pin
Options:
--role <ROLE>
Which registry the entry lands in
Possible values:
- remote: A server this machine attaches to — a `[[remote]]` entry
- satellite: A peer this hub dials for its users — a `[[satellites]]` entry
[default: remote]
--token-file <PATH>
Absolute path to a file holding the pairing token minted by `phux pair` on the other machine
--cert-fingerprint <FP>
The other machine's TLS certificate SHA-256 fingerprint, as printed by `phux pair`. Required for `quic://` and `wss://`
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--session <NAME>
Session to attach on arrival (`--role remote` only). Omitted: the remote server's own last-attach memory decides
--disabled
Register the entry but leave it disabled (`--role satellite` only)
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux host enroll
Set up a machine over ssh, end to end, and register it.
Confirms phux is installed on HOST, installs its service unit so the server survives reboot, mints a pairing token there, and registers the result in the role-correct registry — `--role remote` (the default) yields an entry `phux attach <name>` dials with no flags and no hex strings typed by hand; `--role satellite` a peer this hub dials for its users. Uses the ssh trust you already have; it grants nothing ssh did not already grant.
A host with no reachable listener falls back to an ssh:// entry, which still gives you sessions that outlive the connection.
Usage: phux host enroll [OPTIONS] <HOST>
Arguments:
<HOST>
ssh destination, exactly as you would type it after `ssh` (`mini`, `me@mini`, or a `~/.ssh/config` alias)
Options:
--role <ROLE>
Which registry the enrolled machine lands in
Possible values:
- remote: A server this machine attaches to — a `[[remote]]` entry
- satellite: A peer this hub dials for its users — a `[[satellites]]` entry
[default: remote]
--name <NAME>
Local label to register. Defaults to HOST without any `user@`
--endpoint <HOST:PORT>
Address to register instead of the remote's detected overlay address. Accepts `HOST:PORT` (dialed over QUIC) or a full `quic://`/`wss://` URI
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--quic-port <PORT>
QUIC port to configure on the remote and register
[default: 8788]
--no-service
Skip installing the remote's service unit. The server will not come back on its own after a reboot
--ssh-only
Register an ssh:// entry without contacting the host at all
--session <NAME>
Session to attach on arrival (`--role remote` only)
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux host ls
List registered machines from both registries.
With no `--role`, remotes and satellites are merged into one table with a ROLE column; `--role` filters to one registry.
Usage: phux host ls [OPTIONS]
Options:
--role <ROLE>
Show only this registry
Possible values:
- remote: A server this machine attaches to — a `[[remote]]` entry
- satellite: A peer this hub dials for its users — a `[[satellites]]` entry
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux host rm
Remove a registered machine. Its token file is left in place.
With no `--role`, the name is resolved across both registries; a name registered in both is refused until `--role` disambiguates.
Usage: phux host rm [OPTIONS] <NAME>
Arguments:
<NAME>
Registered name
Options:
--role <ROLE>
Which registry to remove from. Omitted: both are searched
Possible values:
- remote: A server this machine attaches to — a `[[remote]]` entry
- satellite: A peer this hub dials for its users — a `[[satellites]]` entry
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux insert-pane
Insert an already-created pane into a session layout.
Both selectors must each resolve to exactly one local pane in the same session. This command does not spawn: create `NEW_PANE` first with `phux spawn`, then insert it. Omitted direction defaults horizontal.
Usage: phux insert-pane [OPTIONS] <TARGET> <NEW_PANE>
Arguments:
<TARGET>
Existing layout leaf beside which `NEW_PANE` is inserted
<NEW_PANE>
Already-created pane to insert; no implicit spawn occurs
Options:
--split <SPLIT>
Split axis: `horizontal` stacks the panes, `vertical` places them side-by-side
[default: horizontal]
[possible values: horizontal, vertical]
--ratio <RATIO>
Fraction assigned to TARGET; must be strictly between 0 and 1
[default: 0.5]
--json
Emit a schema-versioned JSON result or error
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux kill
Kill a session, window, pane, or the server itself.
`TARGET` uses the selector grammar (see the top-level help): `name`, `name:N`, `name:N.M`, `name:tag`, `@N`, `.`. The selector is resolved client-side against a server-state snapshot to a set of Terminals; the server is then asked to kill each.
`--server` stops the server process instead, ending every session on it. Local socket only.
Usage: phux kill [OPTIONS] <TARGET|--server>
Arguments:
[TARGET]
What to kill (selector)
Options:
--server
Stop the running server, ending every session it holds.
The server exits cleanly, so a supervised one stays stopped rather than being restarted. Note that the next `phux attach`/`new` will auto-spawn a fresh server: this stops the current one, it does not disable phux.
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux launch
Launch an agent integration in a new pane.
Resolves INTEGRATION (a `phux launch --list` id) to its `[launch]` command from an enabled plugin's integration template, then creates a pane running it. The integration also gives the pane its agent name and kind automatically, with no alias or per-shell config.
`--print` resolves and prints the argv without spawning (a server-free dry run). Extra agent arguments follow `--`: `phux launch codex -- --model o3`.
Usage: phux launch [OPTIONS] [INTEGRATION] [-- <EXTRA>...]
Arguments:
[INTEGRATION]
Integration id to launch (from `phux launch --list`)
[EXTRA]...
Extra arguments appended to the agent command, after `--`
Options:
--list
List launchable integrations from enabled plugins and exit
--print
Resolve and print the launch argv (and cwd) without spawning a pane — a server-free dry run
[aliases: --dry-run]
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--target <TARGET>
Existing local pane beside which to place the launched pane
--split <SPLIT>
Split axis for explicit placement (requires `--target`)
[default: horizontal]
[possible values: horizontal, vertical]
--ratio <RATIO>
Fraction of the split retained by TARGET (requires `--target`)
[default: 0.5]
-c, --cwd <DIR>
Working directory for a `working_directory = "workspace"` template. Defaults to the current directory
-h, --help
Print help (see a summary with '-h')
phux logs
Show where phux's logs live, or tail one of them.
Bare `phux logs` prints the inventory: the canonical server log (every spawn path writes it), the per-pid client logs, and the state dir that holds them — with existence, size, and age, so a fresh machine reads "not created yet" instead of an error. `--server` tails the server log and `--client` the newest client log (`--pid` picks a specific one); `-f` follows and `-n` sets the tail length. `--json` emits the inventory as a stable document.
Usage: phux logs [OPTIONS]
Options:
--server
Tail the canonical server log
--client
Tail the newest per-pid client log (or the one `--pid` names)
--pid <PID>
With --client: the client pid whose log to tail, instead of the newest
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-f, --follow
Follow the tailed log as it grows (needs --server or --client)
-n, --lines <LINES>
How many trailing lines to show (needs --server or --client)
[default: 200]
--json
Emit the path inventory as a stable JSON document instead of human text. Inventory only — it cannot combine with a tail
-h, --help
Print help (see a summary with '-h')
phux ls
List sessions on the running server.
Queries the running server and prints one line per session. Does not start a server: with no server running it reports as much and exits non-zero (like `tmux ls`). Pass `--json` for the stable, versioned machine shape instead of the human text.
Usage: phux ls [OPTIONS]
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux mcp
Run the bundled MCP stdio adapter.
This is a transparent launcher for the separate MCP companion binary. All arguments are forwarded unchanged. With no arguments it serves MCP over stdin/stdout; discovery modes include `--skill`, `--schema`, `--help`, and `--version`.
Usage: phux mcp [OPTIONS] [ARGS]...
Arguments:
[ARGS]...
Arguments forwarded unchanged to the MCP companion
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
phux move-pane
Move one existing pane beside another, even across sessions.
SOURCE is collapsed out of its current tree position and inserted beside TARGET. Both selectors must resolve to exactly one local pane. When TARGET lives in a different session the pane is re-parented on the server first — its process, scrollback, and id survive the move.
Usage: phux move-pane [OPTIONS] <SOURCE> <TARGET>
Arguments:
<SOURCE>
Pane to relocate
<TARGET>
Existing destination pane
Options:
--split <SPLIT>
Destination split axis: `horizontal` stacks the panes, `vertical` places them side-by-side
[default: horizontal]
[possible values: horizontal, vertical]
--ratio <RATIO>
Fraction assigned to TARGET; must be strictly between 0 and 1
[default: 0.5]
--json
Emit a schema-versioned JSON result or error
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux new
Create a new session and attach to it.
Creates the named session if it does not already exist, then attaches. Auto-starts a server if none is running. A name already in use is an error; omit the name to take the configured `session-name-template`, disambiguated with a numeric suffix.
With `--json`, creates the session *without* attaching and prints the seed pane's id as JSON instead. This neither attaches nor resizes, and the create is atomic server-side (no attach race). `--json` requires an explicit `-s NAME`, and a name already in use is an error (create-only, never create-or-attach).
Usage: phux new [OPTIONS] [NAME] [-- <COMMAND>...]
Arguments:
[NAME]
Session name. `phux new work` creates a session named "work". Omitted ⇒ the `session-name-template` (e.g. "default"), disambiguated with a numeric suffix if that name is taken
[COMMAND]...
Command (and arguments) to run in the seed pane instead of the default shell. Must follow `--`: `phux new work -- htop`
Options:
-s, --session <SESSION>
Session name in flag form — equivalent to the positional NAME, and the form required by `--json`. An error if it conflicts with NAME
-c, --cwd <CWD>
Working directory for the seed pane
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-e, --env <KEY=VALUE>
Environment assignment for the seed process. Repeat for multiple variables. Headless `--json` mode only
-h, --help
Print help (see a summary with '-h')
phux pair
Mint, rotate, or revoke a remote-consumer credential.
With no subcommand, mint one credential into the server's store and print its stable ID, one-time bearer secret, and certificate fingerprint. `rotate` replaces the bearer with a bounded overlap; `revoke` denies all generations on future connections. These operations update the store directly and take effect without restarting the server.
This never contacts a running server — it only writes the token file.
Usage: phux pair [OPTIONS]
phux pair <COMMAND>
Commands:
rotate Replace a credential's bearer secret with a bounded overlap
revoke Revoke every generation of a credential for new connections
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--tokens <PATH>
Versioned credential store to update. Defaults to `PHUX_WS_TOKENS`
--cert <PATH>
Server certificate PEM, used to print the pairing fingerprint. Defaults to `PHUX_WS_TLS_CERT`
--qr
Also render the pairing payload as a scannable QR code. The QR encodes the same `https://phux.phall.io/connect` one-tap link printed as text, so a phone can pair by scanning instead of typing. Needs a server address: pass `--host`, or let it fall back to a detected overlay address plus the `PHUX_WS_ADDR` port
--host <HOST:PORT>
Server address (`host:port`, or a full `ws://`/`wss://` URL) to embed in the connect link so it is fully self-contained. Omitted: derived from the detected overlay address and the `PHUX_WS_ADDR` port when possible; otherwise no link is printed (the device enters the address itself)
--name <NAME>
Human-readable server name to embed in the connect link, shown by the device in its server list. Omitted: the device picks a default
--json
Emit the mint, rotation, or revocation result as JSON on stdout. `phux host enroll` consumes the mint document over ssh
--migrate-legacy
Explicitly convert legacy anonymous token lines before pairing. Conversion preserves each bearer secret but stores only its verifier
-h, --help
Print help (see a summary with '-h')
phux pair revoke
Revoke every generation of a credential for new connections
Usage: phux pair revoke [OPTIONS] <CREDENTIAL_ID>
Arguments:
<CREDENTIAL_ID>
Stable credential ID printed when the credential was minted
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--tokens <PATH>
Versioned credential store to update. Defaults to `PHUX_WS_TOKENS`
--json
Emit the mint, rotation, or revocation result as JSON on stdout. `phux host enroll` consumes the mint document over ssh
-h, --help
Print help
phux pair rotate
Replace a credential's bearer secret with a bounded overlap
Usage: phux pair rotate [OPTIONS] <CREDENTIAL_ID>
Arguments:
<CREDENTIAL_ID>
Stable credential ID printed when the credential was minted
Options:
--overlap-seconds <SECONDS>
Seconds the previous generation remains valid. Its existing absolute expiry still wins when it is sooner; an already-expired credential cannot be rotated
[default: 300]
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--tokens <PATH>
Versioned credential store to update. Defaults to `PHUX_WS_TOKENS`
--json
Emit the mint, rotation, or revocation result as JSON on stdout. `phux host enroll` consumes the mint document over ssh
-h, --help
Print help
phux paste
Paste text into a pane.
Delivers the payload as ONE paste event to the resolved pane (`ROUTE_INPUT`), so the live pane is neither attached nor resized. When the pane's program has bracketed paste (DEC mode 2004) switched on, the server wraps the payload in paste markers and the program receives it as a single block — auto-indent stays off and multiline text arrives intact. Without the mode, the raw bytes are delivered as if typed.
A paste INSERTS; it does not SUBMIT. Paste-aware shells and REPLs buffer the block until a real Enter — follow with `phux send-keys TARGET Enter` to run what you pasted.
TEXT is the payload; omit it to read the payload from stdin. Payloads are trusted by default (you vouch for content you composed); `--untrusted` opts into the server's safety gate.
Examples:
phux paste demo 'SELECT count(*) FROM users;'
git diff | phux paste review
Usage: phux paste [OPTIONS] <TARGET> [TEXT]
Arguments:
<TARGET>
Target selector: session, session:window, session:window.pane, @id, or `.` (focused). `=` is unsupported by headless commands
[TEXT]
Text to paste. Omit to read the payload from stdin
Options:
--untrusted
Mark the payload untrusted: the server classifies it and the pane's untrusted-paste policy (reject by default) may silently drop an unsafe payload — e.g. anything multiline. Without this flag the paste is trusted and forwarded verbatim
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux perf
Show the server's performance telemetry.
Reads the always-on latency histograms, throughput counters, and process figures the server keeps about itself (`GET_PERF`) and prints them as a table grouped by pipeline stage: `pty.*` (child output arriving), `echo.server` (input to first output on the same pane), `tick.*` and `pump.*` (fan-out to clients), `wire.*` (socket writes), `cmd.*` / `attach.*` (control plane), and `consumer.*` (per-client backpressure). Without `--watch` the numbers cover the server's lifetime; with `--watch SECS` the verb polls and prints each interval on its own, so counters become rates and a stall shows up in the second it happened. Does not start a server.
Usage: phux perf [OPTIONS]
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--watch <SECS>
Poll every SECS seconds and print each interval as a delta
--reset
Zero the server's metrics after each snapshot
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux play
Play a recording back as a live pane.
Creates a new Terminal whose PTY is fed from FILE, then prints its id. The result is an ordinary pane: attach it, `phux snapshot` it, `phux resize` it, watch it from an agent, or `phux kill` it. It is not a viewer for your own shell — for that, `asciinema play FILE` is the right tool and needs no server.
TARGET says WHERE the pane goes: the playback pane is created beside it, splitting its window. TARGET is never written to, and no flag makes playback take over a pane that already has a shell in it. The default is `.`, the focused pane.
The pane is resized to the recording's own grid first, and to each resize the recording contains, so lines wrap where they wrapped when it was captured; --no-fit leaves the grid alone. When the recording ends the pane holds its final frame until you kill it, so nothing races the last byte; --close ends the pane instead.
Examples:
phux play demo.cast
phux play demo.cast work:1.0 --speed 2
phux play demo.cast --loop --idle-limit 0.5 --json
Usage: phux play [OPTIONS] <FILE> [TARGET]
Arguments:
<FILE>
The .cast file to play
[TARGET]
Selector for the pane the playback pane is created beside. Defaults to `.` (the focused pane). Never written to
Options:
--speed <N>
Playback rate. 1 is real time, 2 is twice as fast, 0.5 half speed. Between 0.01 and 100; no events are ever dropped
[default: 1]
--idle-limit <SECS>
Collapse any pause longer than SECS down to SECS. Defaults to the idle limit the recording itself declares; 0 plays the raw timeline
--loop [<N>]
Repeat the recording. Bare `--loop` repeats until the pane is killed; `--loop N` plays it N times
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--split <SPLIT>
Split axis for the new pane
[default: horizontal]
[possible values: horizontal, vertical]
--ratio <RATIO>
Fraction of the split retained by TARGET
[default: 0.5]
--no-fit
Leave the pane's grid alone instead of fitting it to the recording's. Output wider than the pane will wrap
--close
Close the pane when playback ends, instead of holding the final frame until it is killed
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux plugin
Manage local plugin manifests in the phux config registry.
This is a client-local config operation: it validates `phux-plugin.toml` manifests and edits `[[plugins]]` entries in the user's config without contacting a running server.
Usage: phux plugin [OPTIONS] <COMMAND>
Commands:
list List configured plugin manifests [aliases: ls]
link Add or update a manifest entry in `config.toml`
install Fetch, build, validate, and link a plugin package
update Re-fetch, rebuild, and revalidate installed plugins
unlink Remove a configured plugin by id [aliases: rm, remove]
enable Enable a configured plugin by id
disable Disable a configured plugin by id
validate Validate one manifest, or every configured manifest when omitted
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux plugin disable
Disable a configured plugin by id
Usage: phux plugin disable [OPTIONS] <ID>
Arguments:
<ID>
Plugin id from its manifest
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux plugin enable
Enable a configured plugin by id
Usage: phux plugin enable [OPTIONS] <ID>
Arguments:
<ID>
Plugin id from its manifest
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux plugin install
Fetch, build, validate, and link a plugin package.
REF is a git URL (`https://…`, `git@…`, `file://…` — cloned with the system `git`), a local plugin directory (copied), or a local tarball (`.tar`, `.tar.gz`, `.tgz` — extracted with the system `tar`). The package lands under the managed plugins directory (`$XDG_DATA_HOME/phux/plugins`, else `~/.local/share/phux/plugins`), its manifest `[[build]]` steps for this platform run with a bounded timeout and captured output, the manifest is validated (including the `min_phux_version` gate), and the result is linked into `config.toml` like `phux plugin link`. Provenance (ref, branch, resolved commit) is recorded in the managed directory's `plugins.lock` so `phux plugin update` can re-fetch it later.
Usage: phux plugin install [OPTIONS] <REF>
Arguments:
<REF>
Git URL, local plugin directory, or local tarball path
Options:
--rev <REV>
Branch or tag to clone (git sources only)
--disabled
Install and link the plugin but leave it disabled
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux plugin link
Add or update a manifest entry in `config.toml`
Usage: phux plugin link [OPTIONS] <MANIFEST>
Arguments:
<MANIFEST>
Path to a `phux-plugin.toml` file, or a directory containing one
Options:
--disabled
Register the plugin but leave it disabled
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux plugin list
List configured plugin manifests
Usage: phux plugin list [OPTIONS]
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux plugin unlink
Remove a configured plugin by id
Usage: phux plugin unlink [OPTIONS] <ID>
Arguments:
<ID>
Plugin id from its manifest
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux plugin update
Re-fetch, rebuild, and revalidate installed plugins.
Reads the managed directory's `plugins.lock`, re-fetches each recorded source (all of them, or just NAME), reruns its `[[build]]` steps, revalidates the manifest, swaps the managed copy, and records the new resolved commit. `config.toml` is untouched — the linked manifest path does not move.
Usage: phux plugin update [OPTIONS] [NAME]
Arguments:
[NAME]
Plugin id to update. Omit to update every installed plugin
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux plugin validate
Validate one manifest, or every configured manifest when omitted
Usage: phux plugin validate [OPTIONS] [MANIFEST]
Arguments:
[MANIFEST]
Optional path to a `phux-plugin.toml` file or plugin directory
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux rec
Record a pane and export it as an asciinema cast, an animated GIF, or an APNG.
TARGET is a selector (default: the focused pane). Recording is a pure observer: it does not attach the session and never resizes the pane, so it is safe to run against a live session someone is using.
The format follows the output extension (.cast, .gif, .png, .apng); pass --format to override. Use --from to re-render an existing recording without capturing anything.
Examples:
phux rec -o demo.gif
phux rec work:1.0 -o demo.cast --duration 30
phux rec --from demo.cast -o demo.gif --fps 20
Usage: phux rec [OPTIONS] --out <PATH> [TARGET]
Arguments:
[TARGET]
Pane selector. Defaults to the focused pane
Options:
-o, --out <PATH>
Output path. The extension picks the format unless --format is given; a path with no extension gets `.gif`
--format <FMT>
Output format, overriding the extension
Possible values:
- cast: asciinema cast — the archival, re-renderable artifact
- gif: Animated GIF — shareable and embeddable anywhere
- apng: Animated PNG — truecolor, no quantization, larger files
--from <FILE>
Re-render an existing .cast instead of capturing a live pane
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--duration <SECS>
Stop after SECS of recording (default: until Ctrl-C or the pane exits)
--fps <FPS>
Animation sample rate for GIF/APNG output
[default: 10]
--idle-limit <SECS>
Collapse any pause longer than SECS down to SECS. 0 disables
[default: 2]
--max-bytes <BYTES>
Stop encoding and warn once the output reaches BYTES
[default: 8388608]
--cast-version <N>
asciicast format version to write (2 is the interoperable default)
[default: 2]
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux relay
Run a standalone relay, or enroll a route with it.
The relay is a separate rendezvous process for reaching a phux server that cannot accept inbound connections: the server dials OUT to the relay and registers a tunnel for a named route, remote consumers dial IN naming that route, and the relay splices the two as opaque bytes — it never reads what crosses. `run` serves in the foreground; `pair` enrolls a route name and mints the token the server's tunnel authenticates with. Relay state (the route-token store and a self-signed certificate) lives at fixed paths under the phux state directory.
Usage: phux relay [OPTIONS] <COMMAND>
Commands:
run Run the relay in the foreground
pair Enroll a route and mint (or rotate) its tunnel token
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux relay pair
Enroll a route and mint (or rotate) its tunnel token.
Writes one entry binding a fresh secret token to NAME in the relay's route-token store and prints the token once, alongside the relay certificate's SHA-256 fingerprint. Give both to the phux server that will dial out to this relay: the token authenticates its tunnel, and the fingerprint pins the relay's certificate. Pairing a route that is already enrolled REPLACES its token (rotation) — exactly one token per route. Revoke a route by deleting its line from the store. This never contacts a running relay — it only writes the token file, and a running relay picks the change up at the next tunnel handshake.
Usage: phux relay pair [OPTIONS] --route <NAME>
Options:
--route <NAME>
Route name the token is bound to. Consumers select the route via the TLS server name, so it must be a lowercase DNS label: `[a-z0-9-]`, at most 63 characters, no leading or trailing hyphen. Anything else is rejected, never normalized
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux relay run
Run the relay in the foreground.
Binds one QUIC endpoint on LISTEN and serves both relay legs on it: phux servers dial out from behind NAT and register a tunnel for their enrolled route, and remote consumers dial in naming a route, each spliced onto that route's live tunnel as opaque bytes. Enroll routes with `phux relay pair`; the token store is re-read per connection attempt, so pairing a new route (or revoking one by deleting its line) needs no restart. Serves until Ctrl-C.
Usage: phux relay run [OPTIONS] --listen <HOST:PORT>
Options:
--listen <HOST:PORT>
Address the relay's QUIC endpoint binds (e.g. `0.0.0.0:4433`). Always explicit — there is no default listen address, so exposing the relay requires typing where
--max-conns <N>
Maximum concurrent connections, tunnels and consumers combined. An over-cap connection is refused after its handshake completes; existing connections are unaffected
[default: 64]
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux rename
Rename a session.
Reassigns `SESSION`'s human-readable name to `NEW_NAME` in one round-trip. The server is authoritative; attached clients pick up the new name on their next snapshot. An unknown `SESSION` or a `NEW_NAME` already in use is an error.
Usage: phux rename [OPTIONS] <SESSION> <NEW_NAME>
Arguments:
<SESSION>
Current session name
<NEW_NAME>
New session name
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux resize
Set a pane's grid size, with no TTY.
The headless counterpart to resizing your terminal window: names one pane and gives it an exact cell geometry. Nothing attaches and nothing subscribes, so the pane is never dragged toward the 80x24 size a program with no terminal would otherwise report.
The new size takes effect immediately, even with someone attached. It is not permanent against an attached view: under the default `window-size = "smallest"` policy the next attach, detach, or window resize recomputes the pane's geometry from the attached views and overrides it. Set `window-size = "manual"` when an explicit size must hold. Either way this verb reads the server's real size back before exiting, and exits nonzero if it is not the one you asked for, so a script can never mistake a delivered request for an applied one.
Examples:
phux resize demo 120x40
phux resize @7 200x50 --json
Usage: phux resize [OPTIONS] <TARGET> <COLSxROWS>
Arguments:
<TARGET>
Target selector: session, session:window, session:window.pane, @id, or `.` (focused). `=` is unsupported by headless commands
<COLSxROWS>
New grid size, e.g. 120x40. Both axes are whole numbers of cells and at least 1
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux run
Run a command in a pane and capture its exit code.
Reports the command's exit code, output, and duration. Brackets the command with sentinels to capture `$?`, so it assumes a POSIX shell (sh/bash/zsh). The process exit code mirrors the command's — and is 125 when `phux` gives up on `--timeout` — so `phux run … && next` composes like a shell. TARGET is a selector (see the top-level help), resolved client-side to one pane; the command routes to it by id (no attach, no resize).
Flags (`--timeout`, `--json`, `--socket`) MUST precede TARGET, or they are swallowed into the trailing command.
Examples:
phux run build "cargo test"
phux run --timeout 30 work:1.0 "cargo test"
Usage: phux run [OPTIONS] <TARGET> <COMMAND>...
Arguments:
<TARGET>
Target selector: session, session:window, session:window.pane, @id, or `.` (focused). `=` is unsupported by headless commands
<COMMAND>...
The command line: all trailing args, joined with spaces
Options:
--timeout <SECS>
Give up after this many seconds (exit 125). Default: 600s. Pass 0 to wait indefinitely
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux send-keys
Send keys to a pane.
tmux-shaped: each KEY is a named key (`Enter`, `Tab`, `Escape`, `Up`, `C-c`, `M-x`, …) or a literal string. Literals normally type character by character; a literal run immediately before `Enter` is delivered as a submission-safe paste followed by the real key, honoring the pane's live bracketed-paste mode. TARGET is resolved client-side to one pane, so the live pane is neither attached nor resized.
Flags (`--socket`) MUST precede TARGET: KEYS is a trailing var-arg, so anything after TARGET is taken as a key to send.
Examples:
phux send-keys demo "echo hi" Enter
phux send-keys work:1.0 C-c
Usage: phux send-keys [OPTIONS] <TARGET> <KEYS>...
Arguments:
<TARGET>
Target selector: session, session:window, session:window.pane, @id, or `.` (focused). `=` is unsupported by headless commands
<KEYS>...
Keys to send: named keys and/or literal strings, in order
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux server
Run a phux server in the foreground.
Binds a Unix domain socket, pre-seeds a session whose initial pane spawns the user's `$SHELL` inside a real PTY, and serves `ATTACH` requests until Ctrl-C.
Usage: phux server [OPTIONS]
Options:
--session <SESSION>
Name of the pre-seeded session. Matches what `phux attach <name>` will request
[default: default]
--listen <HOST:PORT>
Also accept WebSocket clients on this `HOST:PORT` (the UDS stays on). Loopback (e.g. `127.0.0.1:8787`) is plaintext for local browser dev; any routable address (e.g. `0.0.0.0:8787`) auto-provisions TLS and requires a `phux pair` token. Overrides `$PHUX_WS_ADDR`
--quic <HOST:PORT>
Also accept QUIC clients on this `HOST:PORT` (the UDS stays on). QUIC is always TLS 1.3-encrypted; a loopback address skips token auth (local dev), while any routable address requires a `phux pair` token sent as the stream's opening preamble. Overrides `$PHUX_QUIC_ADDR`
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--webtransport <HOST:PORT>
Also accept WebTransport (HTTP/3 over QUIC) clients on this `HOST:PORT` (the UDS stays on) — the browser's door to QUIC-class transport; the browser client dials it, falling back to WebSocket. Always TLS 1.3-encrypted; a loopback address skips token auth (local dev), while any routable address requires a `phux pair` token carried in the CONNECT request (`Authorization: Bearer` from native consumers, `?token=<hex>` on the session URL from browsers). Overrides `$PHUX_WT_ADDR`
--connect <HOST:PORT>
Dial one relay outbound on `HOST:PORT`. If a matching `[[connector]]` entry exists, its token file and certificate pin are used; otherwise only a loopback endpoint is accepted for unauthenticated development. Without this flag, every configured connector is supervised independently
--hub
Run as a federation hub: consume the `[[satellites]]` registry from `config.toml` at startup, validating every enabled entry's endpoint (`quic://`, `ws://`, `wss://`, or `ssh://`) into the runtime satellite table, then dial and maintain one outbound link per satellite (QUIC and WebSocket links authenticate with a bearer token; `ssh://` bridges over `ssh HOST phux stdio-bridge`), relaying satellite-tagged frames over the links. A malformed enabled endpoint or a duplicate satellite name fails startup. Without this flag the registry is ignored
--exit-after-idle <SECS>
Exit once no client has been connected for SECS, even if panes are still running. For ephemeral servers: a test harness or CI job that bootstraps a private server per run and cannot guarantee its own cleanup step will execute. The clock starts at startup, so a server nobody ever connects to also exits.
Without this flag the server keeps the multiplexer contract and lives until its last pane is gone.
-h, --help
Print help (see a summary with '-h')
phux service
Keep a server running across logout and reboot.
Generates this host's native per-user service unit — a `launchd` `LaunchAgent` on macOS, a systemd user unit on Linux — with the server's environment baked in, so a rebooted host comes back with a server instead of waiting for someone to log in and start one. A restarted server has no terminals: every pane's process died with the host. `install --restore` brings back session names, layout, and cwd, not running processes.
Usage: phux service [OPTIONS] <COMMAND>
Commands:
install Write the unit and hand it to the init system
reconcile Bring an installed unit's restart policy up to date, in place
uninstall Unload the unit and remove what `install` wrote
status Report whether a unit is installed and running
logs Show the supervised server's log
prune-logs Delete the accumulated per-pid `client-*.log` files
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux service install
Write the unit and hand it to the init system.
Idempotent: rerunning reconciles an existing unit, so changing a listener address is `install` again with the new flag.
Usage: phux service install [OPTIONS]
Options:
--quic <HOST:PORT>
Accept QUIC clients on this `HOST:PORT`. A routable address (e.g. `0.0.0.0:8788`) engages TLS and requires a `phux pair` token. Prefer this over `--listen` where UDP is open
--listen <HOST:PORT>
Accept WebSocket clients on this `HOST:PORT`. The fallback for networks that block UDP
--restore
Save the workspace on stop and restore it on start. Off by default: a session list repopulated with fresh shells is a surprise unless asked for. Restores names, layout, and cwd — never running processes
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--hub
Run the supervised server as a federation hub. The service loads enabled `[[satellites]]` entries and keeps their links connected across login, logout, and reboot
--adopt
Never stop a running server to install. When one is live, write the unit and arm it instead of loading it, so the incumbent keeps its panes and the supervisor takes over the next time a server starts.
Without this, an install over a live server is refused, because loading the unit would supervise a process that cannot bind the socket. With it, nothing is stopped and nothing crash-loops. The running process itself is never adopted: neither launchd nor systemd can restart-supervise a process it did not start.
--print
Print the unit (and the restore wrapper) to stdout without writing or loading anything
-h, --help
Print help (see a summary with '-h')
phux service logs
Show the supervised server's log
Usage: phux service logs [OPTIONS]
Options:
-f, --follow
Follow the log as it grows
-n, --lines <LINES>
How many trailing lines to show
[default: 200]
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux service prune-logs
Delete the accumulated per-pid `client-*.log` files
Usage: phux service prune-logs [OPTIONS]
Options:
--dry-run
Report how many would be removed, and remove nothing
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux service reconcile
Bring an installed unit's restart policy up to date, in place.
Rewrites only the keys that carry the restart policy and leaves every other byte of the unit alone, so the listeners, hub mode and socket baked into it by an earlier `install` are preserved rather than re-derived. Nothing is stopped and no pane is lost.
On Linux `systemctl --user daemon-reload` picks the change up without touching the running service. On macOS launchd cannot re-read a plist for a loaded job, so the corrected policy takes effect at the next login or reboot; the command says so rather than claiming otherwise.
Usage: phux service reconcile [OPTIONS]
Options:
--print
Print the reconciled unit to stdout without writing anything
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux service status
Report whether a unit is installed and running
Usage: phux service status [OPTIONS]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux service uninstall
Unload the unit and remove what `install` wrote
Usage: phux service uninstall [OPTIONS]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux signal
Signal a pane's process group.
Delivers a POSIX signal to the program running in the resolved pane and every subprocess it spawned — distinct from `phux kill`, which destroys the pane. `freeze` (SIGSTOP) pauses the process mid-step; `resume` (SIGCONT) lets it run again — the reversible brake for an agent about to do something rash. TARGET is a selector.
Examples:
phux signal build freeze
phux signal . kill
Usage: phux signal [OPTIONS] <TARGET> <SIGNAL>
Arguments:
<TARGET>
Target selector (resolves to one pane)
<SIGNAL>
Which signal to deliver
Possible values:
- interrupt: SIGINT — the Ctrl-C equivalent
- freeze: SIGSTOP — pause the process group (reversible via `resume`)
- resume: SIGCONT — resume a frozen process group
- terminate: SIGTERM — request graceful termination
- kill: SIGKILL — force termination
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux skill
Print the agent skill this binary ships with, on stdout.
The text is compiled into the executable, so it describes the verbs and flags THIS build actually has — it cannot drift from the binary the way a copied file can. It contacts no server and reads no config.
Give it to any agent that needs to drive phux: it teaches the read-act-wait loop, the selector grammar, the difference between a level read and an observed transition, the exit codes, and the safety rules for driving a terminal a human may also be using.
Scopes are `quick` (core loop and safety), `agent` (lifecycle and identity), `terminal` (screen and input mechanics), and `full` (everything, the default). Examples:
phux skill
phux skill agent
phux --skill=terminal
phux --skill=quick | pbcopy
Usage: phux skill [OPTIONS] [SCOPE]
Arguments:
[SCOPE]
Amount and subject of guidance to print
Possible values:
- quick: Essential read-act-wait-verify guidance and safety rules
- agent: Quick guidance plus agent identity and lifecycle supervision
- terminal: Quick guidance plus terminal screen and input mechanics
- full: The complete guide and command inventory
[default: full]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux snapshot
Capture a pane's screen as JSON or a boxed text view.
The agent "floor": read what's on screen as JSON (`--json`) or a boxed text view, without a TTY or tmux. The read is side-effect-free — the server walks its own grid, so this neither attaches nor resizes the pane, and is safe to poll against a pane another client is using.
TARGET is a selector (see the top-level help); omit it for the most-recently-focused session.
Usage: phux snapshot [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target selector. Omit for the most-recently-focused session
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--scrollback [<N>]
Include scrollback history above the viewport. Bare `--scrollback` requests all retained history; `--scrollback N` requests the most-recent N rows. History appears in the JSON `scrollback` field; the boxed view shows it above the viewport
--cells
Include per-cell OSC-133 semantic marks + styles. Populates the JSON `cells` array (sparse: only cells with a non-default style or a semantic mark). No effect on the boxed view, which is plain text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--tail [<N>]
Return the last N rendered rows (history above the viewport, then the viewport). Bare `--tail` returns 80; `--tail 0` returns all, capped at 10000. The viewport is a floor — a grid is never returned in part — and `truncated` reports any dropped rows
--unwrap
Join soft-wrapped rows into logical lines (rows as written, not as painted). Cannot be combined with `--cells`: cell coordinates are grid coordinates and do not survive the join
--rendered
Emit the CLIENT's composited multi-pane view — the assembled frame (layout tiling + dividers + status bar) as the human's glass shows it — as dense structured cells. Unlike the default side-effect-free read this ATTACHES (drives the headless client render path). Mutually exclusive with `--cells` / `--scrollback` / `--tail` / `--unwrap`; sizes the composite via `--cols` / `--rows`
--cols <COLS>
Composited viewport width for `--rendered` (no TTY to measure)
[default: 80]
--rows <ROWS>
Composited viewport height for `--rendered`
[default: 24]
-h, --help
Print help (see a summary with '-h')
phux spawn
Create a pane without attaching.
With `--target`, the pane is inserted beside an exact local owner; otherwise it joins the server's most recently active session. The new pane's id prints to stdout. With `--satellite NAME` on a federation hub (`phux server --hub`), the spawn is routed over the hub's link to that satellite and the returned id is qualified with that host — addressable through the hub by every satellite-capable verb. Does not auto-start a server.
Usage: phux spawn [OPTIONS] [-- <COMMAND>...]
Arguments:
[COMMAND]...
Command (and arguments) to run instead of the default shell. Must follow `--`: `phux spawn -- htop`
Options:
--satellite <NAME>
Route the spawn to a configured federation satellite (a name from `phux host ls --role satellite`, on a server running `--hub`)
--target <TARGET>
Existing local pane beside which to place the new pane
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--split <SPLIT>
Split axis for explicit placement (requires `--target`)
[default: horizontal]
[possible values: horizontal, vertical]
--ratio <RATIO>
Fraction of the split retained by TARGET (requires `--target`)
[default: 0.5]
-c, --cwd <CWD>
Working directory for the new pane
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux status
Report the running server: pid, up since, protocol, clients, logs.
One glance at the server behind the socket: whether it is running and as which pid, since when, the protocol version it speaks, how many clients are attached, the sessions it holds, and where its logs live. Does not start a server: with no server running it reports as much and exits non-zero. Pass `--json` for the stable, versioned machine shape instead of the human text; with no server that shape is `{"running": false, ...}` on stdout, still exiting non-zero.
Usage: phux status [OPTIONS]
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. Exception to the shared failure contract: with no server running, stdout carries the `{"running": false, ...}` document (still exiting non-zero); any other failure leaves stdout empty and puts one JSON error object on stderr
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux swap-pane
Swap two existing pane leaves in the same session layout.
Both selectors must each resolve to exactly one local pane. Split geometry is preserved and attached clients retain their local focus.
Usage: phux swap-pane [OPTIONS] <FIRST> <SECOND>
Arguments:
<FIRST>
First pane selector
<SECOND>
Second pane selector
Options:
--json
Emit a schema-versioned JSON result or error
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux tag
Read and write pane tags.
Tags are freeform strings attached to panes. Once a pane is tagged, the `#tag` selector addresses every pane carrying that tag — e.g. `phux kill #build`, `phux snapshot #web`.
Usage: phux tag [OPTIONS] <COMMAND>
Commands:
ls List the tags on each pane a selector resolves to [aliases: list]
add Add one or more tags to each pane a selector resolves to
rm Remove one or more tags from each pane a selector resolves to [aliases: remove]
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux tag add
Add one or more tags to each pane a selector resolves to
Usage: phux tag add [OPTIONS] <TARGET> <TAGS>...
Arguments:
<TARGET>
Target selector
<TAGS>...
Tags to add (the leading `#` is optional)
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux tag ls
List the tags on each pane a selector resolves to
Usage: phux tag ls [OPTIONS] <TARGET>
Arguments:
<TARGET>
Target selector (session, `session:window`, `@id`, `.`, `#tag`)
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux tag rm
Remove one or more tags from each pane a selector resolves to
Usage: phux tag rm [OPTIONS] <TARGET> <TAGS>...
Arguments:
<TARGET>
Target selector
<TAGS>...
Tags to remove (the leading `#` is optional)
Options:
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux take
Take the input wheel of a pane.
Seizes exclusive input authority over the resolved pane: while held, only this connection's input reaches the PTY — every other client's keystrokes (and any agent's `send-keys`) are locked out. Use it to grab control of a pane an agent is driving. Release with `phux give`. TARGET is a selector (see the top-level help).
Usage: phux take [OPTIONS] <TARGET>
Arguments:
<TARGET>
Target selector (resolves to one pane)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux update
Update phux to the latest release, keeping sessions alive.
Checks the published release, downloads the archive for this platform, verifies it against the checksum published beside it, replaces the binaries atomically, and asks a running server to re-exec so live panes survive. A server, its local clients, its satellites, and its relays must all run the same release, so this is the command that moves a whole deployment in one step.
phux updates only installs it maintains: a release archive unpacked into $PHUX_INSTALL_DIR, ~/.local/bin, ~/bin, /usr/local/bin, or /opt/phux/bin. A Homebrew, Cargo, or Nix install is never modified — the exact native command is printed instead — and an unrecognized location is refused rather than overwritten.
The previous binaries are kept beside the new ones; `--rollback` puts them back.
Examples:
phux update --check
phux update --check --json
phux update
phux update --dry-run --version v1.2.3
phux update --rollback
Usage: phux update [OPTIONS]
Options:
--check
Report the current and latest release and the install source, then stop. Changes nothing and never downloads an archive
--dry-run
Do everything except the replacement: resolve, download, and verify the checksum, then report what would have been installed
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--version <TAG>
Install this release tag instead of the latest one. Accepts any tag from the releases page, including an older one (a downgrade)
--rollback
Restore the binaries saved by the previous `phux update`
--no-restart
Replace the binaries but do not ask a running server to re-exec. Live panes keep the old image until the server is upgraded or restarted
--json
Emit the stable, versioned JSON document on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux upgrade
Graceful-upgrade the running server in place.
Asks the server to snapshot every pane, re-exec the on-disk binary, and re-adopt the live PTYs, so the shells / editors / agents in every session survive a binary update (e.g. after `cargo install` / `brew upgrade`). Clients briefly disconnect and reconnect. This is the low-level primitive: it re-execs whatever is already on disk and downloads nothing. `phux update` is the command that puts a new binary there first.
Usage: phux upgrade [OPTIONS]
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux wait
Block until a pane meets a condition.
Polls the side-effect-free screen read — the poll floor of the event surface: always works, no shell integration. Exits 0 when the condition is met, and 124 when `--timeout` expires first. TARGET is a selector (see the top-level help); omit it for the most-recently-focused session.
Matching is against the lines as WRITTEN: rows the terminal soft-wrapped at its right edge are joined first, so text that straddles a wrap is found rather than silently never matching.
Flags (`--until`, `--regex`, `--idle`, `--tail`, `--output-only`, `--timeout`, `--json`, `--socket`) MUST precede TARGET if you give one.
Examples:
phux wait --until "BUILD SUCCESSFUL" build
phux wait --regex "test result: (ok|FAILED)" --output-only build
phux wait --idle 750 repl
Usage: phux wait [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target selector. Omit for the most-recently-focused session
Options:
--until <TEXT>
Succeed once any line contains this substring. NOTE: this matches ANY line, including the shell's echo of a command you just typed — match on text that appears only in OUTPUT, or pass `--output-only`
--regex <PATTERN>
Succeed once any line matches this Rust regular expression. One line at a time, so `^` and `$` anchor to a line you can see. An invalid pattern is a usage error (exit 2) reported before the wait starts, never a wait that quietly never matches
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--tail [<N>]
Match only within the last N lines, and read that much history to do it. Bare `--tail` uses 80; `--tail 0` uses all retained history, capped at 10000. Without it, only the viewport is read. N counts logical lines AFTER wrapped rows are joined and ignores the blank rows under the cursor, and unlike `snapshot --tail` the viewport is not a floor: `--tail 3` really does mean only the last three lines with content count — including the prompt block already back on screen, so leave room for it. A bare `--tail` reads the next word as N, so spell N out when you also pass TARGET (`--tail 80 build`, not `--tail build`)
--output-only
Ignore lines the shell marked as your own typed input, so a wait cannot be satisfied by the echo of the command that started the work. Needs a shell with OSC-133 integration; with none, nothing is filtered and phux says so on stderr rather than pretending
--idle <MS>
Succeed once the matched lines hold still for this many milliseconds (the pane has settled). Default when neither `--until` nor `--regex` is given. With `--tail N`, only those lines have to hold still — a spinner further up does not count
--timeout <SECS>
Give up after this many seconds (exit 124). Default: wait forever
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
-h, --help
Print help (see a summary with '-h')
phux watch
Stream a pane's live events (the push half of the agent surface).
Subscribes to the server's event stream and prints one event per line. The subscription neither attaches nor resizes the pane — safe to watch a pane a human or another agent is actively using. TARGET is a selector (see the top-level help); omit it for the most-recently-focused session.
With no bounds the stream runs until EOF or Ctrl-C. `--until EVENT` makes it a gate: the first matching event is printed and `watch` exits 0. `--timeout SECS` gives up and exits 124, the same code `phux wait` uses. If the server closes the stream before an `--until` event arrives, that is exit 1 — the event did not happen and can no longer happen.
With `--json` each line is one JSON object and nothing else is written to stdout: no per-line schema_version, and no summary line on timeout.
Examples:
phux watch build
phux watch --json work:1.0
phux watch --until asked --timeout 120 reviewer
Usage: phux watch [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target selector. Omit for the most-recently-focused session
Options:
--until <EVENT>
Exit 0 as soon as an event with this name arrives. Repeatable; any one of them satisfies the watch. The vocabulary is the one this stream prints: `agent_state`, `asked`, `bell`, `command_finished`, `command_started`, `dirty`, `idle`, `pane_closed`, `pane_spawned`, `title_changed`, `unknown`. An unrecognized name is a usage error (exit 2) reported before the watch starts, never a watch that quietly never matches
--timeout <SECS>
Give up after this many seconds (exit 124). Applies with or without `--until`. Default: stream until EOF or Ctrl-C
--json
Emit stable, versioned JSON on stdout instead of the human view. On failure, stdout stays empty and stderr carries one JSON error object
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux workspace
Inspect a git workspace and its worktrees for agent orchestration.
This is a local repo operation: it never contacts a running phux server and never creates or deletes worktrees. Agents use it to map code checkouts to phux sessions/panes before spawning or attaching work.
Usage: phux workspace [OPTIONS] <COMMAND>
Commands:
inspect Inspect the git repository and its checked-out worktrees
save Save the running phux workspace as a JSON archive
restore Restore missing sessions from a workspace archive
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux workspace inspect
Inspect the git repository and its checked-out worktrees
Usage: phux workspace inspect [OPTIONS] [PATH]
Arguments:
[PATH]
Path inside the repository or worktree to inspect
[default: .]
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux workspace restore
Restore missing sessions from a workspace archive
Usage: phux workspace restore [OPTIONS] <ARCHIVE>
Arguments:
<ARCHIVE>
JSON archive path, or '-' to read from stdin
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux workspace save
Save the running phux workspace as a JSON archive
Usage: phux workspace save [OPTIONS]
Options:
-o, --output <PATH>
Write the archive to a path instead of stdout
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help
phux worktree
Manage git worktrees and the sessions bound to them.
Each worktree binds to one session whose name is derived from the worktree's directory basename. The derivation is a pure function of the path, so the binding is computed on demand and can never go stale — phux stores no worktree state and the server knows no git.
Usage: phux worktree [OPTIONS] <COMMAND>
Commands:
list List the repository's worktrees and their bound sessions [aliases: ls]
new Create a worktree and a session rooted in it
open Open the session bound to an existing worktree, creating it if absent
remove Remove a worktree, killing the session bound to it first [aliases: rm]
help Print this message or the help of the given subcommand(s)
Options:
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux worktree list
List the repository's worktrees and their bound sessions.
The `bound` column reads `live` when a session by the derived name exists, `-` when it does not, and `?` when no server is running — "no server" and "no session" are different facts.
Usage: phux worktree list [OPTIONS] [PATH]
Arguments:
[PATH]
Path inside the repository or worktree to list from
[default: .]
Options:
--json
Emit a stable JSON document instead of human text
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux worktree new
Create a worktree and a session rooted in it.
An existing local branch is checked out; a missing one is created, from `--from` when given and from the current HEAD otherwise. The worktree lands beside the repository as `<repo>-<branch>` unless `--path` says otherwise.
Usage: phux worktree new [OPTIONS] <BRANCH> [-- <COMMAND>...]
Arguments:
<BRANCH>
Branch to check out, or to create when it does not exist
[COMMAND]...
Command to run in the new session instead of the default shell
Options:
--path <PATH>
Where to put the worktree. Defaults to a sibling of the repo
--from <REF>
Start point for a newly created branch (default: current HEAD)
-s, --session <NAME>
Session name, overriding the name derived from the path
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
--repo <PATH>
Path inside the repository the worktree belongs to
[default: .]
--attach
Attach to the new session instead of creating it headlessly
--json
Emit a stable JSON document — branch, path, session, and the seed pane's `terminal_id` — instead of human text. This is the first call in a fan-out script, and the id it returns is the pane the caller then sends its first prompt to. Cannot combine with `--attach`: an attached session owns stdout
-h, --help
Print help (see a summary with '-h')
phux worktree open
Open the session bound to an existing worktree, creating it if absent.
Idempotent: an already-live session is reported and left alone, so scripts and keybindings can call this without checking first.
Usage: phux worktree open [OPTIONS] <TARGET>
Arguments:
<TARGET>
Worktree path, branch, or derived session name
Options:
--repo <PATH>
Path inside the repository the worktree belongs to
[default: .]
--attach
Attach to the session instead of only reporting its name
--json
Emit the same document `worktree new --json` emits, whether the session was created now or was already live — so a script that re-enters a fleet gets the seed pane without special-casing
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')
phux worktree remove
Remove a worktree, killing the session bound to it first.
The session is killed before git runs, because git refuses to remove a worktree whose files are held open and a shell sitting in that directory holds it open. Refuses the worktree you are standing in.
Usage: phux worktree remove [OPTIONS] <TARGET>
Arguments:
<TARGET>
Worktree path, branch, or derived session name
Options:
--force
Pass --force to git, removing a worktree with local changes
--repo <PATH>
Path inside the repository the worktree belongs to
[default: .]
--json
Emit a stable JSON document instead of human text. A fan-out teardown script has the same parsing problem creation does
--socket <PATH>
Override the UDS path of the server to dial. Defaults to `$PHUX_SOCKET`, else `$XDG_RUNTIME_DIR/phux/phux.sock` (or `/tmp/phux-$USER/phux.sock` if `XDG_RUNTIME_DIR` isn't set)
-h, --help
Print help (see a summary with '-h')phux reference
Generated reference documentation, rendered from the compiled binary and byte-pinned by a freshness test so it cannot drift from the code.
phux config reference
The complete config.toml surface: a section index pinned against the config schema, every scalar knob with its shipped default, and the annotated default...