A lightweight FastAPI server that spawns and manages multiple concurrent sessions of AI coding agents -- Claude Code, Codex CLI, Gemini CLI, and others -- over the Agent Client Protocol (ACP). It exposes a unified REST + SSE API and ships a minimal chat UI so you can interact with any supported agent from a browser.
Tools like Claude Code and Codex CLI are powerful on their own, but they each run as standalone terminal processes. If you want to:
- Run multiple agent sessions in parallel (e.g. one Claude Code session per repo),
- Drive them from a shared web UI instead of separate terminals,
- Or build your own client on top of a uniform HTTP API regardless of the underlying agent,
...you need something to sit between the agents and the outside world. ACP Server is that layer. It spawns each agent as a stdio child process, speaks ACP over the pipe, and exposes everything through a single HTTP server.
The server ships with built-in configs for Claude Code, Codex CLI, Gemini CLI, and OpenCode, but any agent that implements ACP can be plugged in. See the full list of ACP-compatible agents for what's available.
┌─────────────┐
│ Chat UI │ (static/index.html)
│ or any │
│ HTTP client│
└──────┬──────┘
│ REST + SSE
▼
┌──────────────┐
│ ACP Server │ (FastAPI, in-memory session registry)
│ │
│ /sessions │ create / list / stop
│ /prompt │ send user message
│ /stream │ SSE live updates
│ /events │ buffered history
└──────┬───────┘
│ ACP over stdio
▼
┌──────────────────────────────────────────┐
│ Agent processes (one per session) │
│ │
│ ┌───────────┐ ┌─────────┐ ┌──────────┐ │
│ │ Claude │ │ Codex │ │ Gemini │ │
│ │ Code ACP │ │ ACP │ │ CLI │ │
│ └───────────┘ └─────────┘ └──────────┘ │
└──────────────────────────────────────────┘
- Client (browser or CLI) creates a session by choosing a provider (
claude,codex,gemini,opencode). - ACP Server spawns the matching agent process, negotiates capabilities via the ACP handshake, and registers the session in memory.
- The client sends prompts and receives streaming updates (tool use, text deltas, permission requests) over SSE.
- Sessions are independent -- you can run as many as you want, across different providers and working directories.
- Python >= 3.13
- uv (for dependency management and running)
- Node.js (managed via nvm) -- needed for the ACP adapter binaries
- ACP adapters installed globally via npm:
@agentclientprotocol/claude-agent-acp(for Claude Code)@zed-industries/codex-acp(for Codex CLI)- Gemini CLI with
--experimental-acpflag
- Valid API keys / credentials for whichever agent you want to use
# 1. Install all dependencies (uv, Node.js, ACP adapters, CLI agents)
./install_dependencies.sh
# 2. Configure environment variables in run.sh
# Edit run.sh to set ACP_USERNAME, ACP_PASSWORD, ACP_URL_PREFIX, and ACP_BASE_DIR
# 3. Start the server
./run.sh
# 4. Open http://localhost:8000 in your browser
# The server binds to 0.0.0.0 so it's also reachable via your machine's IP or hostname.A CLI client (cli.py) is included for scripting and quick interaction:
uv run python cli.py providers # list available providers
uv run python cli.py create --provider claude --cwd .
uv run python cli.py prompt <id> "fix the failing test"
uv run python cli.py stream <id> # live SSE stream
uv run python cli.py stop <id>| Variable | Description |
|---|---|
ACP_PORT |
Server port (default 8000) |
ACP_BASE_DIR |
Default working directory for all sessions |
ACP_URL_PREFIX |
URL prefix if served behind a reverse proxy |
ACP_PASSWORD / ACP_USERNAME |
Basic auth credentials |
ACP_UPLOAD_MAX_FILE_BYTES |
Max size per uploaded file (default 8 MB) |
ACP_UPLOAD_MAX_TOTAL_BYTES |
Max total upload size per request (default 24 MB) |
ACP_UPLOAD_MAX_FILES |
Max files per upload (default 6) |
Edit app/config.py and add an entry to the PROVIDERS dict:
"my-agent": ProviderConfig(
name="my-agent",
command="/path/to/my-agent-binary",
args=("--experimental-acp",),
env={"SOME_VAR": "value"},
default_cwd=".",
permission_policy="prompt",
),Each provider (or individual session) can be configured with a permission policy:
prompt-- ask the user (default; UI wiring not yet complete)auto_approve-- automatically approve tool-use requestsdeny-- reject all tool-use requests