~/groundwork

OpenCode

Groundwork's OpenCode adapter adds commands, subagents with permissions, and a plugin for guards and session-start orientation. It needs OpenCode 2.x (tested with 2.0.16 and 2.0.18 — the plugin format changed in 2.x, and 1.x-style plugins fail to load).

What init adds

PathWhat it is
.opencode/commands/gw-*.mdOne command per command file; each reads its core file and follows it
.opencode/agents/gw-*.mdOne subagent per role, with permissions
.opencode/plugins/groundwork-guards.jsRuns your guards before each tool call, and tells each session where things stand

OpenCode reads AGENTS.md itself, so no extra rules file is generated.

Subagents with permissions

SubagentPermissionWhy
gw-plannerbash: denyWrites specs and cards; never runs commands
gw-tester—Writes and runs failing tests
gw-implementer—Makes them pass
gw-revieweredit: denyJudges and sends back; can't fix

If you set models with an opencode key, the model is written into each subagent.

Guards

The plugin hooks execute.before for every tool call. When a guard listed in .groundwork/config.json blocks an action, the plugin throws, and OpenCode stops the call. New installs start with no-ai-trailers on; with "guards": [], nothing is blocked.

{ "guards": ["no-ai-trailers"] }

Add a guard's name to the list and put its .mjs file in .groundwork/guards/ — the same guard files work in every adapter, because they're plain Node.

Session start

The plugin also hooks the session's context: it adds the same few lines Claude Code's session-start hook prints (from .groundwork/hooks/session-start.mjs reading HANDOFF.md) to the system prompt, so a new session already knows which card is in progress and what's next. It's read fresh each time, and skipped for Groundwork's own subagents, which get their card from the runner.

Human-only commands

/gw-approve and /gw-reject are ordinary commands whose text says only the human runs them, and the runner is instructed never to run them. Claude Code additionally enforces this at the tool level; OpenCode has no equivalent switch yet, so the guarantee here is the written rule.

On this page