Skip to content

Add OpenCode host adapter — TypeScript bridge package @archcore/opencode-plugin in plugins/opencode/ #25

Description

@ivklgn

Problem

The portable core is fully prepared for OpenCode, but the TypeScript bridge package that connects OpenCode's plugin API to the core does not exist yet. This issue implements the bridge; the goal is that OpenCode works exactly like the existing hosts (Claude Code / Cursor / Codex) on the same core — the bridge translates, it never decides.

What already exists (do NOT re-implement or refactor)

Core readiness landed on dev (see .archcore/plugin/host-expansion-core-readiness.plan.md):

  • plugins/archcore/bin/lib/normalize-stdin.sh — explicit opencode case (env-only host: ARCHCORE_HOST=opencode from the bridge is never clobbered — pinned by a test that fails on the pre-change code); info helpers emit plain text for opencode; block stays exit 2 + reason on stderr. The full bridge contract is documented in the file header.
  • plugins/archcore/bin/session-start — plain-text arm covers opencode; passes opencode as the host arg to archcore hooks.
  • test/fixtures/stdin/opencode/ — Claude-shaped snake_case fixtures; these ARE the bridge's stdin contract (write-archcore / write-regular / mcp-update).
  • test/helpers/common.bashrun_with_fixture_env helper for env-forced hosts.
  • Tests: block/allow/info pins for opencode across normalize-stdin.bats, check-archcore-write.bats, session-start.bats, output-helpers-matrix.bats.

Decisions are final and recorded in .archcore/plugin/ — do not re-litigate:

  • opencode-adapter-packaging.adr.md — TypeScript npm package @archcore/opencode-plugin, in THIS repo under plugins/opencode/; bun test scoped to that directory only; hook bridge is shell-out only — no decision logic in TS.
  • opencode-host-support.rnd.md — verified OpenCode plugin API facts: tool.execute.before/after hooks; deny = throw new Error(...) (model sees the message); config hook mutates live config (cfg.mcp, cfg.skills.paths); MCP config key is environment, not env; skills ship inside the package and register via cfg.skills.paths.
  • stack-and-tooling.rule.md — the TS + bun test exception is scoped to plugins/opencode/ only.
  • host-adapter-contract.spec.md — adapter obligations and the deny-semantics translation table.

Expected result

An OpenCode session with the plugin installed behaves like the shipped hosts: session-start injects .archcore context, direct writes to .archcore/*.md are blocked with the redirect-to-MCP message (bridge throws Error(stderr) on exit 2), MCP document tools work, post-tool validation/cascade context is appended.

Proposed approach

  • Scaffold plugins/opencode/ as npm package @archcore/opencode-plugin (Bun runtime).
  • Bridge contract (documented in normalize-stdin.sh header): spawn plugins/archcore/bin/ scripts with ARCHCORE_HOST=opencode in env and a Claude-shaped snake_case JSON payload on stdin — exactly the shape in test/fixtures/stdin/opencode/.
  • tool.execute.beforebin/check-archcore-write + bin/check-code-alignment; exit 2 → throw new Error(stderr); stdout (plain text) → context.
  • tool.execute.afterbin/validate-archcore, bin/check-cascade, bin/check-precision; append plain stdout verbatim.
  • Session start → bin/session-start (plain-text output, appended verbatim).
  • config hook: register the archcore MCP server (key environment) and add the bundled skills path to cfg.skills.paths.
  • bun test inside plugins/opencode/ only, driven by the shared fixtures in test/fixtures/stdin/opencode/ so the TS side and the shell side pin the same contract.
  • npm packaging/publish config for @archcore/opencode-plugin (install via plugin: [] array).

Acceptance criteria

  • Live OpenCode session: write blocked with redirect message, MCP tools work, session-start context arrives, skills available.
  • Zero changes under plugins/archcore/ (enforced by host-logic-locality.bats and the exact-output pins — all stay green).
  • No TypeScript outside plugins/opencode/ (stack rule enforcement); make test lint check-json green; bun test green in plugins/opencode/.

Dependencies

  • needs-cli: the Go CLI must accept archcore hooks opencode session-start. Today an unknown host degrades silently (guard still works, context load does not) — needs a companion issue in the CLI repo.

References

.archcore/plugin/opencode-adapter-packaging.adr.md, opencode-host-support.rnd.md, host-adapter-contract.spec.md, stack-and-tooling.rule.md, host-expansion-core-readiness.plan.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:hooksPreToolUse/PostToolUse/SessionStart hooksneeds-cliDepends on the separate Archcore CLI (Go) repopriority:P2Valuable follow-upsize:LMulti-day / needs a spike

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions