Verified live 2026-07-09 · opencode 1.17.5 · nika 0.98.0.
opencode reads AGENTS.md natively — so the project
scaffold IS the integration:
nika init # writes AGENTS.md + editor rules + the authoring skillThat one command teaches any opencode session the house law: author →
nika check → run budget-capped → nika trace verify. Division of labor:
opencode writes code; Nika runs the repeatable work as a checkable file
with receipts.
For schema/validation answers without shell round-trips, add the read-only
oracle to opencode.json at the project root — nika wire opencode writes
it for you (0.99+), or copy opencode.json from this
folder:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"nika": {
"type": "local",
"command": ["nika", "mcp"],
"enabled": true
}
}
}Two facts we verified live so you don't have to:
- opencode prefixes MCP tool names with the server key — in-session the
oracle's tools appear as
nika_nika_check,nika_nika_explain, … A prompt that says "callnika_check" verbatim will miss; say "the nika tools". - The deterministic check is
opencode mcp list→✓ nika connected. Trust that line, not a model's enumeration — small local models can invent tool names instead of reading them.
The oracle validates and teaches; running workflows stays on the terminal,
where --max-cost-usd, effect permits and the trace live. Nine tools ride
tools/list and nothing else does — prompts/list is not served at 0.106.0,
so the /nika:* slash commands are a plugin feature, not an MCP one.
An opencode session writing its first .nika.yaml from training data
usually trips on the same three. Each is a refusal at nika check, before
a token is spent — but knowing them saves the round trip:
- The envelope is closed. Thirteen keys,
additionalProperties: false; the two older catch-all value blocks are retired (NIKA-VALUES-001/-002). A parameter the caller supplies is aninputs:declaration, a fixed value is aconst:entry, deployment settings areconfig:, and credentials aresecrets:references.nika check <file> --fixmigrates what it can prove. permits:absent means ZERO authority, not unrestricted. Anexec:, a fetch or a file write with no grant refuses withNIKA-AUTH-006. Pure compute sayspermits: {}; everything else gets the blocknika check <file> --infer-permitsprints.- A builtin usually beats
exec:.nika catalog --toolslists what aninvokereaches with no MCP server at all — HTTP, files, JSON, hashing, charts.nika check --native-strictfails the file on anexec:a builtin already covers.