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 | INLINECODE0 |
| 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
CODEBLOCK0
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:
CODEBLOCK1
Poll for response. Expect result.protocolVersion: 1.
Step 2: Create Session
CODEBLOCK2
Poll for response. Save result.sessionId (e.g., "sess_abc123").
Step 3: Send Prompts
CODEBLOCK3
Poll every 2 seconds. You'll receive:
- -
session/update notifications (streaming content) - Final response with INLINECODE13
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)
CODEBLOCK4
No response expected - this is a notification.
State to Track
Per OpenCode instance, track:
- -
processSessionId - from bash tool (clawdbot's process ID) - INLINECODE18 - from session/new response (OpenCode's session ID)
- INLINECODE19 - increment for each request you send
Polling Strategy
- - Poll every 2 seconds
- Continue until you receive a response with INLINECODE20
- Max wait: 5 minutes (150 polls)
- If no response, consider the operation timed out
Common Stop Reasons
| stopReason | Meaning |
|---|
| INLINECODE21 | Agent finished responding |
| INLINECODE22 |
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
CODEBLOCK5
Resume Session
Resume a previous OpenCode session by letting the user choose from available sessions.
Step 1: List Available Sessions
CODEBLOCK6
Example output:
CODEBLOCK7
Step 2: Ask User to Choose
Present the list to the user and ask which session to resume:
CODEBLOCK8
Step 3: Load Selected Session
Once user responds (e.g., "1", "the first one", or "ses_451cd8ae..."):
- 1. Start OpenCode ACP:
CODEBLOCK9
- 2. Initialize:
CODEBLOCK10
- 3. Load the session:
CODEBLOCK11
Note: session/load requires cwd and mcpServers parameters.
On load, OpenCode streams the full conversation history back to you.
Resume Workflow Summary
CODEBLOCK12
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
CODEBLOCK13
Returns something like: INLINECODE27
Extract the version number (e.g., 1.1.13).
Step 2: Check Latest Version
CODEBLOCK14
The redirect URL contains the latest version tag:
- - Redirects to: INLINECODE29
- 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:
CODEBLOCK15
- 2. Restart instances (OpenCode auto-downloads new binary on start):
CODEBLOCK16
- 3. Re-initialize each instance (initialize + session/load for existing sessions)
Step 4: Verify Update
CODEBLOCK17
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: INLINECODE31
Update Workflow Summary
CODEBLOCK18
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
OpenCode ACP 技能
通过代理客户端协议(ACP)直接控制 OpenCode。
元数据
- - ACP 协议文档(供代理/LLM 使用):https://agentclientprotocol.com/llms.txt
- GitHub 仓库:https://github.com/bjesuiter/opencode-acp-skill
- 如果此技能出现问题,请在此处提交问题:https://github.com/bjesuiter/opencode-acp-skill/issues
快速参考
| 操作 | 方法 |
|---|
| 启动 OpenCode | bash(command: opencode acp, background: true) |
| 发送消息 |
process.write(sessionId, data:
\n) |
| 读取响应 | process.poll(sessionId) - 每 2 秒重复一次 |
| 停止 OpenCode | process.kill(sessionId) |
| 列出会话 | bash(command: opencode session list, workdir: ...) |
| 恢复会话 | 列出会话 → 询问用户 → session/load |
| 检查版本 | bash(command: opencode --version) |
启动 OpenCode
bash(
command: opencode acp,
background: true,
workdir: /path/to/your/project
)
保存返回的 sessionId - 后续所有命令都需要它。
协议基础
- - 所有消息均为 JSON-RPC 2.0 格式
- 消息以 换行符分隔(每条以 \n 结尾)
- 维护一个从 0 开始的 消息 ID 计数器
分步工作流程
步骤 1:初始化连接
启动 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}}}
轮询响应。期望 result.protocolVersion: 1。
步骤 2:创建会话
json
{jsonrpc:2.0,id:1,method:session/new,params:{cwd:/path/to/project,mcpServers:[]}}
轮询响应。保存 result.sessionId(例如 sess_abc123)。
步骤 3:发送提示
json
{jsonrpc:2.0,id:2,method:session/prompt,params:{sessionId:sess_abc123,prompt:[{type:text,text:您的问题在这里}]}}
每 2 秒轮询一次。您将收到:
- - session/update 通知(流式内容)
- 包含 result.stopReason 的最终响应
步骤 4:读取响应
每次轮询可能返回多行。将每行解析为 JSON:
- - 通知:method: session/update - 收集这些作为响应内容
- 响应:具有与您的请求匹配的 id - 当出现 stopReason 时停止轮询
步骤 5:取消(如果需要)
json
{jsonrpc:2.0,method:session/cancel,params:{sessionId:sess_abc123}}
无需等待响应 - 这是一个通知。
需要跟踪的状态
每个 OpenCode 实例,跟踪:
- - processSessionId - 来自 bash 工具(clawdbot 的进程 ID)
- opencodeSessionId - 来自 session/new 响应(OpenCode 的会话 ID)
- messageId - 每次发送请求时递增
轮询策略
- - 每 2 秒 轮询一次
- 持续直到收到包含 stopReason 的响应
- 最长等待:5 分钟(150 次轮询)
- 如果没有响应,视为操作超时
常见停止原因
| stopReason | 含义 |
|---|
| end_turn | 代理完成响应 |
| cancelled |
您取消了提示 |
| max_tokens | 达到令牌限制 |
错误处理
| 问题 | 解决方案 |
|---|
| 空轮询响应 | 继续轮询 - 代理正在思考 |
| 解析错误 |
跳过格式错误的行,继续 |
| 进程退出 | 重新启动 OpenCode |
| 5 分钟后无响应 | 终止进程,重新开始 |
示例:完整交互
- 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) -> 初始化响应
- 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: bg42) -> opencodeSessionId: sessxyz789
- 4. process.write(sessionId: bg42, data: {jsonrpc:2.0,id:2,method:session/prompt,params:{sessionId:sessxyz789,prompt:[{type:text,text:列出所有 TypeScript 文件}]}}\n)
- 5. process.poll(sessionId: bg_42) 每 2 秒直到 stopReason
-> 收集所有 session/update 内容
-> 最终响应:stopReason: end_turn
- 6. 完成后:process.kill(sessionId: bg_42)
恢复会话
通过让用户从可用会话中选择来恢复之前的 OpenCode 会话。
步骤 1:列出可用会话
bash(command: opencode session list, workdir: /path/to/project)
示例输出:
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
步骤 2:询问用户选择
向用户展示列表并询问要恢复哪个会话:
您想恢复哪个会话?
- 1. ses451cd8ae...(12 条消息,更新于 2026-01-11)
- ses451a89e6...(5 条消息,更新于 2026-01-10)
- ses_4518e90d...(8 条消息,更新于 2026-01-09)
输入会话编号或 ID:
步骤 3:加载所选会话
用户响应后(例如 1、第一个 或 ses_451cd8ae...):
- 1. 启动 OpenCode ACP:
bash(command: opencode acp, background: true, workdir: /path/to/project)
- 2. 初始化:
json
{jsonrpc:2.0,id:0,method:initialize,params:{...}}
- 3. 加载会话:
json
{jsonrpc:2.0,id:1,method:session/load,params:{sessionId:ses_451cd8ae0ffegNQsh59nuM3VVy,cwd:/path/to/project,mcpServers:[]}}
注意:session/load 需要 cwd 和 mcpServers 参数。
加载时,OpenCode 会将完整的对话历史流式传输回给您。
恢复工作流程总结
function resumeSession(workdir):
# 列出可用会话
output = bash(opencode session list, workdir: workdir)
sessions = parseSessionList(output)
if sessions.empty:
notify(未找到之前的会话。重新开始。)
return createNewSession(workdir)
# 询问用户选择
choice = askUser(要恢复哪个会话?, sessions)
selectedId = matchUserChoice(choice, sessions)
# 启动 OpenCode 并加载会话
process = bash(opencode acp, background: true, workdir: workdir)
initialize(process)
session_load(process, selectedId, workdir, mcpServers