@shodocan/opencode-workflows
v0.3.1
Published
Main-session workflow orchestration runtime for OpenCode v0.2 — the main LLM orchestrates native subagent chains via the built-in task tool.
Readme
@shodocan/opencode-workflows
A dynamic workflows runtime and TUI integration for OpenCode (Shodocan fork). Workflows are JavaScript scripts that orchestrate OpenCode-native subagents at scale — dozens to hundreds of coordinated sessions per run — with a clickable TUI so you can watch every spawned subagent and its logs in real time.
Status: v0 implemented, awaiting real OpenCode load test (T999). 131 unit/integration tests passing; typecheck + build clean. See
docs/artifacts/03-07-2026_workflows-plugin-brainstorm/for the full spec + plan + 3-iteration adversarial review record.
Install
From npm (when published)
# Inside your OpenCode config directory (~/.config/opencode/)
npm install @shodocan/opencode-workflowsFrom source (development / personal-use-first)
git clone [email protected]:Shodocan/opencode-workflows.git
cd opencode-workflows
make install # bun install
make build # bun build server + TUIThe package expects the host OpenCode environment to provide peer dependencies. Do not install these directly — they are supplied by the host:
| Peer dependency | Provided by |
|---|---|
| @opencode-ai/plugin | OpenCode server plugin SDK |
| @opencode-ai/sdk | OpenCode client SDK |
| @opentui/solid | OpenCode TUI runtime |
| solid-js | OpenCode TUI runtime |
If peer dependencies are missing, your package manager may warn. On npm you can silence this with npm install --legacy-peer-deps; on bun it resolves automatically when the plugin is loaded inside OpenCode.
Register in OpenCode
Add the plugin to your OpenCode configuration:
opencode.json (server plugin):
{
"plugin": [
"@shodocan/opencode-workflows"
]
}tui.json (TUI plugin):
{
"plugin": [
"./node_modules/@shodocan/opencode-workflows/src/tui/tui.tsx"
]
}After registration, the workflow tool is visible to the model and the w keymap opens the Workflows panel in the TUI.
Build / test / release
make install # bun install
make build # bun build server + TUI bundles
make typecheck # tsc --noEmit
make test # vitest run
make clean # remove dist/ + caches
make release-dry-run # build + typecheck + test + npm publish --dry-run
make version-patch # bump patch + commit + tag (also: version-minor, version-major)
make publish # build + typecheck + test + npm publish (under @shodocan scope)
make release # version-patch + publish + git push --follow-tagsWorkflow script authoring guide
Workflow scripts are ESM JavaScript (.js) files placed in .opencode/workflows/<name>.js (project-level, committed) or ~/.opencode/workflows/<name>.js (personal, gitignored). Project-level files take precedence.
Script shape
export const meta = {
name: 'my-workflow',
description: 'Short description of what this workflow does',
}
export default async function workflow(ctx) {
const { agent, pipeline, args } = ctx
const result = await agent('Do something useful', {
schema: { type: 'object', required: ['output'], properties: { output: { type: 'string' } } },
})
return result
}Primitives
| Primitive | Signature | Description |
|---|---|---|
| agent(prompt, opts?) | prompt: string, opts?: { label?, agent?, schema?, timeoutMs? } | Spawns an OpenCode subagent session, sends the prompt, waits for completion, parses the result against schema if provided. |
| pipeline(items, fn, opts?) | items: T[], fn: (item, index) => Promise<R>, opts?: { concurrency?, failFast? } | Runs fn over each item with bounded concurrency (default 8). Preserves input order. Failures are caught as { __error } unless failFast is set. |
Idempotency requirement (resume semantics)
When OpenCode restarts (process restart or machine reboot), active workflow scripts are re-executed from the top. Only agent() and pipeline() calls short-circuit on done checkpoints (they return the stored result). Any top-level side effects outside those calls — fetch(), fs.writeFileSync, console.log, database writes — will re-run on every resume.
The runtime injects args.__resuming = true on resume so your script can detect and guard against this:
export default async function workflow({ agent, args }) {
// Guard top-level side effects on resume
if (!args.__resuming) {
// Safe: runs only on first execution
await fetch('https://example.com/hook', { method: 'POST', body: JSON.stringify({ started: true }) })
}
// agent() calls are always safe — they short-circuit on resume
return await agent('Do something')
}Rules for workflow authors:
- Keep top-level side effects idempotent (use
appendFileinstead ofwriteFile, deduplicate with a flag). - Guard side effects with
if (!args.__resuming)when they must not repeat. agent()andpipeline()calls are safe — they always return the stored result on resume.- This is a v0 limitation; a future interpreter with checkpointed side effects will relax this requirement.
Name validation
Workflow names must be kebab-case matching /^[a-z0-9-]+$/. Names containing /, \, .., or null bytes are rejected to prevent path traversal.
peerDependencies resolution
This package declares @opencode-ai/plugin, @opencode-ai/sdk, @opentui/solid, and solid-js as peer dependencies, not regular dependencies. This ensures the host OpenCode environment supplies its own versions and avoids duplicate installs. If you are developing outside OpenCode (e.g., running tests), install them manually:
bun add --dev @opencode-ai/plugin @opencode-ai/sdk @opentui/solid solid-jsExample workflows
Complete ESM example workflow scripts live in examples/workflows/:
examples/workflows/route-audit.js— audits route files for missing auth checks usingctx.agent()andctx.pipeline().examples/workflows/plan-review.js— runs refuter agents over plan sections and aggregates pass/fail verdicts.
These examples demonstrate the full workflow shape: meta export, default async function, resume guards (args.__resuming), {__error} sentinel handling, and pipeline concurrency. They can be imported directly under this package's type: module:
node -e "import('./examples/workflows/route-audit.js').then(m => console.log('OK:', m.meta.name))"To use them at runtime, copy the .js file into your project's .opencode/workflows/ directory.
Related
- OpenCode fork (Shodocan): https://github.com/Shodocan/opencode — this plugin targets the Shodocan fork's plugin SDK and TUI.
- remote-agent-setup: https://github.com/Shodocan/remote-agent-setup — the harness repo this plugin is designed to orchestrate.
Documentation
docs/opencode-ref/— full implementation reference: plugin shape, runtime API, TUI surface, persistence/resume model.docs/artifacts/— brainstorm artifacts, plan spec, implementation plan, and task breakdown.
