🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Opencode Acp Control

by @bjesuiter

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

Versionv1.0.2
Downloads4,790
Installs27
Stars⭐ 9
TERMINAL
clawhub install opencode-acp-control

πŸ“– About This Skill


name: opencode-acp-control description: Control OpenCode directly via the Agent Client Protocol (ACP). Start sessions, send prompts, resume conversations, and manage OpenCode updates. metadata: {"version": "1.0.2", "author": "Benjamin Jesuiter ", "license": "MIT", "github_url": "https://github.com/bjesuiter/opencode-acp-skill"}

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: "\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