Skip to main content
The Agent Client Protocol (ACP) is an open protocol that lets editors and IDEs host external coding agents as first-class citizens: the IDE renders the agent’s reasoning, tool calls, plans and permission prompts natively, while the agent runs as a separate process speaking JSON-RPC over stdio. chatcli acp is ChatCLI’s ACP server. Everything you have configured in ChatCLI — providers, models, memory, contexts, skills, plugins, MCP servers — drives your IDE’s AI chat.
What the IDE renders for agent/coder runs is fully structured — not a streamed terminal transcript:
  • Thoughts — the agent’s reasoning arrives as native thought chunks (collapsible in most clients).
  • Tool calls — each action is a first-class tool call with a human title (“Reading: main.go”), a semantic kind (read, edit, execute, search…), live status, and the files it touches. Successful file reads show which file was read — never a dump of its contents into the chat.
  • Plan — the coder’s task list streams as a live plan panel, checked off as the agent progresses.
  • Final answer — clean assistant prose, rendered as markdown by the IDE.
  • Permission dialogs — dangerous commands pause the run and raise the IDE’s native Allow/Reject dialog.

Quick start

The process speaks newline-delimited JSON-RPC on stdin/stdout. All logging goes to the file logger — the protocol channel stays clean.

JetBrains IDEs (IntelliJ IDEA, GoLand, WebStorm, …)

JetBrains AI Assistant hosts custom ACP agents natively (macOS and Linux; no AI subscription required for ACP agents).
1

Open the custom-agent configuration

In the AI Chat tool window, open the agent dropdown and choose Add Custom Agent. The IDE creates and opens ~/.jetbrains/acp.json.
2

Register ChatCLI

~/.jetbrains/acp.json
  • command must be an absolute path (which chatcli to find it).
  • env is optional — with it you pin provider/model for the IDE independently of your terminal sessions; without it, ChatCLI boots with your regular .env/environment resolution.
3

Select ChatCLI and chat

Back in AI Chat, pick ChatCLI from the agent dropdown and send a prompt. Custom agents show a distinct icon.
use_custom_mcp / use_idea_mcp control which MCP servers the IDE offers to agents. ChatCLI brings its own MCP client configuration (~/.chatcli/mcp_servers.json) either way — tools you configured in ChatCLI keep working inside the IDE.

Zed

Add ChatCLI under agent_servers in Zed’s settings.json:
Then open the Agent Panel and select ChatCLI.

Session modes

Every ACP session runs in one of three modes, advertised to the client on session/new and switchable at any time: Switch modes from the IDE’s mode picker, or simply type the command in the prompt:
Mode changes are confirmed to the client via current_mode_update, so the IDE picker always reflects reality.

Slash commands in the IDE

Type / in the prompt box: the IDE autocompletes ChatCLI’s command surface (advertised via available_commands_update). Three groups: Mode switches/chat, /agent, /coder (and /run as an alias for agent). Headless-capable commands — run for real, output returned to the chat: Everything else — commands that need a live terminal (/menu, /gateway, /schedule, /auth, …) answer with a clear “not available over the IDE connection” message instead of failing silently.
A prompt that merely starts with a slash — a filesystem path like /usr/local/bin explain this, a typo’d word — is not hijacked: unknown tokens flow to the model as normal user text.
Commands that would ask for confirmation on a terminal (e.g. /context rm <name>) run with stdin quarantined on the server: any confirmation is answered as deny, fail-safe. Destructive maintenance is best done in the terminal REPL.

Permission dialogs

Unattended agent servers historically face a hard choice: auto-approve everything or block everything. ACP has a better answer — session/request_permission — and ChatCLI uses it:
  • When the coder wants to run a command classified dangerous (recursive deletes, force pushes, privilege escalation…), the run pauses and your IDE shows its native approval dialog with Allow once / Reject once.
  • Anything except an explicit Allow — reject, dialog dismissed, client crash, timeout — denies the command. The agent sees the refusal in-band and replans.
  • The same gate covers shell blocks the agent proposes in agent mode.
Clients that don’t implement the permission request (or headless drivers like MCP agent_task) get the strict behavior: dangerous commands are refused.

Your MCP servers work here too

The ACP process is a full ChatCLI boot — including the MCP client. If ~/.chatcli/mcp_servers.json exists, every configured MCP server is connected at startup and its tools join the agent’s toolbox, exactly like in the terminal:
  • Ask the agent something that needs an MCP tool (“check the open Jira issues”, “query the staging database”) and it calls the connected server’s tool autonomously. In the IDE, the call renders as a native structured tool call like any built-in.
  • Hot reload — editing mcp_servers.json reconnects servers live; no IDE or agent restart needed. /mcp from the prompt box shows connection status and tools.
  • Remote servers using OAuth must be authorized beforehand (run @mcp-login in the terminal once; tokens persist in the keychain).
Connections are established asynchronously at boot: a prompt sent in the very first seconds may not see a slow server’s tools yet — they join the catalog as soon as the connection completes.One conceptual difference from chatcli mcp-server: ACP has no client-facing tool list, so the IDE never invokes MCP tools directly — the agent uses them on your behalf. Direct tool invocation (hub passthrough) is an MCP-server feature.

Under the hood (for integrators)

ChatCLI implements ACP protocol version 1. Methods: session/update kinds emitted: agent_thought_chunk, agent_message_chunk, tool_call, tool_call_update, plan, current_mode_update, available_commands_update. Tool calls carry kind (read/edit/delete/move/search/execute/think/fetch/other), status, rawInput, locations (file paths for follow-along), and content capped for display — the model always receives the full output; the chat view gets a bounded summary. File mentions from the IDE work both ways: resource_link blocks arrive as file references the agent’s tools open themselves, and resource blocks (embedded contents) are injected as attached context.

Operational notes

  • One run at a time — agent/coder runs serialize process-wide (they share the engine state). A second session’s prompt waits for the current run to finish; a second prompt on the same session is rejected while one is in flight.
  • Environment — the ACP process is a normal ChatCLI boot: .env, keychain-backed OAuth logins, provider catalogs, MCP client config and skills all resolve exactly as in your terminal.
  • Sessions are in-process — IDE sessions map to ChatCLI’s process history. /newsession and /compact act on it; session/load is not implemented yet.
  • Logs — stdout is the protocol; diagnostics go to the standard ChatCLI log file. Set LOG_LEVEL=debug in the agent’s env block when investigating.

Troubleshooting

See also