Skip to content

Promote OpenCode to first-class ContextRelay peer#123

Open
nillo wants to merge 4 commits into
mainfrom
feat/opencode-first-class-peer-pr
Open

Promote OpenCode to first-class ContextRelay peer#123
nillo wants to merge 4 commits into
mainfrom
feat/opencode-first-class-peer-pr

Conversation

@nillo

@nillo nillo commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Promotes OpenCode to a first-class ContextRelay peer alongside Claude and Codex. This wires OpenCode through CLI launch, MCP registration, daemon routing, named sessions, docs, instructions, and verifier coverage.

Changes

  • Add/complete OpenCode MCP and daemon routing paths for live messages, handoffs, deliberation, backup, and finality.
  • Add Codex-to-OpenCode MCP tools and fallback marker support.
  • Fix Claude-to-OpenCode relay delivery, named-session startup for ctxrelay opencode and ctxrelay trio --session, and runtime-session-scoped backup state.
  • Update README, reference docs, website docs, generated instruction blocks, doc-sync verifier, plugin bundles, TUI SVG, and CHANGELOG.
  • Add regression coverage for OpenCode routing, MCP behavior, fallback parsing, named trio launch, ledger/session handling, and role instructions.
  • Pin transitive shell-quote to patched 1.8.4 so dependency audit does not pull the vulnerable 1.8.3 copy.

Testing

  • bun run check passed after changelog and dependency override updates.
    • tsc --noEmit
    • 1088 source tests passed
    • 3 example tests passed
    • CLI sync, plugin sync, docs sync, instructions, plugin validation, version, and lockfile checks passed
  • bun audit --audit-level=high passed.
  • git diff --check passed.
  • Background/live smoke passed with an isolated real daemon process:
    • attached OpenCode via daemon WebSocket
    • attached Claude via daemon WebSocket
    • relayed a live Claude-to-OpenCode message
    • authenticated daemon status showed opencodeConnected: true, opencodeReady: true, and OpenCode participant online

Notes

  • Do not merge automatically; this PR is left open for review.

nillo added 2 commits June 9, 2026 19:33
Add OpenCode (headless-cli) as a coordinator-eligible peer alongside Claude
and Codex, with full parity across type system, daemon routing, MCP tools,
CLI commands, session lifecycle, backup system, and instructions.

New files:
- src/opencode-mcp.ts: MCP server with 16 tools for OpenCode
- src/opencode-instructions.ts: coordinator-aware MCP instructions builder
- src/opencode-adapter.ts: daemon WS transport adapter
- src/cli/opencode.ts: ctxrelay opencode command
- src/cli/opencode-mcp.ts: ctxrelay opencode-mcp install/remove/status/server
- src/cli/trio.ts: ctxrelay trio (Claude + Codex + OpenCode launcher)
- src/unit-test/opencode-mcp.test.ts, opencode-instructions.test.ts

Modified (24 files): types, agents, config, agent-descriptors, agent-routing,
control-protocol, daemon, claude-adapter (+3 tools), instructions,
backup/triggers, session-participants, session/registry/policy/escalation,
cli.ts, cli/coordinator/idle-eval/tui, 6 test files.

tsc --noEmit: 0 errors
bun test: 1074/1079 pass (5 pre-existing cli.test flag-check failures)
Comment thread src/opencode-adapter.ts
const line = `[${new Date().toISOString()}] [${DISPLAY_NAME}OpenCode] ${msg}\n`;
process.stderr.write(line);
try {
appendFileSync(this.logFile, line);
Comment thread src/cli/opencode.ts
@@ -0,0 +1,101 @@
import { spawn } from "node:child_process";
import { DISPLAY_NAME, PRIMARY_BIN } from "../branding";
Comment thread src/cli/trio.ts
@@ -0,0 +1,187 @@
import { execFileSync } from "node:child_process";
import { randomUUID } from "node:crypto";
Comment thread src/cli/trio.ts
import { buildInstanceEnv, resolveProjectInstance, type ProjectInstance } from "../instance";
import { envValue } from "../env";
import { StateDirResolver } from "../state-dir";
import { SessionLedger } from "../session/ledger";
Comment thread src/opencode-adapter.ts
@@ -0,0 +1,243 @@
import { spawn, type ChildProcess } from "node:child_process";
Comment thread src/opencode-adapter.ts
@@ -0,0 +1,243 @@
import { spawn, type ChildProcess } from "node:child_process";
import { createInterface } from "node:readline";
Comment thread src/opencode-adapter.ts
import { appendFileSync } from "node:fs";
import { StateDirResolver } from "./state-dir";
import type { BridgeMessage } from "./types";
import { createInstanceId, type ProjectInstance } from "./instance";
Comment thread src/opencode-adapter.ts
import { DaemonLifecycle } from "./daemon-lifecycle";
import { ConfigService } from "./config-service";
import { DISPLAY_NAME } from "./branding";
import { envInt, envValue } from "./env";
Comment thread src/opencode-adapter.ts
stateDir: StateDirResolver,
) {
super();
const config = new ConfigService().loadOrDefault();
@@ -0,0 +1,250 @@
import { describe, expect, test } from "bun:test";
import { OPENCODE_MCP_TOOLS, createOpenCodeMcpServer } from "../opencode-mcp";
import { buildOpencodeMcpInstructions } from "../opencode-instructions";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants