Skip to main content
O Agent Client Protocol (ACP) é um protocolo aberto que permite a editores e IDEs hospedar agentes de código externos como cidadãos de primeira classe: a IDE renderiza nativamente o raciocínio, as tool calls, o plano e os pedidos de permissão do agente, enquanto o agente roda como um processo separado falando JSON-RPC via stdio. chatcli acp é o servidor ACP do ChatCLI. Tudo que você configurou no ChatCLI — providers, modelos, memória, contextos, skills, plugins, servidores MCP — passa a dirigir o chat de IA da sua IDE.
O que a IDE renderiza nos runs de agent/coder é totalmente estruturado — não um transcript de terminal em stream:
  • Raciocínio — chega como thought chunks nativos (colapsáveis na maioria dos clientes).
  • Tool calls — cada ação é uma tool call de primeira classe com título humano (“Reading: main.go”), kind semântico (read, edit, execute, search…), status ao vivo e os arquivos tocados. Leituras bem-sucedidas mostram qual arquivo foi lido — nunca um despejo do conteúdo no chat.
  • Plano — a lista de tarefas do coder vira um painel de plano ao vivo, marcado conforme o agente progride.
  • Resposta final — prosa limpa do assistente, renderizada como markdown pela IDE.
  • Dialogs de permissão — comandos perigosos e regras ask da política pausam o run e disparam o dialog nativo da IDE com as mesmas quatro opções do prompt do terminal: permitir ou negar, uma vez ou sempre.

Início rápido

O processo fala JSON-RPC delimitado por linha em stdin/stdout. Todo logging vai para o logger de arquivo — o canal do protocolo fica limpo.

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

O AI Assistant da JetBrains hospeda agentes ACP customizados nativamente (macOS e Linux; agentes ACP não exigem assinatura de IA).
1

Abra a configuração de agente customizado

Na tool window AI Chat, abra o dropdown de agentes e escolha Add Custom Agent. A IDE cria e abre o ~/.jetbrains/acp.json.
2

Registre o ChatCLI

~/.jetbrains/acp.json
  • command precisa ser um caminho absoluto (which chatcli para descobrir).
  • env é opcional — com ele você fixa provider/modelo para a IDE independentemente das sessões do terminal; sem ele, o ChatCLI sobe com a resolução normal de .env/ambiente.
3

Selecione o ChatCLI e converse

De volta ao AI Chat, escolha ChatCLI no dropdown de agentes e mande um prompt. Agentes customizados aparecem com um ícone próprio.
use_custom_mcp / use_idea_mcp controlam quais servidores MCP a IDE oferece aos agentes. O ChatCLI traz a própria configuração de cliente MCP (~/.chatcli/mcp_servers.json) de qualquer forma — as tools que você configurou no ChatCLI continuam funcionando dentro da IDE.

Zed

Adicione o ChatCLI em agent_servers no settings.json do Zed:
Depois abra o Agent Panel e selecione ChatCLI.

Modos de sessão

Toda sessão ACP roda em um de três modos, anunciados ao cliente no session/new e trocáveis a qualquer momento: Troque de modo pelo seletor da IDE, ou simplesmente digite o comando no prompt:
Mudanças de modo são confirmadas ao cliente via current_mode_update, então o seletor da IDE sempre reflete a realidade.

Slash commands na IDE

