Skip to content

Migrate the Sema plugin to the OpenCode v2 API #1

Description

@HelgeSverre

Problem

@sema-lang/opencode-sema is an OpenCode v1 plugin factory. Its default export returns a config hook, so OpenCode v2 will not run it. Configuration migration alone is insufficient: v2 requires a stable plugin ID and a setup(ctx) implementation.

Current behavior to preserve or explicitly replace

The v1 config hook currently:

  • resolves the Sema binary with SEMA_PATH > plugin path option > sema;
  • warns through the OpenCode client when the resolved binary is unavailable;
  • adds a sema LSP command (sema lsp) without replacing a user-owned entry;
  • adds a sema MCP server (sema mcp) without replacing a user-owned entry;
  • adds a .sema formatter (sema fmt $FILE) unless its option/environment/global configuration disables it; and
  • injects the bundled Sema guide unless its option/environment disables it.

Existing unit tests cover these defaults, precedence rules, opt-outs, non-clobbering behavior, warning behavior, and the default/named export aliases.

Required implementation

  • Replace the v1 SDK dependency and types (@opencode-ai/plugin) with an @opencode/plugin version compatible with the OpenCode v2 release this package targets. Update peer dependency metadata, lockfile, build output, and package exports as needed.
  • Default-export Plugin.define({ id: "sema", async setup(ctx) { ... } }). Keep sema stable because v2 scopes persistent state and diagnostics by plugin ID.
  • Register the MCP server through ctx.mcp.transform. Add the local sema server only when no entry with that name already exists; use [resolvedBinary, "mcp"] and the native v2 MCP shape. Do not overwrite a user-owned entry.
  • Read and validate ctx.options using the existing path, formatter, and instructions contract. Preserve environment precedence and ~ expansion. Preserve SEMA_DISABLE_FORMATTER and SEMA_DISABLE_INSTRUCTIONS semantics where the related v2 behavior exists.
  • Replace the v1 client logger with a documented v2-safe warning mechanism. A missing binary must produce a useful diagnostic without stopping plugin setup.
  • Replace the v1 instructions config mutation. V2 currently accepts instructions configuration but does not resolve it. When instructions are enabled, load the bundled guide during setup and inject it with the v2 session context hook using the documented model-visible system-message shape. Do not add it when the existing opt-out is set.
  • Add a compatibility entrypoint only if we continue to support OpenCode v1. The v2 documentation supports a combined default export with v2 setup() and v1 server() only for v1.18.29+. If retained, narrow the supported v1 range, keep the old config-hook implementation separate, and test both runtimes. Otherwise, make this a v2-only major release and document the breaking support boundary.

Known v2 limits and user-facing behavior

  • LSP: OpenCode v2 accepts lsp configuration but currently has no LSP runtime, built-in servers, diagnostics, or LSP tool. Its plugin API also has no LSP transform. Do not claim that this release provides working Sema LSP integration. Document the manual v2 LSP configuration as forward-compatible only, and open a follow-up when OpenCode exposes an LSP runtime/registration API.
  • Formatter: v2 supports static formatter configuration, but the v2 plugin context exposes no formatter transform. Do not silently pretend the v1 auto-registration still works. Document the exact native v2 formatter.sema configuration snippet and decide whether the formatter plugin option is removed/deprecated or only applies to the v1 compatibility path.
  • MCP config: v2 uses mcp.servers in file configuration, while the plugin should use the documented MCP transform API.

Documentation and release work

  • Update the README install/configuration examples from v1 plugin tuple syntax to v2 plugins object syntax.
  • Document the plugin ID, supported OpenCode versions, v1 support policy, every option/environment variable, and the v2 LSP/formatter limitations above.
  • Add native v2 configuration examples for the manual Sema formatter and future LSP declaration.
  • Add a changelog entry that clearly lists any removed or deferred behavior. Publish as a breaking major release if v1 support is dropped.

Acceptance criteria

  • A package installed through native v2 plugins configuration appears in opencode plugin list with ID sema.
  • The v2 MCP transform registers sema mcp with the resolved binary and preserves a user-defined sema MCP server.
  • path and the two environment toggles retain their documented precedence and behavior.
  • The bundled Sema guide is model-visible in a v2 session when enabled and absent when disabled.
  • The missing-binary path emits a non-fatal warning.
  • Tests cover the v2 API directly, including reload/unload behavior for any resources the plugin owns. Retain and run v1 compatibility tests if v1 remains supported.
  • CI passes format check, typecheck, test, and build; validate the packed/installed package with a real v2 OpenCode project, not only a workspace link.
  • README and changelog document the final v1 policy and the LSP/formatter limitations.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions