Skip to main content
@obversa/engine-opencode-cli runs one engine attempt through the opencode command-line tool, in a fresh process. Use it to put a model from any provider OpenCode runs into a seat, which gives a review panel a third model family. The plugin runs OpenCode clean by default: with your own home folder and your OpenCode login, but with an empty config folder in place of yours, so your OpenCode settings stay out. Set clean: false to run it the way you run it, with your own config folder too. OpenCode loads the repository’s instruction files under its own rules. The plugin adds only what the step needs, through OpenCode’s own config: the tools and permission rules the step declares, no autoupdate and no sharing. Every other tool is set to ask, so OpenCode turns down each call to it and the tool doesn’t run. Free models explains why.

Install

Included in @obversa/obversa.

Requirements

  • OpenCode CLI 1.18.23, the version the plugin is tested with, at an absolute path you pass as executable. The plugin refuses any other version.
  • OpenCode signed in to your model’s provider, or login data you pass in auth.
  • Any model OpenCode runs, free models such as opencode/big-pickle included. Free models says what they cost.

Free models

OpenCode’s free models refuse any run whose config turns a tool off or denies a permission. Their message is “OpenCode’s free tier can only be used from within OpenCode”. So the plugin does neither. It sets each tool the step doesn’t declare to ask. A declared tool the step limits to a pattern, such as Bash(git status), is set to ask for everything else. A free model gives up nothing for this. opencode run turns down every ask, because nobody is there to answer it. The plugin never passes the flags that would approve them, such as --auto. So a tool the step doesn’t declare never runs, and a step’s limits hold the same way on a free model as on a paid one. What it costs: the model sees all of OpenCode’s tools, not only the ones the step declares. When it calls one the step doesn’t declare, OpenCode turns the call down and tells the model, and the model carries on with the step.

Identity

The plugin reports the provider and model family of the model each request names, read from the provider/model string with modelIdentity: anthropic/claude-sonnet-4-5 is reported as provider anthropic and family claude. The identity you pass to the constructor is a claim about what the instance serves, and a request whose model disagrees with it is refused before anything runs.

Quickstart

opencode(model, { executable }) is the seat helper a workflow() role takes, and resolveCommandExecutable finds the absolute path when the file runs:
examples/teams/threshold-panel.ts (excerpt)
new OpenCodeCliEngine(options) is the same engine without the seat identity:
examples/safe-node-attempt.ts (excerpt)
Structured results depend on the model following an instruction the plugin adds: start the final answer with the line OBVERSA_STRUCTURED_RESULT_V1, then one JSON value. The job’s own parser reads that marked text part.

Options

auth and environment

The child gets your own environment, so OpenCode uses your own login. auth is provider-keyed login data that OpenCode uses instead of the logins you stored with opencode auth login. opencode(model, options) takes the same auth option. environment sets more values on top of your environment. Names that start with OPENCODE_ are refused.

clean

true points OpenCode at a new config folder for each OpenCode process, holding only an empty AGENTS.md, and removes it afterwards. Your own settings, plugins, agents, MCP servers and global instruction files stay out, ~/.claude/CLAUDE.md included. The repository’s own config and instruction files still apply. OpenCode’s data folder, which holds your login, stays yours. opencode(model, options) takes the same clean option. Its row in the engines table: runs on your setup, clean mode available, read-only held in both modes. Clean mode moves the whole config folder (XDG_CONFIG_HOME), so commands the step runs also start without their settings in it, such as the GitHub CLI’s login. A config folder you set in OPENCODE_CONFIG_DIR stays out too. Your own skills in ~/.claude/skills and ~/.agents/skills still load in clean mode, because OpenCode’s switch that skips them also skips the repository’s own skills.

The rest

Errors

  • A version other than 1.18.23 refuses the run.
  • A request whose model disagrees with identity is refused before anything runs.
  • A symlink in the workspace that points outside it refuses a step that can read or change files.
  • EngineError kinds as the API lists them.

API

  • opencode(model, options): a TeamSeat for a workflow role. Quickstart.
  • OpenCodeCliEngine: the engine class. OpenCodeCliEngineOptions, OpenCodeCliIdentity, OpenCodeSeat, OpenCodeSeatOptions, OpenCodeInvocation: its types.
  • buildOpenCodeInvocation: the invocation builder, exported for tests.

Next steps