Repository navigation
feat(opencode): attach to an external serve URL - #1806
Merged
Merged
Conversation
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
force-pushed
the
feat/opencode-external-attach-1627
branch
from
October 6, 2026 11:14
94099ce to
89349f3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
OpenCode can now attach to an
opencode servethat 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.serveUrlin 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 sendsdirectoryon every request, including the SSE/eventstream. 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-attachpasses. The turn completes with a durable assistant message. The script, acting as a second client, finds the session on the external server withdirectoryequal to the thread's cwd. The external server's PID and health survive a runtime restart.agent:down), the attached server still answered/global/health.runtime live --scenario opencode-resume(pooled path) passes.bun run typecheckpasses andbun run lintreports 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 servemust 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
agent.canonicalafter refactor(agents)!: replace agent.event replay with canonical recovery #1779 removedagent.event.provider-completeness proofis 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 onmainto confirm. The web OpenCode turn itself completed: the edit landed and the reply rendered. Its tool group showed anerroredbadge, 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 asunavailable. The matrix records both as coverage gaps.opencodeCLI 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.OPENCODE_SERVER_PASSWORD) is out of scope.opencode-attachscenario, an OpenCode row in the completeness matrix, and anupstreamOpenCodereceipt block.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.