| title | acpx CLI Reference |
|---|---|
| description | Definitive command and behavior reference for the acpx CLI, including grammar, options, session rules, output modes, permissions, and exit codes. |
| author | Bob <bob@dutifulbob.com> |
| date | 2026-02-18 |
acpx is a headless ACP client for scriptable agent workflows.
Default behavior is conversational:
- prompt commands use a persisted session
- session lookup is scoped by agent command and working directory (plus optional session name)
execruns one prompt in a temporary session
Global options apply to all commands.
acpx [global_options] [prompt_text...]
acpx [global_options] prompt [prompt_options] [prompt_text...]
acpx [global_options] exec [prompt_options] [prompt_text...]
acpx [global_options] compare <agent>... '<prompt_text>'
acpx [global_options] compare <agent>... --file <path>
acpx [global_options] flow run <file> [--input-json <json> | --input-file <path>] [--default-agent <name>]
acpx [global_options] cancel [-s <name>]
acpx [global_options] set-mode <mode> [-s <name>]
acpx [global_options] set <key> <value> [-s <name>]
acpx [global_options] status [-s <name>]
acpx [global_options] sessions [list | new [--name <name>] | ensure [--name <name>] | close [name] | show [name] | history [name] [--limit <count>] | watch [-s <name>] [--cursor <cursor>] | export [name] --output <path> | import <archive> [--name <name>] [--cwd <dir>]]
acpx [global_options] config [show | init]
acpx [global_options] <agent> [prompt_options] [prompt_text...]
acpx [global_options] <agent> prompt [prompt_options] [prompt_text...]
acpx [global_options] <agent> exec [prompt_options] [prompt_text...]
acpx [global_options] <agent> cancel [-s <name>]
acpx [global_options] <agent> set-mode <mode> [-s <name>]
acpx [global_options] <agent> set <key> <value> [-s <name>]
acpx [global_options] <agent> status [-s <name>]
acpx [global_options] <agent> sessions [list | new [--name <name>] | ensure [--name <name>] | close [name] | show [name] | history [name] [--limit <count>] | watch [-s <name>] [--cursor <cursor>] | export [name] --output <path> | import <archive> [--name <name>] [--cwd <dir>]]The global --mcp-config <path> option loads an external JSON file's mcpServers array for the
invocation, replacing project/global MCP configuration. Relative paths resolve from --cwd.
For a persistent session, close the existing session before switching its MCP config.
<agent> can be:
- built-in friendly name from the README
- unknown token (treated as raw command)
- overridden by
--agent <command>escape hatch
Additional built-in agent docs live in the Agents page.
Prompt options:
-s, --session <name> Use named session instead of cwd default
--no-wait Queue prompt and return immediately if session is busy
-f, --file <path> Read prompt text from file (`-` means stdin)Notes:
- Top-level
prompt,exec,cancel,set-mode,set,sessions, and bareacpx <prompt>default tocodex. - Top-level
flow run <file>executes a user-authored workflow module and persists run state under~/.acpx/flows/runs/. - If a prompt argument is omitted,
acpxreads prompt text from stdin when piped. --fileworks for implicit prompt,prompt, andexeccommands.- After an agent name,
--filemay appear before or afterprompt/exec; an explicit value on the subcommand wins.--no-waitworks before or afterprompt, and omission still waits normally. acpxwith no args in an interactive terminal shows help.
acpx [global_options] flow run <file> [--input-json <json> | --input-file <path>] [--default-agent <name>]- Runs a user-authored workflow module step by step through the
acpx/flowsruntime. - Persists run artifacts under
~/.acpx/flows/runs/<runId>/. - Reuses one implicit main ACP session by default for non-isolated
acpnodes. acpnodes may override their working directory per step, which lets flows prepare an isolated workspace with an action node and then keep the agent session inside that cwd.acpandactionnodes use the global--timeoutvalue as their default step timeout. If--timeoutis omitted, flows default to 15 minutes per active step.- Flows may declare permission requirements. If a flow requires an explicit grant such as
approve-all,acpxfails fast before starting the flow and tells you which permission flag to pass. --input-jsonpasses flow input inline as JSON.--input-filereads flow input JSON from disk.--default-agentsupplies the default agent profile foracpnodes that do not pin one.- The file is always provided by the caller at runtime.
acpxdoes not require any built-in flow registry. - The source repo includes example flow files under
examples/flows/, including a larger PR-triage example underexamples/flows/pr-triage/.
Example invocations:
acpx flow run ./my-flow.ts --input-file ./flow-input.json
acpx flow run examples/flows/branch.flow.ts \
--input-json '{"task":"FIX: add a regression test for the reconnect bug"}'
acpx --approve-all flow run examples/flows/pr-triage/pr-triage.flow.ts \
--input-json '{"repo":"openclaw/acpx","prNumber":150}'The PR-triage example is only an example workflow. It can post GitHub comments or close a PR if you run it against a live repository.
All global options:
| Option | Description | Details |
|---|---|---|
--agent <command> |
Raw ACP agent command (escape hatch) | Do not combine with positional agent token. |
--cwd <dir> |
Working directory | Defaults to current directory. Stored as absolute path for scoping. |
--approve-all |
Approve remaining tool requests | Per-tool policy takes precedence over permission mode approve-all. |
--approve-reads |
Approve remaining reads/searches; prompt for others | Default mode; per-tool policy takes precedence. |
--deny-all |
Deny remaining tool requests | Per-tool policy takes precedence over permission mode deny-all. |
--format <fmt> |
Output format | text (default), json, quiet. |
--suppress-reads |
Suppress read file contents | Replaces raw read payloads with [read output suppressed]. |
--json-strict |
Strict JSON mode | Requires --format json; suppresses non-JSON stderr output. |
--no-fs |
Disable ACP filesystem capabilities | Advertises clientCapabilities.fs.readTextFile and writeTextFile as false during ACP initialize for new agent clients. |
--no-terminal |
Disable ACP terminal capability | Advertises clientCapabilities.terminal: false during ACP initialize for new agent clients. |
--non-interactive-permissions <policy> |
Non-TTY prompt policy | deny (default) or fail when approval prompt cannot be shown. |
--permission-policy <json-or-file> |
Per-tool permission policy | JSON object or file path with autoApprove, autoDeny, escalate, and optional defaultAction (approve, deny, escalate). Alias: --policy. |
--timeout <seconds> |
Max wait time for agent response | Must be positive. Decimal seconds allowed. |
--ttl <seconds> |
Queue owner idle TTL before shutdown | Default 300. 0 disables TTL. |
--model <id> |
Set agent model | Claude-compatible adapters may consume session creation metadata; other agents must advertise a model config option or legacy models metadata. |
--verbose |
Enable verbose logs | Prints ACP/debug details to stderr. |
Permission flags are mutually exclusive. Using more than one of --approve-all, --approve-reads, --deny-all is a usage error.
For model configuration, acpx prefers a valid select control with both
category: "model" and id: "model". Otherwise it uses the first valid
model-category control, including custom IDs, then the legacy id: "model"
fallback. This keeps provider selectors in the same category from taking over
the actual model control.
acpx --approve-all codex 'apply this patch and run tests'
acpx --approve-reads codex 'inspect the repo and propose a plan'
acpx --deny-all codex 'summarize this code without running tools'
acpx --non-interactive-permissions fail codex 'fail fast when prompt cannot be shown'
acpx --policy '{"escalate":["execute"],"defaultAction":"deny"}' --format json codex exec 'run tests'
acpx --cwd ~/repos/api codex 'review auth middleware'
acpx --format json codex exec 'summarize open TODO items'
acpx --format json --json-strict codex exec 'machine-safe JSON output'
acpx --no-fs codex exec 'use agent-native file operations'
acpx --no-terminal codex exec 'summarize without terminal capability'
acpx --timeout 120 codex 'investigate flaky test failures'
acpx --ttl 30 codex 'keep queue owner warm for quick follow-up'
acpx --verbose codex 'debug adapter startup issues'Each agent command supports the same shape.
acpx [global_options] pi [prompt_options] [prompt_text...]
acpx [global_options] pi prompt [prompt_options] [prompt_text...]
acpx [global_options] pi exec [prompt_text...]
acpx [global_options] pi sessions [list | new [--name <name>] | ensure [--name <name>] | close [name]]Built-in command mapping: pi -> npx pi-acp
acpx [global_options] openclaw [prompt_options] [prompt_text...]
acpx [global_options] openclaw prompt [prompt_options] [prompt_text...]
acpx [global_options] openclaw exec [prompt_text...]
acpx [global_options] openclaw sessions [list | new [--name <name>] | ensure [--name <name>] | close [name]]Built-in command mapping: openclaw -> openclaw acp
For repo-local OpenClaw checkouts, override the built-in command in config:
{
"agents": {
"openclaw": {
"command": "env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 node scripts/run-node.mjs acp --url ws://127.0.0.1:18789 --token-file ~/.openclaw/gateway.token --session agent:main:main"
}
}
}acpx [global_options] codex [prompt_options] [prompt_text...]
acpx [global_options] codex prompt [prompt_options] [prompt_text...]
acpx [global_options] codex exec [prompt_text...]
acpx [global_options] codex sessions [list | new [--name <name>] | ensure [--name <name>] | close [name]]Built-in command mapping: codex -> npx -y @agentclientprotocol/codex-acp
acpx [global_options] claude [prompt_options] [prompt_text...]
acpx [global_options] claude prompt [prompt_options] [prompt_text...]
acpx [global_options] claude exec [prompt_text...]
acpx [global_options] claude sessions [list | new [--name <name>] | ensure [--name <name>] | close [name]]Built-in command mapping: claude -> npx -y @agentclientprotocol/claude-agent-acp
Additional built-in agent docs live in the Agents page.
Unknown agent names are treated as raw commands:
acpx [global_options] my-agent [prompt_options] [prompt_text...]
acpx [global_options] my-agent exec [prompt_text...]
acpx [global_options] my-agent sessionsPersistent-session prompt command:
acpx [global_options] <agent> prompt [prompt_options] [prompt_text...]
acpx [global_options] prompt [prompt_options] [prompt_text...]Behavior:
- Finds existing session for scope key
(agentCommand, cwd, name?) - Does not auto-create sessions; missing scope exits with code
4and guidance to runsessions new - Sends prompt on resumed/new session
- If another prompt is already running for that session, submits to the running queue owner instead of starting a second ACP subprocess
- By default waits for queued prompt completion;
--no-waitreturns after queue acknowledgement - Updates session metadata after completion
The agent command itself also has an implicit prompt form:
acpx [global_options] <agent> [prompt_options] [prompt_text...]
acpx [global_options] [prompt_text...] # defaults to codexOne-shot prompt (no saved session):
acpx [global_options] <agent> exec [prompt_options] [prompt_text...]
acpx [global_options] exec [prompt_options] [prompt_text...] # defaults to codexBehavior:
- Creates temporary ACP session
- Applies
--model, then each repeatable--config-option <key=value>, before prompting - Sends prompt once
- Does not write/use a saved session record
- Supports prompt text from args, stdin,
--file <path>, and--file - - Stops without prompting if the adapter rejects a requested config option
acpx --model gpt-5.4 codex exec \
--config-option reasoning_effort=high \
'review this checkout'One-shot prompt against multiple agents:
acpx [global_options] compare <agent>... '<prompt_text>'
acpx [global_options] compare <agent>... --file <path>
acpx [global_options] compare <agent>... -- prompt words after the delimiterBehavior:
- Runs each agent with the same temporary
exec-style ACP session. - Uses the same global execution controls as
exec, including--cwd,--timeout, permission flags,--policy, auth, terminal advertising, retries, model/system options, and--format. --format textprints one summary table row per agent.--format jsonor command-local--jsonprints aCompareRow[]summary payload.--format quietprints<agent>\t<status>per row.- Agents run serially in the requested workspace. The command does not create saved sessions or separate compare transcript directories. Use
--format jsonwhen you need a machine-readable artifact.
CompareRow.status is ok, cancelled, permission_denied, or error.
acpx [global_options] <agent> cancel [-s <name>]
acpx [global_options] cancel [-s <name>] # defaults to codexBehavior:
- Sends cooperative
session/cancelthrough queue-owner IPC when a prompt is running. - If no prompt is running, prints
nothing to canceland exits success.
acpx [global_options] <agent> set-mode <mode> [-s <name>]
acpx [global_options] set-mode <mode> [-s <name>] # defaults to codexBehavior:
- Calls ACP
session/set_mode. <mode>values are adapter-defined (not globally standardized across all ACP adapters).- Unsupported mode ids are rejected by the adapter (often as
Invalid params). - Routes through queue-owner IPC when an owner is active.
- Falls back to a direct client reconnect when no owner is running.
- When fresh fallback is allowed, replaces the previous saved mode without replaying it; other saved settings restore first. A rejected replacement keeps the previous mode preference.
- Prompt reconnect uses model metadata received while restoring a saved mode, including changed model controls and removed model support.
acpx [global_options] <agent> set <key> <value> [-s <name>]
acpx [global_options] set <key> <value> [-s <name>] # defaults to codexBehavior:
- Calls ACP
session/set_config_option. - Routes through queue-owner IPC when an owner is active.
- Falls back to a direct client reconnect when no owner is running.
set model <id>: Uses the advertised model config option throughsession/set_config_option; adapters that explicitly advertise legacymodelsmetadata usesession/set_model.- A config key named
modekeeps config-option transport; useset-modefor the separate legacy mode control. - Saves accepted values for existing config selections, including reasoning effort adjusted or removed by a model switch; does not pin unselected defaults.
- Restores saved model and config selections after reconnect, before the next prompt; already loaded sessions are reused without replay.
acpx [global_options] <agent> sessions
acpx [global_options] <agent> sessions list
acpx [global_options] <agent> sessions list [--cursor <cursor>] [--filter-cwd <dir>] [--local]
acpx [global_options] <agent> sessions new
acpx [global_options] <agent> sessions new --name <name>
acpx [global_options] <agent> sessions ensure
acpx [global_options] <agent> sessions ensure --name <name>
acpx [global_options] <agent> sessions close
acpx [global_options] <agent> sessions close <name>
acpx [global_options] <agent> sessions show
acpx [global_options] <agent> sessions show <name>
acpx [global_options] <agent> sessions history
acpx [global_options] <agent> sessions history <name> [--limit <count>]
acpx [global_options] <agent> sessions watch [-s <name>] [--cursor <cursor>]
acpx [global_options] <agent> sessions export [name] --output <path> [--cwd <dir>]
acpx [global_options] <agent> sessions import <archive> [--name <name>] [--cwd <dir>]
acpx [global_options] <agent> sessions prune [--dry-run] [--before <date> | --older-than <days>] [--include-history]
acpx [global_options] sessions ... # defaults to codexBehavior:
sessionsandsessions listare equivalent--local,--filter-cwd, and the list--cursormay appear onsessionsorlist; explicitlistvalues win. Combining--localwith a cursor is rejected across either placement.- list uses ACP
session/listwhen the agent advertisessessionCapabilities.list, returning agent-nativeSessionInfometadata andnextCursorin JSON output sessions list --cursor <cursor>fetches an agent-side page from an ACP cursor returned by a prior list responsesessions list --filter-cwd <dir>sends the ACP cwd filter; relative values resolve against global--cwdsessions list --localreads saved acpx records for selectedagentCommandinstead of contacting the agent- when the agent does not support
session/list, list falls back to local saved records unless agent-side list filters were requested sessions newcreates a fresh cwd-scoped default sessionsessions new --name <name>creates a fresh named session for cwd- creating a fresh session soft-closes the previous open session in that scope (if present)
- text and quiet output print the local
acpxRecordId; JSON output also includesacpxSessionIdand, when the adapter exposes one,agentSessionId sessions ensurereturns the nearest matching active session or creates one for cwdsessions ensure --name <name>does the same for named sessionssessions closesoft-closes the current cwd default sessionsessions close <name>soft-closes current cwd named sessionsessions show [name]displays stored session metadatasessions history [name]displays stored turn history previews (default 20, configurable with--limit)sessions watch [-s <name>] [--cursor <cursor>]replays retained events and follows new ones without affecting the active turn; see Watching sessions- Watch inherits the agent's
-s/--sessionselection unless its own-s/--nameis set. Its journal cursor comes only fromwatch --cursor, independently of the list pagination cursor onsessions. sessions export [name] --output <path>writes a portable JSON archive with session state and event history;--cwd <dir>selects a different source cwd relative to global--cwdsessions import <archive>writes a fresh local record from a portable archive, reopens it as idle, keeps the provider session id, and clears source-machine process metadata- Imported sessions must resume that provider session; if the destination agent cannot load it, prompts fail clearly instead of starting an empty conversation
sessions import --name <name>and--cwd <dir>override the imported destination scope; import fails instead of creating a duplicate when an active session already exists for that(agent, cwd, name)scope or when another local record already uses the same provider session idsessions prune --dry-runpreviews closed sessions that can be deletedsessions pruneverifies the saved closed status and selected agent before deleting a record; add--include-historyto delete only that session's active and rotated event filessessions prune --before <date>and--older-than <days>filter by close time, falling back to last-used time for older records- close errors if the target session does not exist
acpx [global_options] <agent> status
acpx [global_options] <agent> status -s <name>
acpx [global_options] status
acpx [global_options] status -s <name>Shows local process status for the cwd-scoped session:
running,idle,dead, orno-session- session id, agent command, live queue-owner pid when available
- uptime when running
- last prompt timestamp
- last known exit code/signal when dead
idle means the persistent session is saved and resumable, but no queue owner is
currently running. The next prompt starts a queue owner and reconnects the
session.
Status checks are local and PID-based (kill(pid, 0) semantics). Cached session
PIDs are not reported unless a live queue-owner lease ties them to the session.
acpx [global_options] config show
acpx [global_options] config initconfig showprints the resolved config from global + project files.config initwrites a default global config template if missing.
Config files:
- global:
~/.acpx/config.json - project:
<cwd>/.acpxrc.json(merged on top of global)
Supported keys:
{
"defaultAgent": "codex",
"defaultPermissions": "approve-all",
"nonInteractivePermissions": "deny",
"authPolicy": "skip",
"ttl": 300,
"timeout": null,
"format": "text",
"agents": {
"my-custom": { "argv": ["./bin/my-acp-server", "acp"] }
},
"auth": {
"my_auth_method_id": "credential-value"
}
}CLI flags always override config values.
Custom agents should use structured agents.<name>.argv, which is required on Windows. Legacy
command plus args entries migrate when command is an unquoted executable with no whitespace.
Raw command strings, including --agent, are supported only on Unix.
For ACP authenticate handshakes, use either config auth entries or explicit
ACPX_AUTH_<METHOD_ID> environment variables such as ACPX_AUTH_OPENAI_API_KEY.
Ambient provider env vars such as OPENAI_API_KEY are still passed through to
child agents, but they do not trigger ACP auth-method selection on their own.
--agent <command> sets a raw adapter command explicitly on Unix. On Windows, define a named
agent with agents.<name>.argv so executable and argument boundaries remain unambiguous.
Examples:
acpx --agent ./my-custom-acp-server 'do something'
acpx --agent 'node ./scripts/acp-dev-server.mjs --mode ci' exec 'summarize changes'Rules:
- Do not combine positional agent and
--agentin one command. - The resolved command string becomes the session scope key (
agentCommand). - Invalid empty command or unterminated quoting in
--agentis a usage error. - An explicitly empty or whitespace-only
--agentis rejected before prompt input or adapter startup; omit the flag to use the configured default.
Session records are stored in:
~/.acpx/sessions/*.json
On POSIX systems, session records are written with mode
0600, and their session directory uses 0700. Each write reapplies these
private permissions, including when replacing an older, more permissive file.
The embedded runtime's createFileSessionStore() uses the same policy. This is
storage hardening; it does not isolate agents running under the same OS user.
Operator-managed session-directory symlinks remain supported; permissions apply
to their target directory. Windows access remains governed by the directory's ACLs.
For prompt commands:
- Detect the nearest git root by checking for a
.gitdirectory or file while walking up fromabsoluteCwd, including worktrees and submodules. - If a git root is found, walk from
absoluteCwdup to that git root (inclusive). - If no git root exists, only check exact
absoluteCwd(no parent-directory walk). - At each checked directory, find the first active (non-closed) session matching
(agentCommand, dir, optionalName). - If found, use that session record for prompt queueing and resume attempts.
- If not found, exit with code
4and print guidance to create one viasessions new.
Use sessions new [--name <name>] when you explicitly want a fresh scoped session.
Use sessions ensure [--name <name>] when you want idempotent "get-or-create" behavior.
If a saved session PID is dead, acpx respawns the agent, tries session/resume when advertised or session/load otherwise, and transparently falls back to session/new when reconnecting fails.
When a prompt is already in flight for a session, acpx uses a per-session queue owner process:
- owner process keeps the active turn running
- other
acpxinvocations enqueue prompts through local IPC - owner drains queued prompts one-by-one after each completed turn
- after the queue drains, owner waits for new work up to TTL (
--ttl, default 300s) - submitter either blocks until completion (default) or exits immediately with
--no-wait - if interrupted (
Ctrl+C) during an active turn,acpxsendssession/cancelfirst, waits briefly for cancelled completion, then force-kills only if needed
Slow submitters retain ordered live output in a temporary disk spool instead of an unbounded socket buffer. Each observer can retain up to 64 MiB of unread spool data; one queue owner allows at most 256 MiB of spool file extent, 64 open spools, and 64 observers with pending output, including completed responses whose last chunk is still buffered by the socket. Consumed disk space is reused. These are backlog limits, not limits on the total output of a progressing turn. The current serialized message still requires memory proportional to its size.
Spill and replay use bounded synchronous file operations. A full spool, exhausted
owner budget, or storage failure disconnects that observer with a nonretryable
unknown-outcome error. The admitted prompt continues and is not automatically
replayed or cancelled. Use sessions watch or sessions history to inspect the
recorded outcome before submitting again. When all output slots are occupied,
new prompt and control responses are disconnected before queuing their bytes;
their commands may still execute. Spools are unlinked before receiving
payload and are discarded on disconnect or owner exit; they do not provide
transport replay after a crash. macOS and Linux still disconnect readers that
make no socket progress for one second. Windows preserves paused named-pipe
readers within the storage limits because partial write progress is opaque.
Queue-owner records remain private across heartbeat updates. Shutdown finishes pending record updates and closes the IPC server before releasing ownership. Current clients serialize lease publication, heartbeat updates, and cleanup across processes, so stale recovery cannot remove a replacement owner's files. Recovery rechecks the owner's generation and recorded OS birth identity before each termination signal. A confirmed exit or a different birth identity permits cleanup of that generation's abandoned files without signaling a replacement process. Linux uses raw process start ticks, boot identity, and the observer's PID and time namespaces, so wall-clock changes do not change process identity. Other POSIX birth timestamps have one-second precision. Process queries and signals are separate OS operations.
Healthy owners from older versions remain usable through IPC. Explicit close
requests their normal shutdown and waits for exit. A live owner without a
verifiable birth identity is never forcibly terminated: recovery preserves its
lease and reports QUEUE_OWNER_IDENTITY_UNVERIFIED. Restore local process-query
access and retry, or let the owner finish its normal shutdown or idle expiry.
Missing identity data also preserves a live owner's lease; confirmed local
process exit still permits cleanup of older records. Incompatible identity kinds,
unknown process scope, and another namespace in the same boot preserve custody,
even when the numeric PID does not exist locally.
An invalid descendant-retirement receipt also preserves its owner's
lease and reports QUEUE_OWNER_RETIREMENT_INCOMPLETE. This includes receipt data
that cannot be sized safely; recovery does not treat it as an absent owner.
Abandoned incomplete reservations remain recoverable after the stale-owner window; ambiguous mutation guards are preserved instead of being removed by age. Guard cleanup errors remain retryable on the next status or ownership operation. A live owner stops accepting work and shuts down normally if its guard cleanup fails. The exclusion guarantee requires current clients in the same machine's local PID and time namespaces; do not share the queue home across hosts or namespaces. Older clients that bypass the guard do not participate.
If an ambiguous .acpx/queues/<queue-key>.lock.guard file or its .reclaim
directory prevents recovery, first stop all acpx commands, queue owners, and
embedding hosts using that home directory, and prevent them from restarting.
Only after establishing exclusive access may an operator remove the affected
guard and reclamation directory. Leave the lease and socket for normal recovery,
then retry status or the intended command. File age alone does not establish that
cleanup is safe; if exclusive access cannot be established, preserve the files.
- soft-closed sessions remain on disk with
closed: trueandclosedAt - auto-resume ignores closed sessions during scope lookup
- closed sessions still keep full record data and can be resumed explicitly via record id/session load flows
- session records also keep lightweight turn history previews used by
sessions history
-s, --session <name> adds name into the scope key so multiple parallel conversations can coexist in the same repo and agent command.
--cwd sets the starting point for directory-walk routing (bounded by git root) and the exact scope directory when creating sessions via sessions new.
--format controls output mode:
text(default): human-readable streamjson: raw ACP NDJSON stream for automationquiet: assistant text on stdout; failed prompts emit one structured[acpx] error:line on stderr--format json --json-strict: same ACP NDJSON stream, with non-JSON stderr output suppressed
text: assistant text, tool status blocks, client-operation logs, plan updates, and[done] <reason>json: one raw ACP JSON-RPC message per linequiet: concatenated assistant text on stdout; failed prompts emit one structured[acpx] error:line on stderr
When --suppress-reads is enabled:
text: read-like tool outputs render as[read output suppressed]json: ACPfs/read_text_fileresponses and read-like tool-call outputs replace raw file contents with[read output suppressed]quiet: unchanged, because quiet mode only prints assistant text
ACP message examples:
{"jsonrpc":"2.0","id":"req-1","method":"session/prompt","params":{"sessionId":"019c...","prompt":[{"type":"text","text":"hi"}]}}
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"019c...","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Hello"}}}}
{"jsonrpc":"2.0","id":"req-1","result":{"stopReason":"end_turn"}}Hard rule for the ACP stream:
- no acpx-specific event envelope,
- no synthetic
type/streamwrapper fields, - no ACP payload key renaming.
With --format json, prompt and exec emit raw ACP JSON-RPC messages. Controls such as cancel, set-mode, and set, and queries such as sessions list, show, and history, emit command-specific JSON result documents. A command contacting an adapter does not by itself determine its output shape.
- Agent-side
sessions listwithtext: tab-separatedsessionId,title,cwd,updatedAt, and metadata; a next cursor is printed when supplied. - Agent-side
sessions listwithjson: one object withsource: "agent"andsessions, plus optional_meta,cursor,cwd, andnextCursor. Entries use the adapter'ssessionId. - Agent-side
sessions listwithquiet: one adapter session id per line. - Local
sessions list --local, or a local fallback, withtext: tab-separated local id, name, cwd, and last-used time. - Local listing with
json: one array of full local session records. - Local listing with
quiet: one local record id per line. Closed local records have a[closed]marker in text and quiet output. sessions showwithtext: key/value metadata dumpsessions showwithjson: full session record objectsessions historywithtext: tab-separatedtimestamp role textPreviewentriessessions historywithjson: object containingid,sessionId,limit,count, andentriessessions exportwithtext: output path summarysessions exportwithjson: object containingactionandoutputsessions exportwithquiet: output pathsessions importwithtext: imported record id and cwd summarysessions importwithjson: object containingaction,record_id, andcwdsessions importwithquiet: imported record idsessions prunewithtext: summary plus pruned ids and close/last-used timesessions prunewithjson: object containingaction,dryRun,count,bytesFreed, andprunedsessions prunewithquiet: one pruned session id per linestatuswithtext: key/value process status lines
Choose exactly one mode:
--approve-all: approve tool permission requests not resolved by a per-tool policy--approve-reads: approve remaining read/search requests and prompt for other tools (default)--deny-all: deny tool permission requests not resolved by a per-tool policy
Prompting behavior in --approve-reads:
- interactive TTY: asks
Allow <tool>? (y/N)for non-read/search requests - non-interactive (no TTY): non-read/search requests are not approved
Non-interactive prompt policy:
--non-interactive-permissions deny: deny non-read/search prompts when no TTY (default)--non-interactive-permissions fail: fail withPERMISSION_PROMPT_UNAVAILABLE
Per-tool policy:
--permission-policy <json-or-file>or--policy <json-or-file>matches ACP permission requests by tool kind, title head, title, or raw input tool/name.autoDenywins overautoApprove, which wins overescalate; unmatched requests usedefaultActionwhen set, otherwise the selected permission mode.- Non-interactive escalations deny the current request. Text mode prints a
[permission]notice; JSON mode keeps raw ACP NDJSON and includes escalation details, including tool input when supplied by the agent, on thesession/request_permissionresponse at_meta.acpx.permissionEscalation.
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Agent/protocol/runtime error |
2 |
CLI usage error |
3 |
Timeout |
4 |
No session found (prompt requires an explicit sessions new) |
5 |
Permission denied (permission requested, none approved, and at least one denied/cancelled) |
130 |
Interrupted (SIGINT/SIGTERM) |
ACPX_CLAUDE_INCLUDE_USER_SETTINGS=1 makes built-in claude sessions include
Claude Code user settings. By default, they load only project and local settings
to avoid globally enabled channel or daemon plugins interfering with spawned ACP
sessions.
ACPX_PERF_METRICS_FILE enables optional NDJSON performance capture, including
command arguments. On POSIX, capture files use 0600; existing parent directory
permissions are preserved. Symbolic links, hardlinked files, and special files such
as FIFOs are skipped. Capture failures leave the command's exit status unchanged.
Related runtime behavior:
- session storage path is derived from OS home directory (
~/.acpx/sessions) - child processes inherit the current environment by default
- Windows terminal kill and release requests fail if process cleanup cannot finish after escalation. The terminal remains available for a cleanup retry; restore a working
taskkillcommand before retrying. - ACP
terminal/createhonors agentoutputByteLimit;0stores nothing and the default when omitted is 64 KiB. Hosts can opt into an additional per-terminal retention ceiling withACPX_TERMINAL_MAX_OUTPUT_BYTES(for example,16777216for 16 MiB). Unset, empty, or zero disables only the host ceiling, preserving the agent limit and default. Positive values must be safe integers. The smaller limit applies to combined stdout and stderr, retaining the newest UTF-8 output and reportingtruncated: truewhen exceeded. Truncation drops an incomplete leading code point across writes; the retained output can be empty if no complete code point fits. This bounds retained output per terminal, not total process memory. Each ACP client snapshots the setting at construction; restart warm queue owners to change it.
# Review a PR in a dedicated named session
acpx --cwd ~/repos/shop codex sessions new --name pr-842
acpx --cwd ~/repos/shop codex -s pr-842 \
'Review PR #842, list risks, and propose a minimal patch'
# Continue that same PR review later
acpx --cwd ~/repos/shop codex -s pr-842 \
'Now draft commit message and rollout checklist'
# Parallel workstreams in one repo
acpx codex sessions new --name backend
acpx codex sessions new --name docs
acpx codex -s backend 'fix checkout timeout'
acpx codex -s docs 'document payment retry behavior'
# Manage sessions
acpx codex sessions
acpx codex sessions new --name docs
acpx codex sessions show docs
acpx codex sessions history docs --limit 10
acpx codex sessions close docs
acpx codex status
# Prompt from file/stdin
echo 'triage failing tests' | acpx codex
acpx codex --file prompt.md
acpx codex --file - 'also check lint warnings'
# Config inspection
acpx config show
acpx config init
# JSON automation pipeline
acpx --format json codex exec 'review latest diff for security issues' \
| jq -r 'select(.method=="session/update") | .params.update
| select(.sessionUpdate=="tool_call" or .sessionUpdate=="tool_call_update")
| [(.status // "-"), (.title // "-")] | @tsv'
# One-shot ask with no saved context
acpx claude exec 'summarize src/session.ts in 5 bullets'ACPX_QUEUE_MAX_REQUEST_BYTES optionally bounds a queue owner's incoming request
lines in UTF-8 bytes, excluding the newline. Unset, empty, or zero keeps the
existing unlimited request size. Positive values must be safe integers.
Clients with the same setting reject oversized submissions with
QUEUE_REQUEST_TOO_LARGE before opening a socket. Owners disconnect a raw peer
that exceeds the cap, including incomplete lines, while continuing to serve
other clients. The existing owner-response limit is unchanged.
An owner keeps the setting with which it starts; setting the variable does not reconfigure an already-running owner. Request JSON can be larger than the prompt file because it carries both structured content and display text.