acpx
raw JSON → 0.5.3 verified Sat Apr 25 auth: no javascript
A headless CLI client for the Agent Client Protocol (ACP), enabling AI agents and orchestrators to communicate with coding agents via structured protocol commands instead of PTY scraping. Current stable version: 0.5.3 (alpha). Released frequently with breaking changes expected until stabilization. Supports persistent multi-turn sessions, named sessions, prompt queueing, cooperative cancellation, soft-close lifecycle, crash reconnect, fire-and-forget mode, config files, session inspect/history, and experimental TypeScript-based workflows. Key differentiator: agent-to-agent communication over CLI without ANSI parsing, with compatibility for multiple ACP-compatible agents (Codex, Claude, OpenClaw ACP). Requires Node.js >=22.12.0.
Common errors
error Cannot find module 'acpx' ↓
cause Using CommonJS require() instead of ESM import.
fix
Replace 'const acpx = require("acpx")' with 'import acpx from "acpx"' in an ESM context, or use dynamic import:
const acpx = await import('acpx'). error Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/acpx/... from ... not supported. ↓
cause acpx is an ESM-only package; CommonJS require is not allowed.
fix
Switch to ESM by adding 'type': 'module' in package.json or use dynamic import.
error TypeError: flow(...) is not a function ↓
cause Flow definition not wrapped with `defineFlow` as required since v0.5.0.
fix
Wrap your flow object with
defineFlow(flow) from 'acpx/runtime'. error Error: Unknown agent: 'codex'. Available built-in adapters: ... ↓
cause Agent name mismatch or missing adapter configuration.
fix
Check available agents with
acpx config show or provide full path via --agent option. Warnings
breaking API surface is in alpha and may change significantly between minor versions. Anything built downstream may break until v1.0.0 stabilizes. ↓
fix Pin exact version in package.json and monitor changelog for breaking changes.
breaking defineFlow is now required for flow definitions as of v0.5.0. Raw flow objects are no longer accepted. ↓
fix Wrap flow definitions with defineFlow().
deprecated The `codex` adapter path may change; `codex` is currently an alias and may be renamed in future versions. ↓
fix Use the fully qualified agent name or check adapter registry with acpx config.
gotcha Node.js >=22.12.0 is required. Using older Node versions will result in runtime errors due to ESM features and internal dependencies. ↓
fix Upgrade Node.js to v22.12.0 or higher.
gotcha Session history is stored on disk by default; soft-close does not delete history. For clean state, use session.delete() or delete the session directory manually. ↓
fix Call session.delete() instead of session.close() to remove persisted history.
deprecated The experimental flow runtime (acpx flow run) API is unstable and may change in v0.6.x without notice. ↓
fix Use with caution; follow the runtime embedding API changes in changelog.
Install
npm install acpx yarn add acpx pnpm add acpx Imports
- default (library import) wrong
const acpx = require('acpx')correctimport acpx from 'acpx' - defineFlow wrong
import { defineFlow } from 'acpx'correctimport { defineFlow } from 'acpx/runtime' - FlowContext wrong
import { FlowContext } from 'acpx/runtime'correctimport type { FlowContext } from 'acpx/runtime'
Quickstart
import acpx from 'acpx';
// Start a session with Codex agent (requires CODEX_API_KEY env variable)
const session = await acpx.sessions.create({
agent: 'codex',
name: 'my-session'
});
// Send a prompt and get structured response
const response = await session.prompt('Explain async/await in JavaScript');
console.log(response.thinking);
console.log(response.toolCalls);
// Use named sessions for parallel work
const frontendSession = await acpx.sessions.create({
agent: 'codex',
name: 'frontend'
});
const backendSession = await acpx.sessions.create({
agent: 'codex',
name: 'backend'
});
await frontendSession.prompt('Create React component');
await backendSession.prompt('Add API endpoint');
// Fire-and-forget without waiting for completion
acpx.sessions.send('my-session', {
prompt: 'Run tests',
noWait: true
});
// Close session softly
await session.close();