npm package: @opendeepcrew/acpx
Description: Headless CLI client for the Agent Client Protocol (ACP) — talk to coding agents from the command line
Author: OpenDeepCrew
Latest version: 0.0.2

<p align="center">
  <img src="acpx_banner.svg" alt="acpx banner" width="100%" />
</p>

# acpx

[![npm version](https://img.shields.io/npm/v/@opendeepcrew/acpx.svg)](https://www.npmjs.com/package/@opendeepcrew/acpx)
[![npm downloads](https://img.shields.io/npm/dm/@opendeepcrew/acpx.svg)](https://www.npmjs.com/package/@opendeepcrew/acpx)
[![CI](https://github.com/open-deep-clew/acpx/actions/workflows/ci.yml/badge.svg)](https://github.com/open-deep-clew/acpx/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js](https://img.shields.io/node/v/@opendeepcrew/acpx.svg)](https://nodejs.org)

> ⚠️ `acpx` is in alpha and the CLI/runtime interfaces are likely to change. Anything you build downstream of this might break until it stabilizes.

> ACP coverage status: see [ACP Spec Coverage Roadmap](docs/2026-02-19-acp-coverage-roadmap.md).

Your agents love acpx! 🤖❤️ They hate having to scrape characters from a PTY session 😤

`acpx` is a headless CLI client for the [Agent Client Protocol (ACP)](https://agentclientprotocol.com), so AI agents and orchestrators can talk to coding agents over a structured protocol instead of PTY scraping.

One command surface for Codex, Claude, Gemini, OpenCode, Pi, or custom ACP servers. Built for agent-to-agent communication over the command line.

- **Persistent sessions**: multi-turn conversations that survive across invocations, scoped per repo
- **Named sessions**: run parallel workstreams in the same repo (`-s backend`, `-s frontend`)
- **Prompt queueing**: submit prompts while one is already running, they execute in order
- **Cooperative cancel command**: `cancel` sends ACP `session/cancel` via queue IPC without tearing down session state
- **Soft-close lifecycle**: close sessions without deleting history from disk
- **Queue owner TTL**: keep queue owners alive briefly for follow-up prompts (`--ttl`)
- **Fire-and-forget**: `--no-wait` queues a prompt and returns immediately
- **Graceful cancel**: `Ctrl+C` sends ACP `session/cancel` before force-kill fallback
- **Session controls**: `set-mode` and `set <key> <value>` for `session/set_mode` and `session/set_config_option`
- **Crash reconnect**: dead agent processes are detected and sessions are reloaded automatically
- **Prompt from file/stdin**: `--file <path>` or piped stdin for prompt content
- **Config files**: global + project JSON config with `acpx config show|init`
- **Session inspect/history**: `sessions show` and `sessions history --limit <n>`
- **Local status checks**: `status` reports running/dead/no-session, pid, uptime, last prompt
- **Client methods**: stable `fs/*` and `terminal/*` handlers with permission controls and cwd sandboxing
- **Auth handshake**: stable `authenticate` support via env/config credentials
- **Structured output**: typed ACP messages (thinking, tool calls, diffs) instead of ANSI scraping
- **Any ACP agent**: built-in registry + `--agent` escape hatch for custom servers
- **One-shot mode**: `exec` for stateless fire-and-forget tasks

```bash
$ acpx codex sessions new
$ acpx codex "find the flaky test and fix it"

[thinking] Investigating test suite for flaky failures

[tool] Run npm test -- --reporter=verbose (running)
[tool] Run npm test -- --reporter=verbose (completed)
  output:
    ✓ auth.login (0.8s)
    ✗ checkout.submit (timed out after 5000ms)
    ✓ cart.add (0.3s)

[thinking] Found it — checkout.submit has a race condition in the async setup

[tool] Edit src/checkout.test.ts (completed)
  output:
    Success. Updated 1 file.

[tool] Run npm test -- checkout.submit (completed)
  output:
    ✓ checkout.submit (0.4s)

Fixed: added `await` to the setup hook in checkout.submit. The test was
reading stale state from the previous run.

[done] end_turn
```

## Quick setup — tell your agent about acpx

Copy the block below and paste it into your OpenClaw, Pi, Claude Code, or similar agent harness. It will install acpx, read the skill reference, and know how to use ACP for all future coding agent tasks.

```text
I want you to use acpx to run coding agents over the Agent Client Protocol
(ACP) instead of scraping PTY sessions. Please do the following:

1. Install acpx globally (recommended) or use npx:
   npm install -g @opendeepcrew/acpx@latest

   Or without installing:
   npx @opendeepcrew/acpx@latest

2. Install the acpx skill so you have the full reference available:
   npx @opendeepcrew/acpx@latest --skill install acpx

3. Read the acpx skill reference so you know every command, flag, and
   workflow pattern:
   https://raw.githubusercontent.com/open-deep-clew/acpx/main/skills/acpx/SKILL.md

4. If you need the full CLI reference with all options and examples:
   https://raw.githubusercontent.com/open-deep-clew/acpx/main/docs/CLI.md

From now on, when you need to delegate work to a coding agent, use acpx
instead of spawning raw terminal sessions. For example:
  npx @opendeepcrew/acpx@latest codex "fix the failing tests"
  npx @opendeepcrew/acpx@latest claude "refactor the auth module"
  npx @opendeepcrew/acpx@latest codex exec "one-shot: summarize this repo"
```

## Install

```bash
npm install -g @opendeepcrew/acpx@latest
```

Or run without installing:

```bash
npx @opendeepcrew/acpx@latest codex "fix the tests"
```

Session state lives in `~/.acpx/` either way. Global install is a little faster, but `npx @opendeepcrew/acpx@latest` works fine.

## Agent prerequisites

`acpx` auto-downloads ACP adapters with `npx` on first use. You do not need to install adapter packages manually.

The only prerequisite is the underlying coding agent you want to use:

- `acpx codex` -> Codex CLI: https://codex.openai.com
- `acpx claude` -> Claude Code: https://claude.ai/code
- `acpx gemini` -> Gemini CLI: https://github.com/google/gemini-cli
- `acpx opencode` -> OpenCode: https://opencode.ai
- `acpx kiro` -> Kiro: https://kiro.dev
- `acpx pi` -> Pi Coding Agent: https://github.com/mariozechner/pi

### 全局安装 ACP adapter（推荐国内用户）

默认情况下 `acpx` 通过 `npx` 在线下载 ACP adapter，如果你的网络环境访问 npm 较慢或需要走代理，建议将 adapter 全局安装到本地，避免每次启动都下载：

```bash
# 安装 claude agent adapter
npm install -g @zed-industries/claude-agent-acp

# 安装 codex agent adapter
npm install -g @zed-industries/codex-acp
```

全局安装后 `npx` 会优先使用本地已安装的版本，无需额外配置。

## Usage examples

```bash
acpx codex sessions new                        # create a session (explicit) for this project dir
acpx codex 'fix the tests'                     # implicit prompt (routes via directory-walk)
acpx codex prompt 'fix the tests'              # explicit prompt subcommand
echo 'fix flaky tests' | acpx codex            # prompt from stdin
acpx codex --file prompt.md                    # prompt from file
acpx codex --file - "extra context"            # explicit stdin + appended args
acpx codex --no-wait 'draft test migration plan' # enqueue without waiting if session is busy
acpx codex cancel                               # cooperative cancel of in-flight prompt
acpx codex set-mode plan                        # session/set_mode
acpx codex set approval_policy conservative     # session/set_config_option
acpx exec 'summarize this repo'                # default agent shortcut (codex)
acpx codex exec 'what does this repo do?'      # one-shot, no saved session

acpx codex sessions new --name api              # create named session
acpx codex -s api 'implement cursor pagination' # prompt in named session
acpx codex sessions new --name docs             # create another named session
acpx codex -s docs 'rewrite API docs'           # parallel work in another named session

acpx codex sessions              # list sessions for codex command
acpx codex sessions list         # explicit list
acpx codex sessions show         # inspect cwd session metadata
acpx codex sessions history      # show recent turn history
acpx codex sessions new          # create fresh cwd-scoped default session
acpx codex sessions new --name api # create fresh named session
acpx codex sessions ensure       # return existing scoped session or create one
acpx codex sessions ensure --name api # ensure named scoped session
acpx codex sessions close        # close cwd-scoped default session
acpx codex sessions close api    # close cwd-scoped named session
acpx codex status                # local process status for current session

acpx config show                 # show resolved config (global + project)
acpx config init                 # create ~/.acpx/config.json template

acpx claude 'refactor auth middleware' # built-in claude agent
acpx gemini 'add startup logging'      # built-in gemini agent

acpx my-agent 'review this patch'                      # unknown name -> raw command
acpx --agent './bin/dev-acp --profile ci' 'run checks' # --agent escape hatch
```

## Practical scenarios

```bash
# Review a PR in a dedicated session and auto-approve permissions
acpx --cwd ~/repos/shop --approve-all codex -s pr-842 \
  'Review PR #842 for regressions and propose a minimal fix'

# Keep parallel streams for the same repo
acpx codex -s bugfix 'isolate flaky checkout test'
acpx codex -s release 'draft release notes from recent commits'
```

## Global options in practice

```bash
acpx --approve-all codex 'apply the patch and run tests'
acpx --approve-reads codex 'inspect repo structure and suggest plan' # default mode
acpx --deny-all codex 'explain what you can do without tool access'
acpx --non-interactive-permissions fail codex 'fail instead of deny in non-TTY'

acpx --cwd ~/repos/backend codex 'review recent auth changes'
acpx --format text codex 'summarize your findings'
acpx --format json codex exec 'review changed files'
acpx --format json --json-strict codex exec 'machine-safe JSON only'
acpx --format quiet codex 'final recommendation only'

acpx --timeout 90 codex 'investigate intermittent test timeout'
acpx --ttl 30 codex 'keep queue owner alive for quick follow-ups'
acpx --verbose codex 'debug why adapter startup is failing'
```

## Configuration files

`acpx` reads config in this order (later wins):

1. global: `~/.acpx/config.json`
2. project: `<cwd>/.acpxrc.json`

CLI flags always win over config values.

Supported keys:

```json
{
  "defaultAgent": "codex",
  "defaultPermissions": "approve-all",
  "nonInteractivePermissions": "deny",
  "authPolicy": "skip",
  "ttl": 300,
  "timeout": null,
  "format": "text",
  "agents": {
    "my-custom": { "command": "./bin/my-acp-server" }
  },
  "auth": {
    "my_auth_method_id": "credential-value"
  },
  "proxy": {
    "httpProxy": "http://127.0.0.1:7890",
    "httpsProxy": "http://127.0.0.1:7890",
    "noProxy": "localhost,127.0.0.1"
  }
}
```

### 代理（Proxy）配置

`proxy` 对象用于为所有 spawn 的 agent 子进程配置 HTTP/HTTPS 代理。三个字段均为可选，留空字符串 `""` 或省略即可跳过。

- `httpProxy`：HTTP 请求代理，必须以 `http://` 或 `https://` 开头
- `httpsProxy`：HTTPS 请求代理，必须以 `http://` 或 `https://` 开头
- `noProxy`：逗号分隔的不走代理的主机列表

代理值会在启动时注入 `process.env`（`HTTP_PROXY`、`http_proxy`、`HTTPS_PROXY`、`https_proxy`、`NO_PROXY`、`no_proxy`）。已有的环境变量优先级更高，配置文件不会覆盖它们。所有子进程自动继承这些环境变量。

Use `acpx config show` to inspect the resolved result and `acpx config init` to create the global template.

## Output formats

```bash
# text (default): human-readable stream with tool updates
acpx codex 'review this PR'

# json: NDJSON events, useful for automation
acpx --format json codex exec 'review this PR' \
  | jq -r 'select(.type=="tool_call") | [.status, .title] | @tsv'

# json-strict: suppresses non-JSON stderr output (requires --format json)
acpx --format json --json-strict codex exec 'review this PR'

# quiet: final assistant text only
acpx --format quiet codex 'give me a 3-line summary'
```

JSON events include a stable envelope for correlation:

```json
{
  "eventVersion": 1,
  "sessionId": "abc123",
  "requestId": "req-42",
  "seq": 7,
  "stream": "prompt",
  "type": "tool_call"
}
```

Session-control JSON payloads (`sessions new|ensure`, `status`) may also include
`runtimeSessionId` when the adapter exposes a provider-native session ID.

## Built-in agents and custom servers

Built-ins:

| Agent      | Adapter                                                                | Wraps                                                 |
| ---------- | ---------------------------------------------------------------------- | ----------------------------------------------------- |
| `codex`    | [codex-acp](https://github.com/zed-industries/codex-acp)               | [Codex CLI](https://codex.openai.com)                 |
| `claude`   | [claude-agent-acp](https://github.com/zed-industries/claude-agent-acp) | [Claude Code](https://claude.ai/code)                 |
| `gemini`   | native                                                                 | [Gemini CLI](https://github.com/google/gemini-cli)    |
| `opencode` | native                                                                 | [OpenCode](https://opencode.ai)                       |
| `pi`       | [pi-acp](https://github.com/svkozak/pi-acp)                            | [Pi Coding Agent](https://github.com/mariozechner/pi) |
| `kiro`     | native                                                                 | [Kiro](https://kiro.dev)                              |

Use `--agent` as an escape hatch for custom ACP servers:

```bash
acpx --agent ./my-custom-acp-server 'do something'
```

## Session behavior

- Prompt commands require an existing saved session record (created via `sessions new` or `sessions ensure`).
- Prompts route by walking up from `cwd` (or `--cwd`) to the nearest git root (inclusive) and selecting the nearest active session matching `(agent command, dir, optional name)`.
- If no git root is found, prompts only match an exact `cwd` session (no parent-directory walk).
- `-s <name>` selects a parallel named session during that directory walk.
- `sessions new [--name <name>]` creates a fresh session for that scope and soft-closes the prior one.
- `sessions ensure [--name <name>]` is idempotent: it returns an existing scoped session or creates one when missing.
- `sessions close [name]` soft-closes the session: queue owner/processes are terminated, record is kept with `closed: true`.
- Auto-resume for cwd scope skips sessions marked closed.
- Prompt submissions are queue-aware per session. If a prompt is already running, new prompts are queued and drained by the running `acpx` process.
- Queue owners use an idle TTL (default 300s). `--ttl <seconds>` overrides it; `--ttl 0` keeps owners alive indefinitely.
- `--no-wait` submits to that queue and returns immediately.
- `cancel` sends cooperative `session/cancel` to the running queue owner process and returns success when no prompt is running (`nothing to cancel`).
- `set-mode` and `set` route through queue-owner IPC when active, otherwise they reconnect directly to apply `session/set_mode` and `session/set_config_option`.
- `exec` is always one-shot and does not reuse saved sessions.
- Session metadata is stored under `~/.acpx/sessions/`.
- Each successful prompt appends lightweight turn history previews (`role`, `timestamp`, `textPreview`) to session metadata.
- `Ctrl+C` during a running turn sends ACP `session/cancel` and waits briefly for `stopReason=cancelled` before force-killing if needed.
- If a saved session pid is dead on the next prompt, `acpx` respawns the agent, attempts `session/load`, and transparently falls back to `session/new` if loading fails.

## Full CLI reference

See `docs/CLI.md`.

## License

MIT