Repository navigation
Description
Problem
OpenClaw's only coding-harness protocol is ACP, and opencode acp starts a private OpenCode server per process by design (OpenCode v2 docs: "starts a private OpenCode server for its own use. It doesn't connect to the shared background service"). Meanwhile every other OpenCode client (TUI opencode attach, opencode run --attach, JS SDK createOpencodeClient({ baseUrl }), desktop, web, OpenChamber via OPENCODE_HOST + OPENCODE_SKIP_START=true) can drive one shared opencode serve. Result on the laptop today: OpenChamber's managed serve + a background serve --service + per-session ACP processes, each spawning its own llama.cpp embedding child — duplicate processes, split session state, and per-turn cold boots against the shared SQLite DB (a third-party integrator measured 0/24 success under 8-concurrent load cold-booting vs 6/6 through one shared server).
Research (2026-10-26): ~/workspace/research_notes/openclaw-opencode-single-server-research-20261027-0359/report.md — no fork of OpenClaw or OpenCode is needed; no existing ClawHub plugin bridges ACP to the serve HTTP API.
Design: a small ACP↔HTTP adapter
A single-purpose shim executable that speaks ACP (JSON-RPC over stdio) on one side and the OpenCode serve HTTP API on the other, registered in OpenClaw exactly where opencode acp sits today:
plugins.entries.acpx.config.agents.opencode = {
command = "<adapter>";
args = [ "--server" "http://127.0.0.1:4096" ];
};Mapping:
- ACP
session/new→POST /session(cwd → directory scoping) - ACP
session/prompt→POST /session/:id/message(orprompt_async+GET /eventSSE for streaming updates back as ACP session/update notifications) - serve permission events → ACP
session/request_permission→ reply viaPOST /session/:id/permissions/:permissionID - ACP
session/cancel→POST /session/:id/abort - Auth:
OPENCODE_SERVER_PASSWORDbasic auth, sourced from sops like the other OpenClaw secrets.
Companion changes:
- Run ONE
opencode serveas a user service on a fixed port (4096, loopback; password via sops) started before front-ends. - OpenChamber pointed at it (
OPENCODE_HOST,OPENCODE_SKIP_START=true) so it stops spawning its own managed server. - Retire the stale background
serve --serviceinstance once the shared server is canonical.
Acceptance
-
/acp spawn opencodein OpenClaw creates a session on the shared server (visible viaGET /sessionand in OpenChamber/TUI attached to the same server). - A prompt round-trip through OpenClaw streams output and completes; permission requests surface in OpenClaw and resolve via the permissions endpoint.
- Only one
opencode serveprocess (and one embedding child) on the laptop during an OpenClaw coding session. - Adapter lives in this repo, is covered by the OpenClaw Nix config, and the interim
opencode acpoverride remains a one-line fallback.
Notes
- Interim state (already live): ACP per-session processes; keep sessions non-persistent by default.
- Related adoptables from the same research pass, tracked separately: memory-lancedb in
plugins.slots.memory(verify the official npm package name first — two candidates claim it), OmOC-style persona/tool-restriction shapes remapped to fleet quota pools (do NOT adopt its flagship-model category defaults).
Acceptance criteria
- The adapter executable speaks ACP (JSON-RPC over stdio) on one side and the OpenCode serve HTTP API on the other, and registers in OpenClaw exactly where
opencode acpsits today (agents.opencode command/args). - Session mapping works end-to-end against one shared
opencode serve: session/new → POST /session (cwd → directory), session/prompt → message POST with streaming updates returned as ACP session/update notifications, and serve permission events round-trip through ACP session/request_permission. - An OpenClaw coding session run through the adapter appears in the shared server's session list (visible to OpenChamber/TUI attach) — no private per-process server is spawned.
- Duplicate llama.cpp embedding children from per-session ACP processes are eliminated for adapter-routed sessions (process count check before/after).
Activity
developing-today commentedon Oct 27, 2026
CODE-371
dezren39 commentedon Oct 27, 2026
Intake review
Related: Research:
~/workspace/research_notes/openclaw-opencode-single-server-research-20261027-0359/report.md(no fork of either project needed). Sibling pilot world: #1190 (OpenClaw comment loop), #1185 (babysitter v1).Notes: Well-evidenced problem: every other OpenCode client can share one
opencode serve; OpenClaw's ACP path cannot, and the cost is measured (duplicate embedding children, split session state, 0/24 cold-boot concurrency vs 6/6 shared). The body's mapping table is most of a spec.Risks: Streaming semantics are the hard part —
prompt_async+ SSE event translation must not drop or reorder session/update notifications, and permission replies are on the critical path (a hung permission event hangs the session). Version drift between the ACP dialect OpenClaw expects and the adapter's implementation will be a maintenance tail.Suggested approach: Spike the three mappings (new/prompt/permission) against a local serve first with a scripted ACP client, then wire OpenClaw to it on the laptop for one real session before calling it done.
dezren39 commentedon Oct 27, 2026
T3 Code recon (2026-10-27): attach is built-in config, no code changes
T3 Code 0.1.2 is already installed on amd (Nix-packaged from this repo, running as the
t3codeuser service, fleet-integrated 2026-10-26 — seedoc/2026-10-26T21-18-21Z_feature_t3code-v2-integration/main.md). Today it spawns its OWNopencode serveon an ephemeral port (37249 at recon time), separate from OpenChamber's managed serve (37621) — the side-by-side duplication to eliminate.Attach mechanism exists in 0.1.2: the OpenCode provider instance config schema is
binaryPath,serverUrl,serverPassword(+ model). The settings UI says of serverUrl: "Leave blank to let T3 Code spawn the server when needed." Setting it switches T3 to the external server (corroborated by upstream pingdotgg/t3code#15155). Version requirement (OpenCode >= 2.0.18) is satisfied by the fleet fork 2.0.30+56590c5.Implementation path (no T3 fork):
opencode serveon a FIXED loopback port with a password (this issue's main task).pkgs/t3code-seed-providers/seed.sh's fleet-owned refresh for theopencode-v2instance to set/refreshconfig.serverUrl(+config.serverPassword) — same pattern as its existing binaryPath refresh. settings.json stays writable (T3 writes it at runtime).userdata/secrets/store — check for a reference mechanism before putting any credential in plain settings.json.Coordination note: another workstream was mid-
nixos-rebuild switchfrom~/code-t3wtduring recon, and the T3 feature doc records a previous same-day flip-flop from concurrent activations. Sequence any T3-affecting activation accordingly.dezren39 commentedon Nov 1, 2026
🤖 Agent note · picked up
10 remaining items
dezren39 commentedon Nov 1, 2026
🤖 Agent note · picked up
opencode acpas fallback). PR Wire OpenClaw ACP adapters to Nix runtime plugin #3275 (Nix-package the Claude/Codex ACP adapters — repoint OpenClaw acpx off tmp/plugin-captures #1711) is open on an adjacent concern in the same Nix file — not touching it; will coordinate on the shared file only.dezren39 commentedon Nov 1, 2026
🤖 Agent note · done
opencode acpkept as a documented one-line fallback. Adapter tests: 5/5 pass against a stub serve API (node --test on the laptop); Nix parse OK.Merge pull request #3997 from developing-today/queue/4972-1243-acp-ht…