Skip to main content

Thin Python CLI client for the Agent Client Protocol (ACP)

Project description

acpc

Thin Python CLI client for the Agent Client Protocol (ACP).

Status: alpha (v0.1). No persistent daemon yet, so every call pays a 3-10s cold start while the adapter boots. Fine for scripts and CI, painful for interactive loops. v0.2 will add a daemon. See Known limitations.

What is acpc?

acpc is a headless Python CLI for ACP, built on top of the official agent-client-protocol SDK. Output is plain text with no ANSI escapes, so it composes cleanly with pipes, files, and other agents.

Install

pip install acpc
# or
uv tool install acpc

Requires Python 3.12+.

Quick start

# Send a prompt to Codex
acpc prompt codex "fix the tests"

# Use a model preset
acpc prompt claude "analyze this repo" --model fast

# Pipe a prompt from stdin
echo "explain the architecture" | acpc prompt codex -

# Read prompt from file, write output to file
acpc prompt codex --input-file task.md -o result.md

Commands

Command Description
prompt <agent> [text] Send a prompt to an ACP agent
run <agent> [text] Alias for prompt
models [agent] Show available models and presets
agents List registered agents and install status
sessions <agent> List agent sessions (via ACP)
install <agent> Run the agent's install command
stop <agent> Stop running sessions for an agent
stop -s <id> Stop a specific session by ID
status Show all running sessions
generate-completion Generate or install shell completions

Options reference

All options for the prompt command:

Flag Description ACP mapping
--last Resume the last session session/load
-s, --session ID Resume session by ID session/load
--model MODEL Model ID or preset (fast/standard/max) session/set_model
--mode MODE Set mode for the session session/set_mode
--permissions LEVEL Permission policy (see below) request_permission
--cwd DIR Working directory for the agent session/new (cwd)
--json NDJSON output (ACP events) local
--quiet Final text only (no streaming) local
-o, --output FILE Write output to file local
--input-file FILE Read prompt from file local
--timeout SECS Timeout in seconds local
--dry-run Resolve config and exit without running local

Model presets

Instead of memorizing vendor-specific model IDs, use one of three tier names:

acpc prompt claude --model fast       # cheapest, fastest
acpc prompt claude --model standard   # default
acpc prompt codex --model max         # most capable

Run acpc models to see what each preset resolves to for a given agent.

Presets live in ~/.agents/config.toml. If the file doesn't exist, built-in defaults are used:

[models.claude]
fast = "haiku"
standard = "sonnet"
max = "opus"

[models.codex]
fast = "..."
standard = "..."
max = "..."

Use --dry-run to verify what model will be used without running:

acpc prompt codex --model standard "task" --dry-run

Discovering models

acpc models           # show presets and available models for all agents
acpc models claude    # show for a specific agent

Available models are cached from ACP responses (TTL 7 days). Each acpc prompt call refreshes the cache as a side effect, so it stays fresh without an extra round-trip. If the cache is stale, acpc models <agent> fetches live from the adapter.

Permissions

The --permissions flag controls how acpc responds to ACP permission requests. Tool calls are classified by their kind field into three categories.

Level read-like edit/execute delete/move
all allow allow allow
write allow allow deny
read allow deny deny
none deny deny deny
prompt allow ask user ask user

Read-like tool kinds: read, search, think, fetch, switch_mode, other.

Default: prompt when stdin is a TTY, read when piped (non-TTY).

In non-interactive contexts, denied operations cause exit code 3.

Output modes

stdout carries agent output only. stderr carries [acpc]-prefixed diagnostics.

text (default): Agent text streams to stdout as it arrives. Tool calls appear on stderr as [acpc] tool: edit:src/main.py.

acpc prompt codex "fix the bug" > fix.md

json: Every ACP session_update event passes through as NDJSON. The stream is wrapped by session_started, session_ended, and session_error meta-events.

acpc prompt codex "fix the bug" --json | jq 'select(.sessionUpdate == "agent_message_chunk")'

quiet: Collects all text, emits only the final result when the session ends. The -o flag writes to a file (not written on crash).

acpc prompt codex "summarize" --quiet -o summary.md

Multi-turn sessions

Every completed session saves its ID per agent. Use --last to resume:

acpc prompt codex "remember: the password is hunter2"
acpc prompt codex --last "what was the password?"

Resume a specific session by ID:

acpc prompt codex -s 019cf2ca-b50f-7a13-ad67-14fe4db0e0ac "follow up"

Session IDs and resume commands appear on stderr:

[acpc] session: 019cf2ca-b50f-7a13-ad67-14fe4db0e0ac
[acpc] resume: acpc prompt codex -s 019cf2ca-b50f-7a13-ad67-14fe4db0e0ac "follow up"

Last-session tracking is scoped per PPID to avoid race conditions in concurrent use.

