acp-bridgein Production, Not Demos

Turn any local LLM (Ollama, llama.cpp, OpenAI-compatible) into an Agent Client Protocol-compatible agent. Spawn it from Zed, JetBrains, ACP UI, Meuxe, or Codex CLI — your data stays on your machine.

How it fits

You write code in your editor. Your editor spawns acp-bridge as a subprocess and talks to it through JSON-RPC over stdin/stdout. acp-bridge talks to your local LLM (Ollama, llama.cpp, vLLM, LM Studio — anything OpenAI-compatible) over its native HTTP API. Tool calls stay on your box.

┌──────────────────┐ JSON-RPC / stdio ┌──────────────┐ HTTP ┌─────────────┐ │ Editor │ ─────────────────────▶ │ acp-bridge │ ───────▶ │ Local LLM │ │ (Zed, Meuxe, │ ◀───────────────────── │ (Rust) │ ◀─────── │ (Ollama, │ │ ACP UI, …) │ session/update │ │ │ llama.cpp) │ └──────────────────┘ └──────┬───────┘ └─────────────┘ │ tool calls │ (sandboxed) ▼ ┌──────────────┐ │ Working dir │ └──────────────┘

Compatible Clients

acp-bridge negotiates the protocol version with each Client at init time. The table below shows which Client speaks which version today and what you can expect.

ClientACP versionacp-bridge wireTested
Zedv1v1✓ via zed_style.rs e2e
JetBrains IDEsv1v1✓ mirrors Zed shape
ACP UIv1v1✓ via inspector_style.rs e2e
ACP Inspectorv1v1✓ via inspector_style.rs e2e
Meuxev1v1✓ — issue #13 fixed
Codex CLI adapterv1 (minimal)v1✓ via minimal_style.rs e2e
Claude Code (Claude Agent SDK)v1v1interop verified manually
OpenCodev2 (preview)v1 (negotiated)will negotiate v2 once OpenCode ships v2

Protocol support

acp-bridge implements ACP v1 fully and ACP v2 on the same code base. The negotiation is automatic: at init the Client sends its preferred protocolVersion, acp-bridge picks the highest version both sides support, and every subsequent notification uses the corresponding wire shape.

What v2 changes

Conceptv1 wirev2 wire
initialize responseagentInfo + agentCapabilitiesUnified info + capabilities
image capabilitytrue / false{} (marker) or omit
Tool start notificationtool_call with toolCallId + kind + status: "in_progress"tool_call_update with the same fields (legacy tool_call not emitted)
Plan{sessionUpdate: "plan", entries[]}{sessionUpdate: "plan_update", plan: {type: "items", planId, entries[]}}
End-of-turn(none)state_update with stopReason

Latest release

v0.9.2
2026-10-06
Thinking-model tool-call recovery
Reasoning models (DeepSeek-R1, Qwen 2.5/3, GLM) sometimes emit tool-call JSON inside the content channel instead of the structured tool_calls field — the agent stalled on such rounds. acp-bridge now strips think-tag scaffolding and recovers embedded tool-call JSON (fenced or bare) into the normal tool dispatch. 185 tests passing.
v0.9.1
2026-10-03
v2 wire-shape blockers + sandbox hardening
Three v2 schema violations caught by code review of the 0.9.0 release, plus five pre-existing bugs and a stale-docs sweep. acp-bridge now also implements v2 baseline session/close and session/list, Ollama native tool.arguments object handling, and web_fetch redirect re-validation. 171 tests passing.
v0.9.0
2026-10-02
ACP v1 / v2 dual wire format
Negotiate protocolVersion at init; emit v1 or v2 wire shape accordingly. Same code base, dispatch by version.

Three Things To Know

⌘

ACP v1 + v2, same code base

One binary. Negotiation at init picks the right wire shape per Client. Today that means Zed / JetBrains / ACP UI / Meuxe / Codex CLI on v1, future v2-only Clients on v2.

⌬

11 built-in tools

read_file, list_dir, search_code, write_file, edit, web_fetch (opt-in), bash, git_status / git_diff / git_log / git_commit. Sandboxed to the session working dir.

⏚

Air-gap clean, audit-friendly

Single 5 MB static Rust binary. No npm. No models.dev fetches. No LSP. Outbound only to the configured LLM endpoint, opt-in via LLM_WEB_ALLOWLIST.