You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
opencode is a registered builder harness but is broken end-to-end. A builder configured with shell.builder: "opencode" launches, immediately exits 0, and shows the relaunch screen
("Agent exited at your request. Press Enter to relaunch, or close this terminal.") — so it never
actually runs. This issue is to either fix opencode as a builder or retire it (sibling of #1338,
"Retire Gemini CLI as a builder harness"). Original support was added in #178 (closed).
Surfaced during manual testing of Spec 1313 (afx send mailbox delivery).
Observed: the new task builder instantly prints Agent exited at your request. Press Enter to relaunch, or close this terminal. and never starts.
Root cause — CLI-contract drift (verified)
The builder launch script (packages/codev/src/agent-farm/commands/spawn-worktree.ts:875) passes the
initial prompt as a positional argument — the claude/codex convention:
OPENCODE_HARNESS.buildScriptRoleInjection returns an empty fragment (opencode's role injection is
file-based via the opencode.json it writes — { "instructions": [".builder-role.md"] }), so the prompt
falls through to Codev's generic positional form.
But opencode 1.18.11's positional slot is a project path, not a prompt:
opencode [project] start opencode tui [default]
opencode run [message..] run opencode with a message
Positionals:
project path to start opencode in [string]
Options:
--prompt prompt to use [string]
So opencode tries to cd into a directory named after the entire prompt text, fails, and exits 0.
Confirmed directly:
$ opencode "You are a Builder. Read codev/roles/builder.md for your full role definition."
Error: Failed to change directory to <cwd>/You are a Builder. Read codev/roles/builder.md…
EXIT=0
The launch loop treats exit 0 as a clean/user-requested exit → the relaunch screen. This is the worst failure mode: it looks like a healthy idle builder, not an error. The OPENCODE_HARNESS was
written against an older opencode CLI (a bare positional was an initial prompt); opencode's CLI has since
moved prompts to opencode run "<msg>" (headless) or opencode --prompt "<msg>" (TUI with initial prompt).
Secondary gap — no render-gate profile (Spec 1313)
Even if the launch were fixed, afx send to an opencode builder would always hold no-profile: PROFILES_BY_HARNESS in packages/codev/src/agent-farm/servers/gate-profiles.ts is { claude, codex }
only (agy is matched directly). detectHarnessFromCommand recognizes opencode, but it isn't in the
profile registry, so resolveProfile returns null → no-profile. A working opencode builder would
therefore be undeliverable-to until an opencode gate profile is measured and added.
Decision: fix or retire
Option A — Fix opencode as a builder
Correct the launch invocation. Deliver the prompt via opencode --prompt "<prompt>" (TUI with an
initial prompt) instead of the positional slot. This needs a harness-level "prompt delivery form" seam
(today the generic script appends "$(cat prompt)" positionally for every harness) or an
opencode-specific launch template.
Add an opencode render-gate profile to gate-profiles.ts (marker glyph, region-end patterns,
placeholder intensity/color rule) — empirically measured like claude/codex/agy — so afx send can
deliver instead of holding no-profile.
Verify file-based role injection (opencode.jsoninstructions: [".builder-role.md"]) is still
honored by current opencode.
Guard against CLI drift — a version-bump smoke test that a spawned opencode builder actually reaches
an interactive prompt with the role + task applied.
Option B — Retire opencode as a builder (mirrors #1338)
Remove OPENCODE_HARNESS from BUILTIN_HARNESSES and the opencode branch from detectHarnessFromCommand (packages/codev/src/agent-farm/utils/harness.ts).
A decision is recorded (fix vs retire), and one of the two is implemented and verified live — not
just unit-green:
Fix:afx spawn --task "…" with shell.builder: "opencode" reaches a working interactive
opencode builder with the role + task applied, andafx send to it delivers (not no-profile).
Retire:shell.builder: "opencode" is rejected at spawn with a helpful error; no silent
relaunch loop; no dangling opencode harness references in code or docs.
The silent exit-0 "Agent exited at your request" loop is gone in both outcomes.
Summary
opencode is a registered builder harness but is broken end-to-end. A builder configured with
shell.builder: "opencode"launches, immediately exits 0, and shows the relaunch screen("Agent exited at your request. Press Enter to relaunch, or close this terminal.") — so it never
actually runs. This issue is to either fix opencode as a builder or retire it (sibling of #1338,
"Retire Gemini CLI as a builder harness"). Original support was added in #178 (closed).
Surfaced during manual testing of Spec 1313 (
afx sendmailbox delivery).Reproduction
afx spawn --task "I am testing, please sit idle."Observed: the new task builder instantly prints
Agent exited at your request. Press Enter to relaunch, or close this terminal.and never starts.Root cause — CLI-contract drift (verified)
The builder launch script (
packages/codev/src/agent-farm/commands/spawn-worktree.ts:875) passes theinitial prompt as a positional argument — the claude/codex convention:
OPENCODE_HARNESS.buildScriptRoleInjectionreturns an empty fragment (opencode's role injection isfile-based via the
opencode.jsonit writes —{ "instructions": [".builder-role.md"] }), so the promptfalls through to Codev's generic positional form.
But opencode 1.18.11's positional slot is a project path, not a prompt:
So opencode tries to
cdinto a directory named after the entire prompt text, fails, and exits 0.Confirmed directly:
The launch loop treats exit 0 as a clean/user-requested exit → the relaunch screen. This is the
worst failure mode: it looks like a healthy idle builder, not an error. The
OPENCODE_HARNESSwaswritten against an older opencode CLI (a bare positional was an initial prompt); opencode's CLI has since
moved prompts to
opencode run "<msg>"(headless) oropencode --prompt "<msg>"(TUI with initial prompt).Secondary gap — no render-gate profile (Spec 1313)
Even if the launch were fixed,
afx sendto an opencode builder would always holdno-profile:PROFILES_BY_HARNESSinpackages/codev/src/agent-farm/servers/gate-profiles.tsis{ claude, codex }only (agy is matched directly).
detectHarnessFromCommandrecognizesopencode, but it isn't in theprofile registry, so
resolveProfilereturnsnull→no-profile. A working opencode builder wouldtherefore be undeliverable-to until an opencode gate profile is measured and added.
Decision: fix or retire
Option A — Fix opencode as a builder
opencode --prompt "<prompt>"(TUI with aninitial prompt) instead of the positional slot. This needs a harness-level "prompt delivery form" seam
(today the generic script appends
"$(cat prompt)"positionally for every harness) or anopencode-specific launch template.
gate-profiles.ts(marker glyph, region-end patterns,placeholder intensity/color rule) — empirically measured like claude/codex/agy — so
afx sendcandeliver instead of holding
no-profile.opencode.jsoninstructions: [".builder-role.md"]) is stillhonored by current opencode.
harness.session,supportsContextReset) against opencode's--continue/--session.an interactive prompt with the role + task applied.
Option B — Retire opencode as a builder (mirrors #1338)
OPENCODE_HARNESSfromBUILTIN_HARNESSESand theopencodebranch fromdetectHarnessFromCommand(packages/codev/src/agent-farm/utils/harness.ts).shell.builder: "opencode"fail fast at spawn with a clear "unsupported harness" errorinstead of silently launching a broken relaunch loop. (Related: Harden harness resolution: unrecognized override command defaults to claude harness (residual --resume crash-loop) #1062 — an unrecognized command
falls back to the claude harness;
opencodeis currently recognized, so it launches with the wronginvocation rather than falling back.)
Acceptance criteria
just unit-green:
afx spawn --task "…"withshell.builder: "opencode"reaches a working interactiveopencode builder with the role + task applied, and
afx sendto it delivers (notno-profile).shell.builder: "opencode"is rejected at spawn with a helpful error; no silentrelaunch loop; no dangling opencode harness references in code or docs.
Related
no-profilegate gap and this launch failure were surfacedEnvironment
1.18.11(/home/user/.opencode/bin/opencode)builder/spir-1313) during manual testing.