Skip to content

Plugin Installation

The @obsigna/opencode-plugin package (Tier B) emits one daemon-signed receipt per native OpenCode tool call. For the MCP channel (Tier A), see MCP Proxy.

The plugin holds no key of its own — obsigna-daemon owns the key and signs every receipt (ADR-0010). Initialise it once and start it before launching OpenCode:

Terminal window
obsigna-daemon --init # one-time: generates the Ed25519 signing key pair
obsigna-daemon # start the daemon (listens on a Unix socket)

The plugin reaches the daemon over its default platform socket automatically — no extra flag needed.

Add the package to your project and register it in opencode.json:

Terminal window
npm install @obsigna/opencode-plugin
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@obsigna/opencode-plugin"]
}

OpenCode also loads plugins from .opencode/plugin/. To configure the plugin programmatically, export a configured instance from a file there:

.opencode/plugin/obsigna.ts
import { createObsignaPlugin } from "@obsigna/opencode-plugin";
export const ObsignaPlugin = createObsignaPlugin({
strict: false,
deny: ["read", "glob", "grep", "list"], // skip read-only noise
});

Configure via environment variables (read when the plugin loads):

VariableDefaultMeaning
AGENTRECEIPTS_SOCKETper-OS defaultDaemon socket path
AGENT_RECEIPTS_CHANNELopencodeReceipt channel label
AGENT_RECEIPTS_STRICTfalseRe-throw on emit failure instead of warning
AGENT_RECEIPTS_ALLOWComma-separated tool allow-list (only these emit)
AGENT_RECEIPTS_DENYComma-separated tool deny-list (these never emit)

createObsignaPlugin(config) accepts the same options plus actionMap (per-tool action-type overrides) and debugLog (a custom log sink). Explicit config wins over environment variables.

Default is catch-and-warn (ADR-0025): a tool call is never aborted because the daemon is unreachable; the drop is logged loudly via the configured logger. Because emission is best-effort, a daemon outage produces a chain gapobsigna receipt verify will report it — rather than silently passing. This is honest-operator-grade auditing, not a completeness guarantee.

Set AGENT_RECEIPTS_STRICT=1 to re-throw emit failures from the tool.execute.after hook so OpenCode surfaces a broken audit pipeline.

After running a few OpenCode tool calls (e.g. ask it to run a shell command and edit a file), inspect and verify the receipts:

Terminal window
obsigna receipt list # recent receipts — look for channel: opencode
obsigna receipt show 1 # full fields of receipt #1 by sequence
obsigna receipt verify # walk the hash chain and check every signature

A healthy chain prints an OK summary. If the daemon was down for some calls, verify reports the gap — exactly the honest-operator signal the default posture is designed to surface.

To see both channels together, run an MCP tool too (see MCP Proxy): receipts with channel: opencode (native, from the plugin) appear alongside channel: mcp (from the proxy), all in the same daemon chain.