opencode-acp-control
Control OpenCode directly via the Agent Client Protocol (ACP). Start sessions, send prompts, resume conversations, and manage OpenCode updates.
Best use case
opencode-acp-control is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Control OpenCode directly via the Agent Client Protocol (ACP). Start sessions, send prompts, resume conversations, and manage OpenCode updates.
Teams using opencode-acp-control should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/opencode-acp-control-3/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How opencode-acp-control Compares
| Feature / Agent | opencode-acp-control | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Control OpenCode directly via the Agent Client Protocol (ACP). Start sessions, send prompts, resume conversations, and manage OpenCode updates.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
ChatGPT vs Claude for Agent Skills
Compare ChatGPT and Claude for AI agent skills across coding, writing, research, and reusable workflow execution.
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
SKILL.md Source
# 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/berriosb/Opencode-Acp-Control
- If you have issues with this skill, please open an issue ticket here: https://github.com/berriosb/Opencode-Acp-Control/issues
## Quick Reference
| Action | How |
|--------|-----|
| Start OpenCode | `bash(command: "opencode acp --cwd /path/to/project", 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 --cwd /path/to/your/project",
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:
```json
{"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
```json
{"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
```json
{"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)
```json
{"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 --cwd /home/user/myproject", 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 --cwd /path/to/project", background: true, workdir: "/path/to/project")
```
2. **Initialize**:
```json
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{...}}
```
3. **Load the session**:
```json
{"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 --cwd " + workdir, 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 --cwd /path/to/project", 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-sideRelated Skills
Pest Control Operations Agent
You are an expert pest control business operations advisor. Help operators with licensing, EPA/FIFRA compliance, pricing, route optimization, seasonal planning, technician management, and growth strategy.
Export Compliance & Trade Controls
Analyze products, destinations, and end-users against US export control regulations (EAR, ITAR, OFAC sanctions). Generate classification recommendations, license requirements, and compliance checklists.
ecovacs-robot-control
Control Ecovacs/DEEBOT robot vacuums via the Ecovacs IoT API. Use when the user wants to control a robot vacuum, check battery, start/stop/pause cleaning, return to dock, check clean status, set suction/water level, manage schedules, check consumables, or control auto-empty station. Covers all mainstream Ecovacs protocols including clean_V2, charge, getBattery, getCleanInfo_V2, getStats, getSpeed/setSpeed, getWaterInfo/setWaterInfo, getWorkMode/setWorkMode, getLifeSpan, getAutoEmpty/setAutoEmpty, getCachedMapInfo, getMapSet, getSched_V2/setSched_V2.
clawphone-wechat-control
处理微信会话列表、进入聊天、发送消息、处理微信内弹窗与聊天页失败排查。适用于用户要求查看微信消息、回复联系人、转发、处理聊天输入框或发送失败时。执行时必须先确认当前在微信的哪个页面,再按聊天场景一步一验。
clawphone-phone-control
使用手机控制 MCP 完成手机界面感知与操作。适用于读取当前手机状态、打开 App、处理弹窗、点击控件、输入文本、排查手机自动化失败等场景。执行时优先读取界面状态,涉及坐标点击时必须基于当前截图临时判定,禁止把历史坐标当成通用规则。
ralph-opencode-free-loop
Run an autonomous Open Ralph Wiggum coding loop using OpenCode Zen with free models and automatic fallback.
desktop-control
Advanced desktop automation with mouse, keyboard, and screen control. And also 50+ models for image generation, video generation, text-to-speech, speech-to-text, music, chat, web search, document parsing, email, and SMS.
controld
Manage Control D DNS filtering service via API. Use for DNS profile management, device configuration, custom blocking rules, service filtering, analytics settings, and network diagnostics. Triggers when user mentions Control D, DNS filtering, DNS blocking, device DNS setup, or managing DNS profiles.
control-ikea-lightbulb
Control IKEA/TP-Link Kasa smart bulbs (set on/off, brightness, and color). Use when you want to programmatically control a local smart bulb by IP on the LAN.
intiface-control
Control 750+ BLE intimate devices (Lovense, Kiiroo, We-Vibe, Satisfyer, etc.) from natural language via Intiface Central and buttplug-mcp. Works on macOS, Windows, and Linux. No protocol reverse-engineering required.
Robotic Control Skill (OpenClaw)
## Overview
agent-control
Manage OpenClaw isolated agents from chat with short commands. Use when the user asks to create/list/switch/bind/delete agents, route channels to a specific agent, or set an agent identity without manually typing full CLI syntax.