Skip to main content

OpenCode Integration

SigmaShake integrates with OpenCode (sst/opencode) in three complementary layers:

  1. MCP server — OpenCode calls ssg_* tools to evaluate tool calls, search the Hub, and run diagnostics
  2. In-process plugin hook — the .opencode/plugins/ssg-governance.js plugin intercepts every tool call via tool.execute.before before it executes
  3. AGENTS.md governance block — instructs the model to use the ssg_evaluate protocol on every action

All three are written by a single command.


Quick setup

ssg init --client=opencode

This writes:

  • opencode.json — adds an mcp.ssg-governance entry (type: "local") and a permission block that transpiles deny/ask rules from your .rules files into OpenCode's native per-tool policy. Existing unrelated keys are preserved.
  • .opencode/plugins/ssg-governance.js — the in-process plugin whose tool.execute.before hook shells ssg hook opencode (fail-closed; returns an exit-1 block on DENY or FORCE verdicts). Tested on OpenCode 1.15.0+.
  • AGENTS.md — appends an SSG_GOVERNANCE_START / SSG_GOVERNANCE_END governance 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:

MethodWhen to use
ssg init --client=opencodeNormal path — writes all three layers at once
ssg plugins emit opencode > .opencode/plugins/ssg-governance.jsUpdate 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 ssg error. 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 OpenCodeTool
"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:

  1. The tool call is held by the plugin
  2. The dashboard at http://localhost:5599 shows the queued decision
  3. You approve or deny
  4. 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 toolSSG capability
bash, shell, runexecute
edit, write, apply_patch, createwrite
readread
grep, glob, listsearch
webfetch, websearch, fetchnetwork
taskagent

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.