feat(dispatcher): add opencode CLI support - #89
Merged
Conversation
opencode (anomalyco/opencode) is a provider-agnostic open-source coding agent CLI. Like codex, it mints its own session id per invocation and does not accept a caller-provided id. Add first-class support by mirroring the codex pattern from #88: capture the CLI-minted session id from the JSON event stream into a sidecar under pid_dir_for_project() keyed by the dispatcher's session_id, then feed it back to `opencode run --session <id>` on resume. JSON shape verified against opencode v1.14.46: {"type":"step_start","timestamp":...,"sessionID":"ses_<base62>",...} The sessionID is on every event (not gated on a specific type) so the capture filter records the first occurrence; a regex validator (`^ses_[A-Za-z0-9]+$`) protects the downstream `--session <id>` invocation against injection from a malformed sidecar. - run_agent opencode branch: `opencode run --format json [--title <session_name>] [PROMPT]` piped through _opencode_capture_session. - resume_agent opencode branch: reads the captured sessionID via _opencode_session_id and calls `opencode run --session <id> ...`. Falls back to a fresh run when the sidecar is missing or malformed (same defensive pattern as the codex/kiro branches). - Tests: 31 cases in tests/unit/test-lib-agent-opencode.sh covering source-of-truth grep, run_agent argv shape + sessionID capture, resume using captured sid, fallback when sidecar missing, crash path, and a malformed-sidecar regression that verifies the regex validator triggers fallback rather than passing garbage to opencode. - README: add opencode to the top blurb, AGENT_CMD allowed values, and the Supported Agent CLIs table (Full support row). - autonomous.conf.example: add a one-paragraph comment naming the four first-class CLIs. Full unit suite: 37/37 test files pass.
There was a problem hiding this comment.
Summary
This PR successfully adds first-class opencode CLI support to the dispatcher's agent abstraction layer. The implementation mirrors the proven codex pattern (CLI-minted session ID capture) and includes comprehensive testing.
Implementation Quality:
- Follows established architecture patterns from the codex branch
- Proper error handling for all failure modes (CLI crashes, missing sidecars, malformed data)
- Security defenses in place: symlink checks (CWE-59), regex validation to prevent injection attacks
- Comprehensive test suite with 31 test cases covering behavioral verification and edge cases
Verification:
- All changes are consistent across documentation, configuration, implementation, and tests
- The regex pattern
^ses_[A-Za-z0-9]+$correctly validates opencode's session ID format - Fallback behavior matches the defensive pattern used in other CLI branches
No blocking issues found. The code is ready for merge.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
4 tasks
zxkane
added a commit
that referenced
this pull request
May 10, 2026
## Summary Document the two prerequisites for running opencode under the dispatcher: (1) `opencode providers login` to set up credentials, and (2) explicit `AGENT_DEV_MODEL` / `AGENT_REVIEW_MODEL` in `autonomous.conf` (opencode is provider-agnostic — no default model). Also flag that `AGENT_PERMISSION_MODE=bypassPermissions` isn't yet wired to opencode's `--dangerously-skip-permissions` flag (same gap as codex). ## Why After #89 added first-class opencode support, a user reading the README's "Full support" badge and setting `AGENT_CMD=opencode` would get a silently stalled pipeline: opencode enters a session but produces no output without credentials and an explicit model. Spelling out the prereqs up-front prevents the foot-gun. ## What changed - **README → Supported Agent CLIs**: opencode row now has a † footnote covering auth + explicit model + the bypassPermissions gap. - **README → variable table**: the `AGENT_CMD` row gets an inline pointer to the footnote so users editing `autonomous.conf` see the warning without scrolling. - **`autonomous.conf.example`**: the `AGENT_CMD` comment and the `AGENT_DEV_MODEL` / `AGENT_REVIEW_MODEL` comments now explicitly call out that empty model values are valid for claude/codex but invalid for opencode. ## Test Plan - [x] No code changes; `bash -n` clean on `autonomous.conf.example` - [ ] CI checks pass ## Checklist - [x] Docs only - [x] Build/tests not affected
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.
Summary
Add first-class opencode (
anomalyco/opencode) support to the dispatcher's agent abstraction layer. opencode is a provider-agnostic open-source coding agent CLI that, like codex, mints its own session id per invocation. Mirrors the pattern established in #88: capture the CLI-minted id from the JSON stream into a sidecar, feed it back on resume.Why
After #88 fixed the codex branch with a session-id-capture pattern, opencode's identical wrinkle (CLI mints the id; caller can't pre-mint) became cheap to address with the same approach. README #87 already lists opencode as the next CLI to integrate; this closes that follow-up.
Design
opencode JSON shape (verified against
opencode run --format json --pure "test"on v1.14.46):{"type":"step_start","timestamp":1778415469963,"sessionID":"ses_1ee2d8d...","part":...}Every event carries
"sessionID":"ses_<base62>"— not gated on a specific event type. The capture filter records the first occurrence (which arrives in the very first event), validates the format with^ses_[A-Za-z0-9]+$, and writes it to${pid_dir}/opencode-session-${dispatcher_session_id}.run_agentopencode case:opencode run --format json [--title <session_name>] [PROMPT]piped through_opencode_capture_session.resume_agentopencode case: reads the captured id via_opencode_session_idand callsopencode run --session <id> --format json [PROMPT]. Falls back torun_agentwhen the sidecar is missing or malformed (defense-in-depth: even though pid_dir is mode 0700, a malformed sidecar value would otherwise be passed toopencode run --session ...as raw shell input).Test Plan
opencode run --format json --pure "test", confirmed JSON shape; ran resume with the captured id, confirmed it works.tests/unit/test-lib-agent-opencode.sh:run --format json, resume uses--session)ses_with;injection\hazard→ regex rejects, fallback triggers, garbage never reachesopencode run --session`)bash -nclean onlib-agent.shlib-config.shsourceBackwards Compatibility
AGENT_CMD=opencodewas previously routed to the generic<cli> -p <prompt>fallback. With this PR it's routed to a first-class branch — the new behavior is strictly more correct (no-pflag misuse).claude/codex/kirobranches unchanged.Open follow-ups (not in scope)
--dangerously-skip-permissionsflag wiring whenAGENT_PERMISSION_MODE=bypassPermissions. The codex branch has the same gap; would prefer a single PR that addresses both consistently rather than per-CLI ad-hoc fixes.Checklist