OpenCode Integration
SigmaShake integrates with OpenCode (sst/opencode) in three complementary layers:
- MCP server — OpenCode calls
ssg_*tools to evaluate tool calls, search the Hub, and run diagnostics - In-process plugin hook — the
.opencode/plugins/ssg-governance.jsplugin intercepts every tool call viatool.execute.beforebefore it executes - AGENTS.md governance block — instructs the model to use the
ssg_evaluateprotocol on every action
All three are written by a single command.
Quick setup
ssg init --client=opencode
This writes:
opencode.json— adds anmcp.ssg-governanceentry (type: "local") and apermissionblock that transpiles deny/ask rules from your.rulesfiles into OpenCode's native per-tool policy. Existing unrelated keys are preserved..opencode/plugins/ssg-governance.js— the in-process plugin whosetool.execute.beforehook shellsssg hook opencode(fail-closed; returns an exit-1 block on DENY or FORCE verdicts). Tested on OpenCode 1.15.0+.AGENTS.md— appends anSSG_GOVERNANCE_START/SSG_GOVERNANCE_ENDgovernance block that OpenCode auto-loads at the project root. Idempotent; a pre-existing file is left intact except for that block.
Restart OpenCode once after running ssg init so it picks up the MCP server and plugin.
Plugin install methods
Three equivalent ways to get the plugin file:
| Method | When to use |
|---|---|
ssg init --client=opencode | Normal path — writes all three layers at once |
ssg plugins emit opencode > .opencode/plugins/ssg-governance.js | Update the plugin file only, without re-running full init |
| CDN download (see below) | Machines without ssg on PATH yet |
CDN download:
curl -fsSL https://download.sigmashake.com/plugins/opencode/latest/ssg-governance.js \
-o .opencode/plugins/ssg-governance.js
Versioned builds are available at:
https://download.sigmashake.com/plugins/opencode/<version>/ssg-governance.js
A latest.json pointer at /plugins/opencode/latest.json identifies the current version string.
The plugin and the CLI binary are free to download. However, the plugin shells ssg hook opencode at runtime — a local ssg binary on PATH with an active SigmaShake subscription is required for governance to function. The ssg daemon fails closed without a license; tool calls are blocked, not silently allowed.
To override fail-closed behavior during debugging:
SSG_HOOK_FAIL_OPEN=1 opencode
This env var makes the hook fail-open (allow) on any
ssgerror. Do not use it in production.
How the enforcement layers interact
OpenCode calls a tool
↓
tool.execute.before (plugin hook)
↓
ssg hook opencode ←── evaluates against your .rules files
↓
ALLOW / LOG → tool executes normally
ASK → tool pauses; dashboard prompts for human approval
DENY / FORCE → plugin throws; OpenCode sees a blocked call
The MCP server (ssg_evaluate) provides the same verdict path for tool calls that the model initiates explicitly via MCP. This is also the only enforcement path for tool calls inside task-spawned subagents — see the caveat below.
Known caveat: subagent tool calls
Per sst/opencode#5894, tool.execute.before does not fire for tool calls made inside task-spawned subagents. The in-process plugin hook only covers tool calls in the top-level agent context.
To govern subagent tool calls, rely on the MCP path: the ssg_evaluate tool is callable from within subagent context and evaluates against the same ruleset.
MCP tools
With the MCP server connected, OpenCode can call SSG tools autonomously:
| Ask OpenCode | Tool |
|---|---|
| "Set up SigmaShake for my project" | ssg_onboard |
| "Check if governance is working" | ssg_doctor |
| "Find rules for this project type" | ssg_hub_search |
| "Block writes to production config" | ssg_write_rule |
See MCP Server for the complete tool reference and token budget.
opencode.json configuration
The permission block written by ssg init follows OpenCode's last-match-wins ordering: a catch-all "*" entry comes first, then specific overrides derived from your .rules files:
{
"mcp": {
"ssg-governance": {
"type": "local",
"command": "ssg",
"args": ["mcp-server"],
"env": {
"SSG_CLIENT": "opencode"
}
}
},
"permission": {
"bash": "ask",
"edit": "allow",
"write": "allow",
"read": "allow"
}
}
The permission block is regenerated from your active .rules files each time you run ssg init. Existing non-SSG keys in opencode.json are left unchanged.
Human approval flow (ASK rules)
When a rule uses ASK, the plugin hook pauses the tool call and the SSG daemon queues a decision:
- The tool call is held by the plugin
- The dashboard at
http://localhost:5599shows the queued decision - You approve or deny
- OpenCode resumes with the result
Start the dashboard before using ASK rules:
ssg serve
Example rules for OpenCode
Require approval for task spawning
rule require-approval-tasks {
enabled true
priority 90
severity error
ASK agent
MESSAGE "OpenCode task spawn detected — requires approval."
PROMPT "Allow this subagent task?"
}
Block writes to production config
rule block-prod-config-writes {
enabled true
priority 100
severity error
DENY write
IF path GLOB "**/config/production*"
OR path GLOB "**/.env.production"
MESSAGE "Direct writes to production config are blocked."
}
Log all shell command executions
rule log-shell-execs {
enabled true
LOG execute
MESSAGE "Shell command logged."
}
Tool capability mapping
| OpenCode tool | SSG capability |
|---|---|
bash, shell, run | execute |
edit, write, apply_patch, create | write |
read | read |
grep, glob, list | search |
webfetch, websearch, fetch | network |
task | agent |
Troubleshooting
Plugin not intercepting tool calls
Confirm the plugin file exists and is valid JavaScript:
ls .opencode/plugins/ssg-governance.js
node --check .opencode/plugins/ssg-governance.js
Re-emit from your local binary if it is missing or stale:
ssg plugins emit opencode > .opencode/plugins/ssg-governance.js
Restart OpenCode after placing the file.
ssg hook opencode returning errors
Run the hook manually to see the raw output:
echo '{"tool":"bash","input":{"command":"echo test"}}' | ssg hook opencode
Check that ssg is on PATH and a license is active:
ssg status
ssg doctor
MCP tools not visible in OpenCode
Verify the opencode.json has the mcp.ssg-governance entry and that ssg mcp-server starts cleanly:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | ssg mcp-server
Restart OpenCode — MCP connections initialize at startup.
Subagent tool calls not governed
This is a known upstream limitation (sst/opencode#5894). The tool.execute.before plugin hook does not fire inside task-spawned subagents. Use the ssg_evaluate MCP tool from within subagent context as the enforcement path until upstream resolves this.
Related
- Client Adapters — Full adapter reference
- MCP Server — Complete MCP tool reference
- Rule Syntax — Full rule language reference
- Writing Rules — Best practices and patterns
- Dashboard — Real-time approval and audit UI