v1.0.2

Opencode Acp Control

bjesuiter bjesuiter ← All skills

Control OpenCode directly via the Agent Client Protocol (ACP). Start sessions, send prompts, resume conversations, and manage OpenCode updates.

Downloads
1.6k
Stars
4
Versions
3
Updated
2026-02-24

Install

npx clawhub@latest install opencode-acp-control

Documentation

OpenCode ACP Skill

Control OpenCode directly via the Agent Client Protocol (ACP).

Metadata

  • -For ACP Protocol Docs (for Agents/LLMs): https://agentclientprotocol.com/llms.txt
  • -GitHub Repo: https://github.com/bjesuiter/opencode-acp-skill
  • -If you have issues with this skill, please open an issue ticket here: https://github.com/bjesuiter/opencode-acp-skill/issues

Quick Reference

| Action | How |

|--------|-----|

| Start OpenCode | bash(command: "opencode acp", background: true) |

| Send message | process.write(sessionId, data: "<json-rpc>\n") |

| Read response | process.poll(sessionId) - repeat every 2 seconds |

| Stop OpenCode | process.kill(sessionId) |

| List sessions | bash(command: "opencode session list", workdir: "...") |

| Resume session | List sessions → ask user → session/load |

| Check version | bash(command: "opencode --version") |

Starting OpenCode

bash(

command: "opencode acp",

background: true,

workdir: "/path/to/your/project"

)

Save the returned sessionId - you'll need it for all subsequent commands.

Protocol Basics

  • -All messages are JSON-RPC 2.0 format
  • -Messages are newline-delimited (end each with \n)
  • -Maintain a message ID counter starting at 0

Step-by-Step Workflow

Step 1: Initialize Connection

Send immediately after starting OpenCode:

{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{"fs":{"readTextFile":true,"writeTextFile":true},"terminal":true},"clientInfo":{"name":"clawdbot","title":"Clawdbot","version":"1.0.0"}}}

Poll for response. Expect result.protocolVersion: 1.

Step 2: Create Session

{"jsonrpc":"2.0","id":1,"method":"session/new","params":{"cwd":"/path/to/project","mcpServers":[]}}

Poll for response. Save result.sessionId (e.g., "sess_abc123").

Step 3: Send Prompts

{"jsonrpc":"2.0","id":2,"method":"session/prompt","params":{"sessionId":"sess_abc123","prompt":[{"type":"text","text":"Your question here"}]}}

Poll every 2 seconds. You'll receive:

  • -session/update notifications (streaming content)
  • -Final response with result.stopReason

Step 4: Read Responses

Each poll may return multiple lines. Parse each line as JSON:

  • -Notifications: method: "session/update" - collect these for the response
  • -Response: Has id matching your request - stop polling when stopReason appears

Step 5: Cancel (if needed)

{"jsonrpc":"2.0","method":"session/cancel","params":{"sessionId":"sess_abc123"}}

No response expected - this is a notification.

State to Track

