@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
@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-pickleincluded. 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 toask. 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 theprovider/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)
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.23refuses the run. - A request whose model disagrees with
identityis refused before anything runs. - A symlink in the workspace that points outside it refuses a step that can read or change files.
EngineErrorkinds as the API lists them.
API
opencode(model, options): aTeamSeatfor a workflow role. Quickstart.OpenCodeCliEngine: the engine class.OpenCodeCliEngineOptions,OpenCodeCliIdentity,OpenCodeSeat,OpenCodeSeatOptions,OpenCodeInvocation: its types.buildOpenCodeInvocation: the invocation builder, exported for tests.
Next steps
- A review panel with a threshold: an OpenCode seat on a panel with Codex, with a real run.
- Safe node attempts: the offline example in full.