Digite / na caixa de prompt: a IDE autocompleta a superfície de comandos do ChatCLI (anunciada via available_commands_update). O input hint de cada comando mostra seus subcomandos reais — derivados ao vivo do mesmo completer que alimenta o terminal, então nunca dessincroniza (o protocolo ACP não tem completion estruturada além do nome do comando; a linha de hint é toda a superfície disponível, e o ChatCLI a aproveita ao máximo). Três grupos: Trocas de modo/chat, /agent, /coder (e /run como alias de agent). Templates de slash commands — todo comando do catálogo de slash commands do projeto (.chatcli/commands, ~/.chatcli/commands e todos os dirs de interop — Claude Code, Devin, Windsurf, Cursor, opencode, Codex, Gemini, Qwen, Copilot) é anunciado com seu argument-hint como input hint. Invocar um expande o template e o executa no modo atual da sessão, exatamente como texto digitado. Comandos headless — executam de verdade, com o output devolvido no chat: Todo o resto — comandos que precisam de um terminal vivo (/menu, /gateway, /schedule, /auth, …) respondem com uma mensagem clara de “não disponível pela conexão da IDE” em vez de falhar em silêncio. O /session opera na sessão de quem chama, não em estado global do processo: cada sessão da IDE salva, carrega e vincula de forma independente. /session attach <nome> (ou save/load) vincula a conversa da IDE a uma sessão nomeada no store compartilhado — cada turno é gravado (write-through) e escritas de outras superfícies (REPL do terminal, gateway, clientes MCP) são adotadas antes de cada turno. Veja Continuidade cross-surface.
Um prompt que apenas começa com barra — um path como /usr/local/bin explica isso, uma palavra com typo — não é sequestrado: tokens desconhecidos fluem para o modelo como texto normal do usuário.
Comandos que pediriam confirmação num terminal (ex.: /context rm <nome>) rodam com o stdin em quarentena no servidor: qualquer confirmação é respondida como negada, fail-safe. Manutenção destrutiva é melhor feita no REPL do terminal.

Dialogs de permissão

Servidores de agente unattended historicamente enfrentam uma escolha dura: auto-aprovar tudo ou bloquear tudo. O ACP tem uma resposta melhor — session/request_permission — e o ChatCLI a usa:
  • As regras ask da sua política de segurança abrem o dialog nativo da IDE com o vocabulário completo do terminal: Allow / Always allow / Reject / Always reject. As opções always persistem uma regra no coder_policy.json — exatamente o que apertar a ou d faz no prompt do terminal — então a próxima ocorrência nem precisa de dialog.
  • Quando o coder quer executar um comando classificado como perigoso (deletes recursivos, force push, escalação de privilégio…), o dialog oferece só Allow once / Reject once: comandos exec nunca ganham um always geral, espelhando o prompt interativo que esconde essas opções para eles de propósito.
  • Qualquer coisa que não seja um Allow explícito — reject, dialog fechado, crash do cliente, timeout — nega a ação. O agente vê a recusa in-band e replaneja; um Always reject também registra uma regra deny permanente.
  • O mesmo gate cobre blocos shell propostos pelo agente no modo agent.
Um dialog que nunca recebe resposta não consegue congelar o run: a espera é limitada por CHATCLI_MCP_PERMISSION_TIMEOUT (compartilhada com o MCP server; uma duração Go como 90s/10m ou segundos puros, default 600s; 0/off eleva o limite para um teto de 24h). Ao expirar, a ação nega fail-safe, o modelo é informado de que o pedido ficou sem resposta — não que você negou — então ele continua e consegue explicar, e os próximos dialogs do mesmo run falham rápido em vez de travar de novo. Prefere zero dialogs numa sessão? /policy mode auto coloca a sessão em automode de política: regras ask auto-aprovam enquanto regras deny e operações safety-immune continuam travando. /policy mode interactive restaura os dialogs. Clientes que não implementam o pedido de permissão (respondendo method not found) continuam funcionando sem ele: comandos perigosos são recusados fail-safe, enquanto regras ask da política caem no contrato unattended histórico (auto-approve) — frontends minimalistas ou wrapeados nunca quebram. Regras deny explícitas bloqueiam em qualquer superfície.

Seus servidores MCP funcionam aqui também

O processo ACP é um boot completo do ChatCLI — incluindo o cliente MCP. Se o ~/.chatcli/mcp_servers.json existe, todos os servidores MCP configurados são conectados no startup e as tools deles entram na caixa de ferramentas do agente, exatamente como no terminal:
  • Peça ao agente algo que precise de uma tool MCP (“veja as issues abertas do Jira”, “consulte o banco de staging”) e ele chama a tool do servidor conectado autonomamente. Na IDE, a chamada renderiza como uma tool call estruturada nativa igual a qualquer built-in.
  • Hot reload — editar o mcp_servers.json reconecta servidores ao vivo; sem reiniciar IDE nem agente. /mcp na caixa de prompt mostra status de conexão e tools.
  • Servidores remotos com OAuth precisam ser autorizados antes (rode @mcp-login no terminal uma vez; os tokens persistem no keychain).