Per OpenCode instance, track:

  • -processSessionId - from bash tool (clawdbot's process ID)
  • -opencodeSessionId - from session/new response (OpenCode's session ID)
  • -messageId - increment for each request you send

Polling Strategy

  • -Poll every 2 seconds
  • -Continue until you receive a response with stopReason
  • -Max wait: 5 minutes (150 polls)
  • -If no response, consider the operation timed out

Common Stop Reasons

| stopReason | Meaning |

|------------|---------|

| end_turn | Agent finished responding |

| cancelled | You cancelled the prompt |

| max_tokens | Token limit reached |

Error Handling

| Issue | Solution |

|-------|----------|

| Empty poll response | Keep polling - agent is thinking |

| Parse error | Skip malformed line, continue |

| Process exited | Restart OpenCode |

| No response after 5min | Kill process, start fresh |

Example: Complete Interaction

1. bash(command: "opencode acp", background: true, workdir: "/home/user/myproject")

-> processSessionId: "bg_42"

2. process.write(sessionId: "bg_42", data: '{"jsonrpc":"2.0","id":0,"method":"initialize",...}\n')

process.poll(sessionId: "bg_42") -> initialize response

3. process.write(sessionId: "bg_42", data: '{"jsonrpc":"2.0","id":1,"method":"session/new","params":{"cwd":"/home/user/myproject","mcpServers":[]}}\n')

process.poll(sessionId: "bg_42") -> opencodeSessionId: "sess_xyz789"

4. process.write(sessionId: "bg_42", data: '{"jsonrpc":"2.0","id":2,"method":"session/prompt","params":{"sessionId":"sess_xyz789","prompt":[{"type":"text","text":"List all TypeScript files"}]}}\n')

5. process.poll(sessionId: "bg_42") every 2 sec until stopReason

-> Collect all session/update content

-> Final response: stopReason: "end_turn"

6. When done: process.kill(sessionId: "bg_42")

---

Resume Session

Resume a previous OpenCode session by letting the user choose from available sessions.

Step 1: List Available Sessions

bash(command: "opencode session list", workdir: "/path/to/project")

Example output:

ID                                  Updated              Messages

ses_451cd8ae0ffegNQsh59nuM3VVy 2026-01-11 15:30 12

ses_451a89e63ffea2TQIpnDGtJBkS 2026-01-10 09:15 5

ses_4518e90d0ffeJIpOFI3t3Jd23Q 2026-01-09 14:22 8

Step 2: Ask User to Choose

Present the list to the user and ask which session to resume:

"Which session would you like to resume?

1. ses_451cd8ae... (12 messages, updated 2026-01-11)

2. ses_451a89e6... (5 messages, updated 2026-01-10)

3. ses_4518e90d... (8 messages, updated 2026-01-09)

Enter session number or ID:"

Step 3: Load Selected Session

Once user responds (e.g., "1", "the first one", or "ses_451cd8ae..."):

1. Start OpenCode ACP:

   bash(command: "opencode acp", background: true, workdir: "/path/to/project")

2. Initialize:

   {"jsonrpc":"2.0","id":0,"method":"initialize","params":{...}}

3. Load the session:

   {"jsonrpc":"2.0","id":1,"method":"session/load","params":{"sessionId":"ses_451cd8ae0ffegNQsh59nuM3VVy","cwd":"/path/to/project","mcpServers":[]}}

Note: session/load requires cwd and mcpServers parameters.

On load, OpenCode streams the full conversation history back to you.

Resume Workflow Summary

function resumeSession(workdir):

# List available sessions

output = bash("opencode session list", workdir: workdir)

sessions = parseSessionList(output)

if sessions.empty:

notify("No previous sessions found. Starting fresh.")

return createNewSession(workdir)

# Ask user to choose

choice = askUser("Which session to resume?", sessions)

selectedId = matchUserChoice(choice, sessions)

# Start OpenCode and load session

process = bash("opencode acp", background: true, workdir: workdir)

initialize(process)

session_load(process, selectedId, workdir, mcpServers: [])

notify("Session resumed. Conversation history loaded.")

return process

Important Notes

  • -History replay: On load, all previous messages stream back
  • -Memory preserved: Agent remembers the full conversation
  • -Process independent: Sessions survive OpenCode restarts

---

Updating OpenCode

OpenCode auto-updates when restarted. Use this workflow to check and trigger updates.

Step 1: Check Current Version

bash(command: "opencode --version")

Returns something like: opencode version 1.1.13

Extract the version number (e.g., 1.1.13).

Step 2: Check Latest Version

webfetch(url: "https://github.com/anomalyco/opencode/releases/latest", format: "text")

The redirect URL contains the latest version tag:

  • -Redirects to: https://github.com/anomalyco/opencode/releases/tag/v1.2.0
  • -Extract version from the URL path (e.g., 1.2.0)

Step 3: Compare and Update

If latest version > current version:

1. Stop all running OpenCode processes:

   process.list()  # Find all "opencode acp" processes

process.kill(sessionId) # For each running instance

2. Restart instances (OpenCode auto-downloads new binary on start):

   bash(command: "opencode acp", background: true, workdir: "/path/to/project")

3. Re-initialize each instance (initialize + session/load for existing sessions)

Step 4: Verify Update

bash(command: "opencode --version")

If version still doesn't match latest:

  • -Inform user: "OpenCode auto-update may have failed. Current: X.X.X, Latest: Y.Y.Y"
  • -Suggest manual update: curl -fsSL https://opencode.dev/install | bash

Update Workflow Summary

function updateOpenCode():

current = bash("opencode --version") # e.g., "1.1.13"

latestPage = webfetch("https://github.com/anomalyco/opencode/releases/latest")

latest = extractVersionFromRedirectUrl(latestPage) # e.g., "1.2.0"

if semverCompare(latest, current) > 0:

# Stop all instances

for process in process.list():

if process.command.includes("opencode"):

process.kill(process.sessionId)

# Wait briefly for processes to terminate

sleep(2 seconds)

# Restart triggers auto-update

bash("opencode acp", background: true)

# Verify

newVersion = bash("opencode --version")

if newVersion != latest:

notify("Auto-update may have failed. Manual update recommended.")

else:

notify("OpenCode is up to date: " + current)

Important Notes

  • -Sessions persist: opencodeSessionId survives restarts — use session/load to recover
  • -Auto-update: OpenCode downloads new binary automatically on restart
  • -No data loss: Conversation history is preserved server-side

Launch an agent with Opencode Acp Control on Termo.