Agent registry

Agents are defined in TOML files. Three agents ship built-in (codex, claude, gemini). Run acpc agents to see the current list and install status.

TOML format

identity = "my-agent"
name = "My Agent"
author = "Me"
run_command = "my-agent-acp"
install_command = "npm install -g my-agent-acp"

User overrides

Place .toml files in the platform config directory to add or override agents:

  • Linux: ~/.config/acpc/agents/
  • macOS: ~/Library/Application Support/acpc/agents/
  • Windows: %APPDATA%\acpc\agents\

User overrides take priority over built-in agents with the same identity.

Installing adapters

acpc install codex    # runs the install_command from the TOML file
acpc agents           # shows install status for all agents

Process management

Running sessions are tracked in the platform state directory (~/.local/state/acpc/ on Linux). Each entry stores PID, agent identity, working directory, and start time.

acpc status                              # list running sessions
acpc stop codex                          # stop all sessions for codex
acpc stop -s 019cf2ca-b50f-7a13-ad67     # stop a specific session

Signal handling: Ctrl+C sends session/cancel via ACP, waits 2s for the agent to exit cleanly, then sends SIGKILL to the entire process group. Child processes are spawned in their own process group to prevent orphans.

Exit codes

Code Meaning
0 Success (end_turn)
1 Agent error (max_tokens, max_turn_requests, ACP error)
2 Usage error (unknown agent, missing prompt)
3 Permission denied (non-interactive)
124 Timeout (--timeout exceeded)
130 SIGINT (Ctrl+C)
141 SIGPIPE
143 SIGTERM

Trust model

TOML agent files define run_command and install_command, which acpc executes as shell commands. This is the same trust level as shell aliases or PATH entries. Only place TOML files you trust in the config directory.

The spawned adapter process inherits your full environment (env vars, PATH, credentials). Environment filtering (--env) is planned for v0.2. As a workaround, use env -i to strip the environment:

env -i HOME="$HOME" PATH="$PATH" acpc prompt codex "task"

CI usage

In non-TTY environments (CI, scripts, pipes), permissions default to read. Use --permissions all to allow writes, or --permissions none for dry runs.

# CI: run agent, capture JSON output, check exit code
acpc prompt codex "run the test suite and fix failures" \
    --permissions all \
    --json \
    --timeout 300 \
    > agent-output.ndjson

if [ $? -eq 0 ]; then
    echo "Agent completed successfully"
elif [ $? -eq 124 ]; then
    echo "Agent timed out"
else
    echo "Agent failed with exit code $?"
fi
# Parse agent text from NDJSON
acpc prompt codex "summarize changes" --json \
    | jq -r 'select(.sessionUpdate == "agent_message_chunk") | .content.text' \
    | tr -d '\n'

Known limitations

v0.1 covers the basics. A few rough edges to be aware of:

  • Cold start per call (~3-10s). Every acpc prompt spawns a fresh adapter process. No persistent daemon yet, so interactive multi-turn loops feel slow. Scripts and CI are fine. The daemon lands in v0.2.
  • Unix-only. Linux and macOS work. Windows is planned for v0.3 (needs named pipes instead of Unix sockets, and taskkill instead of killpg).
  • --last is not orchestration-safe. Last-session tracking is scoped per parent PID. That works for a human in a terminal, but breaks when one orchestrator agent spawns several acpc calls. For programmatic use, grab the session ID from stderr and pass it back with -s SESSION_ID. acpc warns when --last is used.
  • Gemini needs GEMINI_API_KEY in env. OAuth reuse in ACP subprocess mode is broken upstream (gemini-cli #7549, #12042). API key is the only reliable auth path right now.
  • No env filtering. The spawned adapter inherits your full environment (see Trust model). An --env flag is planned for v0.2.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

acpc-0.1.0.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

acpc-0.1.0-py3-none-any.whl (30.1 kB view details)

Uploaded Python 3

File details

Details for the file acpc-0.1.0.tar.gz.

File metadata

  • Download URL: acpc-0.1.0.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for acpc-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0e7156ba00d40a1161724f38585c0f2b93f0f4c6e0297dff4f69cfe2780f13a9
MD5 f3a00a3b13cb61f5ebfde96c1e7ace21
BLAKE2b-256 a9bbf5ad268868a8d718ea6cfab8390f512e79b88ccccb479ff33ad80aa6cbac

See more details on using hashes here.

File details

Details for the file acpc-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: acpc-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for acpc-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 817224403298a6a793a7bcc7903a6036cb087ea6d4ba7777e0af8323180be7ee
MD5 6a4314ac705ea6f20ea395f1d9ca5769
BLAKE2b-256 010c7d0f43b5205cf6d9fd78ac6935d3d49438aa0d0f959f04637261db3f90dc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page