Skip to content
Agentic Control Plane

Govern opencode with Agentic Control Plane

See, control, and price every tool call opencode makes — the bash commands, the file edits, the web fetches, and the model calls behind them — from one dashboard. One command, no code changes.

Every tool opencode runs — bash, read, write, edit, webfetch, MCP tools — flows through ACP’s governance plugin before it executes. Logged with identity. Denied when policy says deny. Audited end-to-end.

TL;DR

curl -sf https://agenticcontrolplane.com/install.sh | bash

Three things you get the moment it's running — click any to see it full-size:

ACP tool-surface control table: every tool the agent can call, Allow/Deny per tool
ControlEvery tool opencode can call, one row each — Allow / Deny per tool. Deny-by-default on rm -rf, force-push, and the rest. Enforced at the call, outside the model.
ACP cost-per-run distribution for one agent across many runs, log scale
PriceRoute model calls through the proxy and every one is metered — each run split loop-vs-leaf and plotted across runs, so you see which step is the bill and which runs blow the budget.
ACP session trace: per-call timeline of one agent run with cost and decision
AuditEvery tool + model call in a run, in order — what ran, what it returned, the policy decision, and what it cost. Exportable.

See your first governed call →Free for individuals · full install below

The installer detects opencode (~/.config/opencode or the opencode binary), writes a governance plugin to ~/.config/opencode/plugin/acp-govern.ts, and opens your browser to provision a workspace. Restart opencode and every tool call is governed.

How it works

Unlike Claude Code, Cursor, and Codex — which shell out to a hook script over stdin — opencode ships a first-class plugin system. A plugin is a TypeScript module under ~/.config/opencode/plugin/ (global) or .opencode/plugin/ (project) whose exported hooks run in-process. ACP’s plugin registers two of them:

  • tool.execute.before — fires before any tool runs. The plugin POSTs the tool name, input arguments, and session ID to https://api.agenticcontrolplane.com/govern/tool-use. The server evaluates the seven-layer governance pipeline (immutable rules, delegation chain, scopes, ABAC, rate limits, plan limits, content scanning). If the decision is deny, the plugin throws — which is how opencode blocks a tool call — and the agent sees the reason.
  • tool.execute.after — fires after the tool returns. The plugin POSTs the output (truncated at 200 KB) to /govern/tool-output, where the server scans for PII, prompt injection, and secrets and records the result in the audit log. Best-effort: an audit failure never blocks your work.

The plugin reads your bearer token from ~/.acp/credentials — the same credential every other ACP integration uses, so one install.sh run covers opencode alongside Claude Code, Cursor, and the rest.

What gets installed and where

Path Contents
~/.config/opencode/plugin/acp-govern.ts The governance plugin — TypeScript, no dependencies, ~120 lines
~/.acp/credentials Your bearer token (set after browser OAuth)

The installer is idempotent — it overwrites only acp-govern.ts and leaves any other plugins you’ve written untouched. Running on a machine without opencode is a no-op.

Prefer to install by hand? Drop the plugin into ~/.config/opencode/plugin/acp-govern.ts yourself and set ~/.acp/credentials to your ACP key — the installer does exactly that.

Fail-open by default

If the ACP gateway is unreachable, the plugin allows the call and prints a loud ran UNGOVERNED warning rather than blocking — the same fail-open default as every ACP integration. We never brick an agent you didn’t explicitly set to block. To flip a machine to fail-closed (block when the gateway is unreachable):

echo closed > ~/.acp/failmode      # or: export ACP_FAIL_MODE=closed

Add the cost X-ray

The plugin above governs and audits tool calls — it never sees the model’s token usage, so it can’t show cost. To meter spend, prompt-cache hit rate, and the loop-vs-leaf cost X-ray, route opencode’s model calls through the ACP proxy. opencode is provider-flexible; point its Anthropic-compatible base URL at the ACP proxy and use your ACP key (gsk_...):

// ~/.config/opencode/opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": { "baseURL": "https://api.agenticcontrolplane.com/anthropic/v1" }
    }
  }
}

Set ANTHROPIC_AUTH_TOKEN to your ACP key. Same responses, now metered — and the proxy governs the tool-use blocks the model emits as a second layer. Full walkthrough: Turn on Cost X-Ray.

Setting up policy

The same three policy axes that apply to every harness apply to opencode traffic:

  1. Tool policies (Policies → Tool Policies) — workspace-wide tool allowlist and required scopes.
  2. Agent policies (Policies → Agent Policies) — per-tier rules.
  3. User policies (Policies → User Policies) — overrides per identity.

Most-restrictive wins on conflict. Start in audit mode for a few days to learn what your agents actually do, then switch to enforce mode when patterns are clear.

Limitations

Honest list of what ACP’s opencode integration cannot do today:

  • Tier attribution is coarse. opencode’s tool.execute.before payload carries the tool name and session ID but does not distinguish its build vs plan agents to the plugin, so calls are reported at the interactive tier. We’re tracking richer agent attribution as opencode’s plugin context evolves.
  • Input mutation is deny-or-allow, not rewrite. The plugin can block a call (by throwing) but the audit path is observe-only — it flags findings on the output, it does not redact it.
  • The plugin runs in opencode’s runtime. A machine that can’t reach api.agenticcontrolplane.com fails open by default (see above); air-gapped setups should point ACP_API_BASE at a self-hosted GatewayStack instance.
  • permission.ask is not used. opencode also exposes a permission.ask plugin hook, but it has known reliability gaps upstream; we enforce via tool.execute.before (throw-to-block), which is the dependable path.

Troubleshooting

Plugin isn’t firing. Restart opencode completely — plugins are loaded at startup. Confirm the file is at ~/.config/opencode/plugin/acp-govern.ts.

Every tool call is being blocked. You’re on fail-closed and the gateway is unreachable, or ~/.acp/credentials is missing/expired. Check the credential, or echo open > ~/.acp/failmode to restore the default.

Plugin fires but nothing appears in the dashboard. Confirm the workspace tied to your token — the Activity page is workspace-scoped. Switch workspaces in the top-right dropdown if you have more than one.

  • Claude Code — hook-based governance, the most complete integration
  • Cursor — same hook pattern, different config file
  • OpenAI Codex CLI — Claude-style hooks, currently Bash-only
  • OpenClaw — native plugin, like opencode
  • Turn on Cost X-Ray — meter spend across any harness through the proxy