Connectors

OpenCode

The OpenCode connector wires DefenseClaw into opencode via a dependency-free JavaScript bridge plugin auto-loaded from ~/.config/opencode/plugins/, whose tool.execute.before hook blocks risky tool calls by throwing.

The OpenCode connector wires DefenseClaw into opencode. Unlike the shell-hook connectors, opencode has no command-hook config surface — it auto-loads JavaScript/TypeScript plugins from ~/.config/opencode/plugins/ at startup. DefenseClaw installs a single, dependency-free bridge plugin (defenseclaw.js) there. The plugin's tool.execute.before hook forwards every tool call to the local DefenseClaw gateway and throws — aborting the tool, exactly like opencode's own .env-protection example — whenever the gateway returns a block decision. opencode continues to talk directly to its configured upstream model provider; DefenseClaw never inserts an LLM proxy.

Three commands against one opencode session (v1.17.3) with the DefenseClaw bridge plugin loaded: (1) `echo hello` runs through as action=allow / severity=NONE and prints `hello`; (2) `chmod 777 /tmp/dc_test` trips a CRITICAL finding → the bridge's tool.execute.before hook throws new Error(reason), so opencode aborts the tool and strikes the command out without ever running it; (3) `cat /etc/shadow` raises another sensitive-file finding. Each tool.execute.before / tool.execute.after event streams into the Splunk Connector Activity dashboard filtered to connector=opencode on the right.

No opencode.json edit, no shell shim. Local plugins under ~/.config/opencode/plugins/ are loaded automatically, so installing the connector is just writing one file. The bridge uses the runtime's global fetch, so it needs no npm dependencies (and never triggers a bun install). The JavaScript plugin is supported on macOS and Linux. The DefenseClaw OpenCode integration is not certified on Windows.

Native Windows x64 setup rejects this connector; use a supported macOS or Linux host.

Setup

defenseclaw setup opencode                # observe (default) - record only
defenseclaw setup opencode --mode action  # block on policy hits by throwing

This connector is global/user-scoped only. DefenseClaw writes the bridge plugin to ~/.config/opencode/plugins/defenseclaw.js (owner-only, 0o600, because it carries the gateway token) with the gateway address, token, and fail mode substituted in at setup time. There is no proxy-enforcement path for OpenCode — blocking happens plugin-side by throwing inside tool.execute.before.

setup opencode is the dedicated OpenCode alias. See the quick-alias reference for its common setup options and full guardrail setup for advanced scanner and judge configuration.

Version contract

The current contract is opencode-hooks-v1 (the plugin API is documented as a stable contract rather than a versioned floor, so the contract is unbounded — min 0.0.0). tool.execute.before is the only blockable event; tool.execute.after is observe-only telemetry.

Lifecycle events

EventWhen it firesDefenseClaw roleAction verdict → behavior
tool.execute.beforeRight before a tool (bash, read, edit, …) executesInspect tool args; intercept risky commandsblock → gateway returns {decision: "deny", reason}; the bridge throws new Error(reason), aborting the tool
tool.execute.afterImmediately after a tool returnsCapture diagnostics / flag secrets in output. Cannot block — tool already ran.Observe-only (fire-and-forget; never adds latency)

opencode has no hook-driven ask or context-injection surface, so confirm verdicts fall back to allow and findings on tool.execute.after are telemetry only.

The bridge plugin

DefenseClaw writes a single managed plugin file. Its tool.execute.before resolves the gateway verdict before throwing, so a fail-open transport error never turns into an accidental block:

"tool.execute.before": async (input, output) => {
  const verdict = await defenseclawPost("tool.execute.before", input.tool, output.args, cwd);
  if (verdict) throw new Error(verdict.reason); // block: aborts the tool
}

When the gateway is unreachable, the bridge honors the configured fail mode: FAIL_MODE=closed throws (fail closed); FAIL_MODE=open allows. The bridge's thrown Error is authoritative for tool.execute.before.

Local surfaces

defenseclaw.js

DefenseClaw v1 governs opencode tool execution via the bridge plugin. opencode's MCP servers live in opencode.json; defenseclaw mcp list --connector opencode, defenseclaw mcp set <name> --connector opencode, and defenseclaw mcp unset <name> --connector opencode read or update the top-level mcp map. For local MCP servers, mcp set refuses commands outside trusted install prefixes unless you add the directory to DEFENSECLAW_TRUSTED_BIN_PREFIXES or pass --force-untrusted-command for that one write, because OpenCode will execute the stored command. Skills / rules / plugins / agents surfaces remain unsupported and their panels are hidden while claw.mode=opencode.

Hook capabilities

Block events

  • tool.execute.before

Native ask events

None — confirm verdicts are downgraded with the raw action preserved.

Disable

defenseclaw guardrail disable --connector opencode --yes

Teardown removes the managed ~/.config/opencode/plugins/defenseclaw.js when it is unchanged since setup. If the operator hand-edited the file, teardown leaves it in place and defenseclaw doctor surfaces the lingering managed plugin. No tombstone is needed: opencode re-reads the plugins directory on each startup, so removing the file stops it loading.