As conexões são estabelecidas de forma assíncrona no boot: um prompt enviado nos primeiríssimos segundos pode ainda não enxergar as tools de um servidor lento — elas entram no catálogo assim que a conexão completa.Uma diferença conceitual em relação ao chatcli mcp-server: o ACP não tem lista de tools voltada ao cliente, então a IDE nunca invoca tools MCP diretamente — o agente as usa por você. Invocação direta de tool (hub passthrough) é recurso do modo mcp-server.

Por baixo do capô (para integradores)

O ChatCLI implementa o ACP protocol version 1. Métodos: Kinds de session/update emitidos: agent_thought_chunk, agent_message_chunk, tool_call, tool_call_update, plan, current_mode_update, available_commands_update. Tool calls carregam kind (read/edit/delete/move/search/execute/think/fetch/other), status, rawInput, locations (paths para follow-along) e conteúdo limitado para exibição — o modelo sempre recebe o output completo; a visão do chat recebe um resumo limitado. Menções de arquivo da IDE funcionam nos dois sentidos: blocos resource_link chegam como referências que as ferramentas do agente abrem sozinhas, e blocos resource (conteúdo embutido) são injetados como contexto anexado.

Notas operacionais

  • Um run por vez — runs de agent/coder serializam no processo (compartilham o estado do engine). O prompt de uma segunda sessão espera o run atual terminar; um segundo prompt na mesma sessão é rejeitado enquanto há um em voo — e uma sessão enfileirada que você cancela desiste do lugar imediatamente, em vez de ficar presa atrás do run ativo.
  • Parks e monitores ficam no turno — quando o modelo usa @park (ex.: “verifique o gate do PR a cada 30s”), o turno fica aberto e cada ciclo de monitoração streama na IDE na mesma request; apertar Stop cancela o monitor por completo (job do scheduler + snapshot). Esperas síncronas do @scheduler emitem uma linha de heartbeat ⏳ a cada 30s. Veja Agent park & resume.
  • Dialogs de permissão são limitados e honestos — cada session/request_permission espera até CHATCLI_MCP_PERMISSION_TIMEOUT (padrão 600s; off = teto de 24h). Um timeout ou uma falha no round-trip do dialog bloqueia a ação fail-safe, mas é reportado ao modelo como sem resposta/falhou, nunca como negação do usuário.
  • Ambiente — o processo ACP é um boot normal do ChatCLI: arquivo de ambiente, logins OAuth no keychain, catálogos de provider, config de cliente MCP e skills resolvem como no terminal. Uma ressalva importante: a IDE não executa o seu shell profile, então CHATCLI_DOTENV e qualquer export do .zshrc/.bashrc não chegam no processo do agente, e o diretório de trabalho dele é o projeto. Por isso o ChatCLI cai para ~/.chatcli/.env e depois ~/.env quando não há ./.env — mantenha seu arquivo em um desses e a IDE concorda com o terminal. O que a IDE precisar fixar explicitamente vai no bloco env. O /config na caixa de prompt mostra o arquivo em efeito, a origem dele e o profile AWS efetivo.
  • Configuração por projeto — o projeto aberto na IDE (o cwd do session/new) contribui com o .env dele por cima, somente preenchendo: pode adicionar variáveis que você não definiu, nunca sobrescreve uma já em efeito, e só o primeiro projeto anunciado se aplica. Diretório de projeto é entrada não confiável, então CHATCLI_PROJECT_ENV=safe (padrão) recusa variáveis de credencial e endpoint vindas dele; all aceita tudo e off desliga.
  • Sessões são por sessão e restauráveis — cada sessão da IDE mantém seu próprio histórico de conversa. session/load (capability loadSession: true) traz de volta um session id anterior: o estado vivo se o servidor ainda está rodando, ou o espelho de autosave mcp-<id> após um restart, com a conversa replayada na IDE. Para continuidade durável entre superfícies, vincule a uma sessão nomeada com /session attach <nome> — veja Continuidade cross-surface.
  • Logs — stdout é o protocolo; diagnóstico vai para o arquivo de log padrão do ChatCLI. Coloque LOG_LEVEL=debug no bloco env do agente ao investigar.

Troubleshooting

Veja também