| title | Prompting |
|---|---|
| description | How acpx submits prompts — implicit vs explicit, persistent vs one-shot, stdin and --file input, queue submission with --no-wait, and timeouts. |
acpx has one core operation: send a prompt to an ACP agent and stream the response. Everything else (sessions, queueing, cancel, mode) wraps that.
The CLI accepts a prompt in five interchangeable ways:
# 1. Implicit, positional text. Defaults to codex when no agent is given.
acpx codex 'fix the failing tests'
acpx 'summarize this branch'
# 2. Explicit `prompt` subcommand.
acpx codex prompt 'fix the failing tests'
acpx prompt 'summarize this branch'
# 3. From stdin (piped).
echo 'review changed files' | acpx codex
git diff | acpx codex prompt
# 4. From a file.
acpx codex --file ./brief.md
acpx codex prompt -f ./brief.md
# 5. From stdin, with extra context appended.
git diff | acpx codex --file - 'and call out anything risky'Unicode text is preserved across piped input chunks, including structured prompts,
--file -, and compare.
Structured JSON prompts can include ACP resource_link blocks with a string
name and non-empty uri. Their optional title may be a string or null;
both are preserved through file input, stdin, and queued prompts. Embedded
resource blocks require a string resource.text or resource.blob, plus the
agent's embeddedContext capability. Empty strings are valid names and payloads.
The --file - form is particularly handy for piping a long prompt from another tool while still tacking on a short instruction at the end.
| Command | Reuses saved session? | Writes saved session? | Queue-aware? |
|---|---|---|---|
prompt |
Yes — resumes by scope | Updates history | Yes |
| (bare) | Same as prompt |
Same as prompt |
Yes |
exec |
No — temporary session | No | No |
exec is the right choice when:
- you want a stateless answer in a script (
SUMMARY=$(acpx --format quiet codex exec '…')) - you do not want to fork a session by accident
- you need machine-readable JSON output without later turns appended
prompt (or bare) is the right choice when:
- the conversation should remember earlier turns
- you want queue-aware submission with
--no-wait - you want
cancel/set-mode/setto apply to the same session
Top-level acpx prompt …, acpx exec …, acpx cancel, acpx set-mode …, acpx set …, and acpx sessions … all default to the codex agent. You can change the default for your environment by setting defaultAgent in config:
{ "defaultAgent": "claude" }CLI flags still win, so acpx codex … always runs codex even if defaultAgent is claude.
Available on prompt, the bare implicit form, and exec:
| Option | Description |
|---|---|
-s, --session |
Use a named session within the current cwd scope |
--no-wait |
Enqueue and return immediately if a prompt is already running |
-f, --file |
Read prompt text from a file (- reads stdin and still allows extra args) |
--no-wait is per-prompt; the next call without --no-wait will block normally.
After an agent name, --file and --no-wait can appear before the explicit prompt subcommand or on it. exec accepts --file in either position as well. When both levels supply a file, the subcommand's explicit file wins. File input still combines with positional text, including when --file - reads stdin; text after -- remains literal prompt content.
When a turn is already in flight for the target session, acpx does not spawn a second adapter. It submits to the running queue owner over local IPC. The submitter then either:
- blocks until the queued prompt completes (default), streaming events as they happen, or
- returns as soon as the owner acknowledges (
--no-wait).
Queued prompts drain in submission order. After the queue empties, the owner stays alive for an idle TTL (--ttl <seconds>, default 300).
# Long-running turn
acpx codex 'run the full test suite and triage failures'
# Queue follow-ups without waiting
acpx codex --no-wait 'after that, summarize root cause in 3 bullets'
acpx codex --no-wait 'and propose 1 minimal fix'Ctrl+C while waiting on a queued or running prompt sends ACP session/cancel first, waits briefly for the cancelled completion, and falls back to a force-kill only if the agent does not respond. See Session control for the explicit cancel command.
For applications using acpx/runtime, AcpRuntimeTurn.promptStarted resolves only after the writable ACP transport accepts that turn's prompt request. It remains pending under transport backpressure and rejects if submission or the write fails.
Readiness does not mean the agent has finished processing the prompt. Await turn.result for the turn outcome after persistence and cleanup have settled.
You may hold the object returned by startTurn() before reading its promises or events. Early startup or admission errors remain observable when you later consume that turn.
In-process createAcpRuntime() turns accept an optional synchronous assertActive
callback on both startTurn() and runTurn(). Throw when the host no longer
permits the prompt, even if its AbortSignal has not been aborted:
const turn = runtime.startTurn({
handle,
requestId: crypto.randomUUID(),
mode: "prompt",
text: "Review the repository",
signal: abortController.signal,
assertActive() {
if (!admission.active) {
throw new Error("Prompt admission revoked");
}
},
});The callback may run more than once. Keep it synchronous and safe to repeat.
ACPX checks authority after turn preparation and again immediately before the
native prompt transport write, including after SDK write-queue waits. A rejected
prompt is not written: promptStarted rejects with the original callback error,
and result reports a failed turn after normal persistence and cleanup.
runTurn() reports that failure as its terminal error event. An aborted turn
signal still produces a cancelled result.
This guards prompt admission, not session creation, reconnect, or local
checkpoint writes that preparation may already have performed. A rejection at
the transport boundary closes that connection; a persistent session reconnects
on the next turn. After the write is admitted, changing host authority does not
cancel the prompt or discard its result. Use turn.cancel() or abort the signal
to request cancellation. Callers without assertActive retain their existing
behavior. Shared runtimes reject this in-process callback.
ACP has no request that adds input to a prompt that is already running, so
mode: "steer" does not interrupt or extend the active turn. In-process
createAcpRuntime() admits a steer turn like a prompt turn: it waits behind any
active turn on the same session, its promptStarted resolves only after that
turn settles, and it runs as the next prompt. To redirect work in progress,
cancel the active turn first, then start the new one.
Shared runtimes reject steer turns.
--timeout <seconds> caps how long acpx will wait for an agent response. It applies to:
- the active prompt turn
- the per-step default for flows
acpandactionnodes (15 minutes when--timeoutis omitted)
acpx --timeout 90 codex 'investigate the intermittent test timeout'Decimal seconds are allowed. Negative or zero is rejected as a usage error.
If no final ACP response arrives by the end of the bounded update drain, acpx exits with code 3. Partial assistant text does not count as completion. A final response received during that drain retains its actual stop reason, usage, and metadata.
Before the next queued prompt starts, acpx attempts cooperative cancellation of unfinished work and closes its connection. Cancellation and process cleanup can add time beyond the response deadline. The next turn reconnects using the saved provider session; shared sessions require that exact session to resume successfully.
--model <id> requests a specific model:
acpx --model gpt-5.4 codex exec 'one-shot summary'
acpx --model claude-sonnet-4-6 claude 'do the thing'Behavior varies by adapter:
- Claude consumes the value as session-creation metadata.
- Other agents must advertise a model session config option or legacy
modelsmetadata. Config options usesession/set_config_option; explicitly advertised legacy models usesession/set_model. - Model ids must appear in the adapter's advertised values. Unknown ids are rejected.
- Cursor may advertise model variants with bracketed settings such as
composer-2.5[fast=false]. When exactly one advertised Cursor id has the requested bare model as its prefix,acpxforwards that advertised id automatically; ambiguous variants remain rejected.
For mid-session model switches, use set model <id> instead. See Session control.
exec accepts repeatable --config-option <key=value> flags for adapter-advertised ACP
session controls. ACPX applies the requested model first, then the config options in command
order, and only then sends the prompt:
acpx --model gpt-5.4 codex exec \
--config-option reasoning_effort=high \
'one-shot review'The temporary selection is not saved. If any session/set_config_option request fails, exec
reports the adapter error and does not start the prompt.
Prompts can trigger permission requests for tool calls. The default policy auto-approves reads and prompts for writes; non-interactive runs default to deny. See Permissions.
acpx --approve-all codex 'apply the patch and run tests'
acpx --deny-all codex 'analyze without using any tools'Whichever way you supply prompt text, acpx concatenates the file (or stdin) with positional args, separated by a blank line. That is what makes --file - plus appended args work.
If neither stdin is piped nor --file is provided and there are no positional args, acpx prints help and exits.
# Implicit, codex default
acpx 'review the latest commit'
# Explicit agent and explicit verb
acpx claude prompt 'refactor src/auth into clearer modules'
# Stdin + appended ask
git log --oneline -n 20 | acpx codex --file - 'pick the 3 most important changes'
# One-shot JSON for automation
acpx --format json codex exec 'list TODO comments by file' \
| jq -r 'select(.method=="session/update")'
# Named session + fire-and-forget follow-up
acpx codex sessions new --name release
acpx codex -s release 'collect changes since v0.6.0'
acpx codex -s release --no-wait 'then draft release notes'- Sessions — scope rules, queueing, and crash recovery in depth.
- Session control —
cancel,set-mode,set. - Output formats — what gets emitted per format and
--suppress-reads. - CLI reference — formal grammar.