Skip to main content
Glama
Claude Code × OpenCode

Claude Code × OpenCode

by AXLdev123
README.md
<p align="center">
  <img src="assets/banner.svg" alt="Claude Code × OpenCode" width="100%">
</p>

<p align="center">
  <a href="https://github.com/AXLdev123/claude-code-x-opencode/actions/workflows/ci.yml"><img src="https://github.com/AXLdev123/claude-code-x-opencode/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-d97757" alt="MIT license"></a>
  <img src="https://img.shields.io/badge/node-%E2%89%A5%2020-3c873a" alt="Node 20+">
  <img src="https://img.shields.io/badge/MCP-stdio-1c1a17" alt="MCP stdio">
  <img src="https://img.shields.io/badge/OpenCode-API%20v2-f4efe8?labelColor=1c1a17" alt="OpenCode API v2">
</p>

---

**Claude Code × OpenCode** is an [MCP](https://modelcontextprotocol.io) server that gives Claude Code one more sub-agent: [OpenCode](https://opencode.ai). Claude writes a brief, picks the model, the agent and the skills, lets OpenCode work in your project, then gets back its answer, the list of files it changed and what it cost.

It is useful for three things:

- **Using any model from inside Claude Code.** Every provider connected to OpenCode (OpenRouter, Kilo, OpenCode Zen, Anthropic, OpenAI…), with their reasoning variants, including free models for bulk work.
- **Running work in parallel.** Up to 12 OpenCode sessions at once, each with its own model, agent and permissions.
- **Staying in control.** Permission requests and questions from the agent come back to Claude, which can answer them, interrupt the agent, revert its changes or fork the session.

```text
You      › Migrate the 40 components in src/legacy to the new API, in parallel,
           with a free model, then check the result.

Claude   › oc_delegate_parallel  4 batches × opencode/deepseek-v4.1-flash-free
           ✓ batch 1 · 10 files · $0     ✓ batch 2 · 10 files · $0
           ✓ batch 3 · 10 files · $0     ✓ batch 4 · 10 files · $0
           oc_session diff → review → npm test ✓
```

## Contents

- [Features](#features)
- [How it works](#how-it-works)
- [Installation](#installation)
- [Getting started](#getting-started)
- [Tool reference](#tool-reference)
- [Choosing a model](#choosing-a-model)
- [Permissions](#permissions)
- [Long tasks and blocked sessions](#long-tasks-and-blocked-sessions)
- [Configuration](#configuration)
- [Recipes](#recipes)
- [Troubleshooting](#troubleshooting)
- [Development](#development)
- [Known limitations](#known-limitations)

## Features

| | |
|---|---|
| **Full delegation** | New session or continue an existing one, fork, free-form brief or slash command, attached files. |
| **Every model** | Pick by `provider/model#variant` or by plain name; search by price, context size and free tier. |
| **Agents and skills** | Primary agent (`build`, `plan`, or your own), mentioned sub-agents, OpenCode skills attached to the message. |
| **Parallelism** | `oc_delegate_parallel` runs up to 12 tasks and gathers the results. |
| **Background work** | `wait: false`, then `oc_wait` / `oc_result` whenever you like. Tasks outlive the wait timeout. |
| **Control** | `auto` / `readonly` / `agent` permissions or custom rules, answers to permissions and questions, interrupt, revert, diff. |
| **Readable results** | Final answer, tools used, files changed, tokens and cost, or the full transcript of the turn. |
| **Full access** | `oc_api` calls any of the ~120 operations of the OpenCode API: worktrees, MCP, credentials, web search, terminals, config. |
| **Zero configuration** | Finds the local OpenCode service on its own, starts it if it is asleep, reconnects if it moves to another port. |

## How it works

```mermaid
flowchart LR
    U([You]) --> C[Claude Code]
    C -- "MCP (stdio)<br/>oc_delegate, oc_wait…" --> M[claude-code-x-opencode]
    M -- "HTTP + Basic auth<br/>API v2" --> S[(OpenCode service)]
    S --> A1[Session 1<br/>model A · build agent]
    S --> A2[Session 2<br/>model B · plan agent]
    S --> A3[Session n<br/>…]
    A1 & A2 & A3 --> P[[Your project<br/>files · shell · web · MCP]]
```

The MCP server contains no model and stores no key. It talks to the **OpenCode service** already installed on your machine (`opencode service`), using the password that service writes to `~/.config/opencode/service.json`. Your providers, agents, skills and OpenCode MCP servers are the ones you already use.

One `oc_delegate` call does this:

1. creates the session (directory, model, agent, permissions), or picks up the one you give it;
2. sends the brief, with the requested skills, sub-agents and files;
3. waits until the session is idle again, checking every 4 seconds that it is not waiting for a permission or an answer;
4. summarizes the turn: answer, tools, files changed, tokens, cost, errors.

## Installation

### Requirements

- **Node.js 20 or later**
- **OpenCode 2.x** (API v2, tested with 2.1.4), with at least one provider connected: `opencode auth login`
- **Claude Code** (or any other MCP client)

Check that OpenCode answers:

```bash
opencode service status
```

### Option 1: straight from GitHub

```bash
claude mcp add -s user opencode -- npx -y github:AXLdev123/claude-code-x-opencode
```

On Windows, go through `cmd /c`:

```bash
claude mcp add -s user opencode -- cmd /c npx -y github:AXLdev123/claude-code-x-opencode
```

### Option 2: from a clone

```bash
git clone https://github.com/AXLdev123/claude-code-x-opencode.git
```

```bash
cd claude-code-x-opencode && npm install
```

```bash
claude mcp add -s user opencode -- node /path/to/claude-code-x-opencode/server.mjs
```

Then check:

```bash
claude mcp get opencode
```

### Other MCP clients

Claude Desktop, Cursor, Windsurf and the others take the same JSON entry:

```json
{
  "mcpServers": {
    "opencode": {
      "command": "npx",
      "args": ["-y", "github:AXLdev123/claude-code-x-opencode"]
    }
  }
}
```

### Optional: the Claude Code skill

The [`skill/opencode-subagent`](skill/opencode-subagent/SKILL.md) folder teaches Claude when to delegate, how to write the brief and how to check the work it gets back. Copy it to `~/.claude/skills/`:

```bash
cp -r skill/opencode-subagent ~/.claude/skills/
```

## Getting started

Open a new Claude Code session and talk normally:

> Check that the OpenCode connection works and list its free models.

> Delegate to OpenCode, with `claude-sonnet-5-5#high`, writing the tests for `src/parser.ts`. It must run `npm test` and give me the result.

> Ask three different models to review this module read-only, then give me a synthesis.

> Start documenting the `api/` folder in the background with a free model; we'll look at the result later.

## Tool reference

### Delegate

| Tool | What it does |
|---|---|
| `oc_delegate` | Hands off a task and returns the result. Creates a session or continues `session_id` (with `fork` to copy its history). |
| `oc_delegate_parallel` | Runs 1 to 12 tasks in parallel (one session each) and waits for every answer. |
| `oc_send` | Sends a follow-up message, a slash command or skills to an existing session. `delivery: steer` injects while the agent works, `queue` waits for the end of the turn. |
| `oc_wait` | Waits for a session started in the background, or just unblocked, to finish. |
| `oc_result` | Reads a session's state without waiting, pending requests included. |
| `oc_interrupt` | Stops the current turn. |

### Unblock

| Tool | What it does |
|---|---|
| `oc_pending` | Lists the permissions and questions blocking a session (or the whole server). |
| `oc_answer` | Answers: `request_id` + `decision` (`once`, `always`, `reject`), or `form_id` + `answer`. |

### Manage

| Tool | What it does |
|---|---|
| `oc_sessions` | Lists sessions, filtered by directory, text, parent or archive state. |
| `oc_session` | `info`, `diff`, `fork`, `compact`, `rename`, `archive`, `unarchive`, `delete`, `set_model`, `set_agent`, `shell`, `load_skill`, `revert`, `revert_clear`, `context`, `export`. |

### Discover

| Tool | What it does |
|---|---|
| `oc_status` | Connection, version, URL, default model, number of models, agents and skills. |
| `oc_models` | Searches models by text, provider or free only. Shows price, context size and variants. |
| `oc_catalog` | `agents`, `skills`, `commands`, `mcp`, `providers`, `integrations`, `plugins`, `config`, `projects`, `worktrees`, `websearch_providers`, `info`. |

### Everything else

| Tool | What it does |
|---|---|
| `oc_api_ops` | Lists the operations of the OpenCode API, or the detailed schema of one of them. |
| `oc_api` | Calls an operation by `operation` (operationId) or `method` + `path`. Path and query parameters go in `params`; `directory` is a shortcut. |

<details>
<summary><b>Every parameter of <code>oc_delegate</code></b></summary>

| Parameter | Type | Default | Purpose |
|---|---|---|---|
| `task` | text | **required** | The brief. The agent cannot see your conversation. |
| `directory` | absolute path | service directory | Project the agent works in. |
| `session_id` | text | | Continue this session. |
| `fork` | boolean | `false` | With `session_id`: copy the session before continuing. |
| `title` | text | generated | Session title. |
| `model` | text | default model | See [Choosing a model](#choosing-a-model). |
| `agent` | text | default agent | `build`, `plan`, or one of your agents. |
| `skills` | list | | Ids of OpenCode skills to attach. |
| `agents` | list | | Sub-agents to mention (`@general`, `@explore`…). |
| `files` | list | | Paths or URIs of files to attach. |
| `command` | text | | Slash command to run; `task` becomes its arguments. |
| `permissions` | preset or rules | `auto` | See [Permissions](#permissions). |
| `wait` | boolean | `true` | `false`: return right away with the `session_id`. |
| `timeout_s` | 5 to 7200 | `900` | Past it, the task keeps running and `oc_wait` picks it up. |
| `detail` | `final`, `summary`, `full` | `summary` | Answer only, answer + tools + files, or transcript. |

</details>

## Choosing a model

| Syntax | Example |
|---|---|
| `provider/model` | `opencode/claude-sonnet-5-5` |
| `provider/model#variant` | `opencode/claude-opus-5-5#max` |
| ids containing `/` | `openrouter/nex-agi/nex-n2.6` |
| plain name | `deepseek-v4.1-flash-free` |

With a plain name, the server takes the exact match, then the shortest one, preferring the `opencode`, `anthropic`, `openai`, `kilo` and `openrouter` providers in that order. If the name is still ambiguous, the error lists the candidates. Variants (`low`, `high`, `max`…) are shown by `oc_models`.

## Permissions

| Preset | Effect |
|---|---|
| `auto` *(default)* | Everything is allowed, like `opencode run --auto`. The agent works on its own. |
| `readonly` | Reading, searching and web allowed; editing, writing, patching and shell denied. |
| `agent` | The selected agent's rules. Anything set to `ask` blocks the session and comes back to Claude. |
| rules | A list of `{ action, resource, effect }`, with `effect` set to `allow`, `deny` or `ask`. |

Example: allow everything except the shell, which needs approval every time.

```json
[
  { "action": "*", "resource": "*", "effect": "allow" },
  { "action": "shell", "resource": "*", "effect": "ask" }
]
```

## Long tasks and blocked sessions

```mermaid
stateDiagram-v2
    [*] --> Running: oc_delegate
    Running --> Done: the session is idle again
    Running --> Blocked: permission or question
    Running --> Background: wait=false or timeout reached
    Blocked --> Running: oc_answer then oc_wait
    Background --> Done: oc_wait
    Running --> Interrupted: oc_interrupt
    Done --> Running: oc_send
```

When a session is waiting for something, the call returns with the exact command to run:

```text
session ses_… BLOCKED, waiting for an answer:
- permission per_… (session ses_…): shell on node -e "console.log(6*7)"
  → oc_answer {session_id:"ses_…", request_id:"per_…", decision:"once|always|reject"}
Answer with oc_answer, then resume with oc_wait {session_id:"ses_…", since:1794312322352}.
```

If the MCP client sends a `progressToken`, the server publishes a progress notification every 4 seconds while it waits.

## Configuration

Nothing is required. To target another OpenCode server:

| Variable | Purpose |
|---|---|
| `OPENCODE_URL` | Server URL (otherwise: `opencode service status`). |
| `OPENCODE_PASSWORD` | Basic auth password (otherwise: read from the service file). |
| `OPENCODE_SERVICE_FILE` | JSON file holding `password` (default: `~/.config/opencode/service.json`). |

```bash
claude mcp add -s user opencode -e OPENCODE_URL=http://127.0.0.1:4096 -e OPENCODE_PASSWORD=secret -- npx -y github:AXLdev123/claude-code-x-opencode
```

## Recipes

<details>
<summary><b>Compare three models on the same question</b></summary>

```json
{
  "tool": "oc_delegate_parallel",
  "arguments": {
    "detail": "final",
    "tasks": [
      { "task": "Review src/auth.ts and list the security flaws, without changing anything.", "directory": "/project", "model": "opencode/claude-sonnet-5-5#high", "permissions": "readonly" },
      { "task": "Review src/auth.ts and list the security flaws, without changing anything.", "directory": "/project", "model": "opencode/gpt-6.1-sol", "permissions": "readonly" },
      { "task": "Review src/auth.ts and list the security flaws, without changing anything.", "directory": "/project", "model": "opencode/deepseek-v4.1-flash-free", "permissions": "readonly" }
    ]
  }
}
```
</details>

<details>
<summary><b>Start in the background, collect later</b></summary>

```json
{ "tool": "oc_delegate", "arguments": { "task": "Document every exported function in api/", "directory": "/project", "wait": false } }
```

```json
{ "tool": "oc_wait", "arguments": { "session_id": "ses_…", "since": 1794312225387 } }
```
</details>

<details>
<summary><b>Plan agent + OpenCode skill</b></summary>

```json
{ "tool": "oc_delegate", "arguments": { "task": "Write the migration plan to Postgres 18.", "directory": "/project", "agent": "plan", "skills": ["writing-plans"] } }
```
</details>

<details>
<summary><b>Slash command</b></summary>

```json
{ "tool": "oc_delegate", "arguments": { "task": "HEAD~3", "command": "review", "directory": "/project" } }
```
</details>

<details>
<summary><b>Undo what the agent did</b></summary>

```json
{ "tool": "oc_session", "arguments": { "session_id": "ses_…", "action": "diff" } }
```

```json
{ "tool": "oc_session", "arguments": { "session_id": "ses_…", "action": "revert", "value": "msg_…" } }
```
</details>

<details>
<summary><b>Create a worktree through the raw API</b></summary>

```json
{ "tool": "oc_api_ops", "arguments": { "operation": "worktree.create" } }
```

```json
{ "tool": "oc_api", "arguments": { "operation": "worktree.create", "body": { "…": "…" } } }
```
</details>

## Troubleshooting

| Symptom | Likely cause and fix |
|---|---|
| `OpenCode service not found` | The service does not start. Run `opencode service start`, then `opencode service status`. |
| `HTTP 401` | Wrong password. Check `~/.config/opencode/service.json` or set `OPENCODE_PASSWORD`. |
| `Model "x" not found` or `is ambiguous` | Look up the exact id with `oc_models { search: "x" }`. |
| The task is "still running" | Expected past `timeout_s`: resume with `oc_wait`. Raise `timeout_s` if needed. |
| Nothing happens, no error | The session is probably waiting for a permission: `oc_pending`. |
| The tools do not show up | MCP servers load at startup: open a new Claude Code session. |

## Development

```bash
npm install
```

```bash
npm test
```

| Command | What it checks | Needs OpenCode |
|---|---|---|
| `npm test` | The 15 tools and their schemas. | No |
| `npm run test:live -- <empty-dir>` | The whole flow with real free models: delegation, follow-up, background, parallel. | Yes |
| `npm run test:live -- <empty-dir> quick` | Discovery only, no model calls. | Yes |
| `npm run test:interactive -- <empty-dir>` | Attached skills and the permission → `oc_answer` → `oc_wait` round trip. | Yes |

The live tests use `deepseek-v4.1-flash-free` and `opencode/big-pickle` by default; override them with `TEST_MODEL`, `TEST_MODEL_2` and `TEST_SKILL`.

Layout:

```text
server.mjs          the 15 MCP tools
lib/client.mjs      service discovery, HTTP client, OpenAPI, model resolution
lib/session.mjs     sessions, waiting, pending requests, result summaries
skill/              "opencode-subagent" Claude Code skill
test/               offline and end-to-end tests
```

Contributions are welcome: see [CONTRIBUTING.md](CONTRIBUTING.md).

## Known limitations

- Waiting and skill loading go through `experimental` routes of the OpenCode API. They may change from one version to the next.
- The `readonly` preset denies the `edit`, `write`, `patch`, `bash` and `shell` actions. A third-party MCP tool that writes to disk under another name is not covered: for a real sandbox, pass explicit rules.

## License

[MIT](LICENSE). Independent project, not affiliated with Anthropic or the OpenCode team.