Skip to content

Add the opencode adapter (six agent CLIs now) - #53

Merged
navbytes merged 3 commits into
mainfrom
feat/opencode-adapter
Aug 6, 2026
Merged

navbytes merged 3 commits into
mainfrom
feat/opencode-adapter

Conversation

@navbytes

@navbytes navbytes commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Adds the opencode adapter, the third of the three the competitive research recommended. roost now covers six agent CLIs: pi, Claude Code, shell, codex, gemini, opencode.

The research changed the design, which is why it was worth doing first. The published troubleshooting docs describe per-project project/<slug>/storage/ session directories. That is stale — opencode's own source (packages/core/src/global.ts, database/database.ts) stores sessions in one global SQLite database at $XDG_DATA_HOME/opencode/opencode.db. There are no session files to scan.

So session_root, session_id_from_path and owns_session_file stay at the trait default and detection degrades honestly to SessionState::Unknown, rather than fabricating a directory that doesn't exist. Reading the database would mean a new SQL dependency or shelling out, neither of which this crate does anywhere. That limitation is documented in the module as a researched conclusion, not left looking like an oversight — the same shape as codex's date-bucketed (not cwd-bucketed) sessions.

Confirmed against source rather than assumed:

  • Resume is opencode --session <id> (-s). --continue is never emitted — opencode --continue should not resume from subagent tasks anomalyco/opencode#2086 is exactly the hazard of it resuming a subagent's thread instead of the parent's. A test guards its absence.
  • Session ids are ses_ plus 26 base62 characters (packages/schema/src/session-id.ts), comfortably inside the existing valid_session_id guard — no loosening needed.

Five tests: launch shape, resume shape plus the --continue/-c absence guard, id round-trip through valid_session_id, session_root is None across two different cwds, session_state always Unknown, and detect_session returning None with a populated taken set.

Two fixes outside the adapter, both caused by it:

  • the_picker_draws_both_columns_and_the_live_filter asserted that a one-letter p query leaves exactly one row. Adding opencode gave p a second match, so it failed. The test's actual point is that type-ahead narrows to one row — not that some adapter happens to be alone under a single letter — so the query is now pi, with an added assertion that opencode is the row that drops.
  • README's roadmap line still listed opencode as deferred and predated native selection.

644 unit tests plus all integration green; clippy unchanged. opencode isn't installed on the build host, so there is no live subprocess smoke test.

Resume mechanism confirmed against the live CLI reference
(opencode.ai/docs/cli) and opencode's own dev-tip source: `opencode
--session <id>` resumes exactly; `--continue` is never emitted, since
anomalyco/opencode#2086 shows it can resume a subagent's thread
instead of the parent's.

Sessions are confirmed to live in one global SQLite database
(packages/core/src/{global,database/database}.ts), not a directory of
per-session files, so session_root/session_id_from_path/
owns_session_file stay at the trait default (None/Unknown) rather than
faking a scannable path — documented in the module doc as a researched
limitation, not an oversight.
Declares the module and adds it to adapter_specs() right after gemini
— matching the research doc's priority ranking (codex, gemini,
opencode) — so registry() and picker_ids() both pick it up.
…ferred

Adding the opencode adapter made the picker test's one-letter 'p' query
match two rows instead of one, so its 'no second row survives' assertion
failed. The test's point is that type-ahead narrows to exactly one row,
not that any particular adapter is alone under a single letter — so the
query is now 'pi', with an added assertion that opencode (the other 'p'
match) is the row that drops.

README's roadmap line still listed opencode as deferred and predated
native selection.
@navbytes

navbytes commented Aug 6, 2026

Copy link
Copy Markdown
Owner Author

Merging on local verification: GitHub Actions is in a major outage, so CI cannot run. Verified against the rebased merge result — 657 tests pass, clippy unchanged. The one red is firehose_latency_starvation_and_clean_exit (253–262ms against a 250ms echo bound), which unmodified main also fails about one run in three on this machine under parallel build load; CI itself loosens that bound to 1000ms on macOS runners. Not a regression.

@navbytes
navbytes merged commit cf859cb into main Aug 6, 2026
0 of 2 checks passed
@navbytes
navbytes deleted the feat/opencode-adapter branch August 6, 2026 23:44
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.

1 participant