Skip to content

feat(opencode): attach to an external serve URL - #1806

Merged
chuks-qua merged 5 commits into
mainfrom
feat/opencode-external-attach-1627
Oct 6, 2026
Merged

chuks-qua merged 5 commits into
mainfrom
feat/opencode-external-attach-1627

Conversation

@chuks-qua

@chuks-qua chuks-qua commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

What

OpenCode can now attach to an opencode serve that is already running. Before, Mcode always spawned and owned one serve process per worktree. A user with a shared backend could not point Mcode at it.

Set provider.opencode.serveUrl in Settings > Providers > OpenCode. When it is set, turns, stop, and model listing go to that server. Mcode does not probe the CLI or use the pool, and it never closes the server. When the field is empty, Mcode spawns a pooled server per worktree, as before.

One serve process can host many directories. A request without ?directory= runs in the server's own working directory, which I measured on opencode 1.18.28. So the HTTP client now sends directory on every request, including the SSE /event stream. For pooled servers the value equals the server's cwd, so behavior there does not change.

The settings row also gains the missing OpenCode CLI path input. It now uses the catalog name, so it reads "OpenCode" instead of "Opencode".

Verified on a live runtime (opencode 1.18.28, model opencode/muse-spark-1.3-contributor-free):

  • runtime live --scenario opencode-attach passes. The turn completes with a durable assistant message. The script, acting as a second client, finds the session on the external server with directory equal to the thread's cwd. The external server's PID and health survive a runtime restart.
  • With the whole Mcode runtime stopped (agent:down), the attached server still answered /global/health.
  • runtime live --scenario opencode-resume (pooled path) passes.
  • Targeted tests pass: OpenCode server suite (116 tests), contracts settings (41), and web ProviderSection (13). bun run typecheck passes and bun run lint reports no errors.

Upstream versions recorded in the attach receipt: binary 1.18.28, server 1.18.28, SDK none (Mcode uses a hand-written HTTP client, not @opencode-ai/sdk).

Why

Closes #1627. A shared opencode serve must stay shared. If Mcode owned it, closing the app or idle eviction would kill other clients' sessions, which is the shared-server failure mode called out in #1621.

UI Changes

Settings > Providers, OpenCode row. Before: no configuration. After: CLI path and Serve URL. The Serve URL commits on blur or Enter, and it shows an inline error for anything other than an empty value or an http(s) URL.

Config Changes

New setting provider.opencode.serveUrl (string, default ""). It accepts an empty value or an absolute http(s) URL, and it strips a trailing slash. It rejects other schemes, embedded credentials, and query or fragment parts, because the adapter appends its own ?directory=.

Review Notes

  • Builds on fix(verify-mcode): read live turn events from agent.canonical #1805 (merged), which fixed the verify-mcode live harness to read agent.canonical after refactor(agents)!: replace agent.event replay with canonical recovery #1779 removed agent.event.
  • The full provider-completeness proof is not green. On web, every provider journey failed: Codex, Claude, and OpenCode. Codex and Claude fail at the same Review comparison step ("comparison did not settle" or "Live agent diff never appeared"), and this PR does not touch them. I infer the failure is not from this change, but I did not rerun the matrix on main to confirm. The web OpenCode turn itself completed: the edit landed and the reply rendered. Its tool group showed an errored badge, which needs a follow-up look. On Electron, OpenCode is a coverage gap, not a pass, because OpenCode is disabled in that profile. Live automatic review and the managed block cannot run for OpenCode, because it reports approval review as unavailable. The matrix records both as coverage gaps.
  • Availability still requires the opencode CLI on PATH even when a serve URL is set. Attaching to a remote server from a machine without the CLI is a possible follow-up.
  • Serve URL authentication (OPENCODE_SERVER_PASSWORD) is out of scope.
  • The verifier gains an opencode-attach scenario, an OpenCode row in the completeness matrix, and an upstreamOpenCode receipt block.

OpenCode settings before

OpenCode settings after


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Base automatically changed from fix/verify-mcode-canonical-live-events to main October 6, 2026 11:14
A configured provider.opencode.serveUrl attaches turns, stop, and model
listing to an external opencode serve that the app never spawns, pools,
or closes. Every request now carries the thread directory, because one
serve process hosts many directories.

Refs #1627
…completeness matrix

Records the opencode binary and server versions in receipts.

Refs #1627
@chuks-qua
chuks-qua force-pushed the feat/opencode-external-attach-1627 branch from 94099ce to 89349f3 Compare October 6, 2026 11:14
@chuks-qua
chuks-qua merged commit 1064498 into main Oct 6, 2026
6 of 11 checks passed
@chuks-qua
chuks-qua deleted the feat/opencode-external-attach-1627 branch October 6, 2026 11:20
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.

OpenCode external attach, catalog, and verifier matrix

1 participant