Plugins

June 26, 2026 ยท View on GitHub

Overview

Zara ships as a single OpenCode plugin (.opencode/plugin/zara.mjs), a composition root that loads 12 domain modules from .opencode/plugin/zara/. Each module hooks into the conversation lifecycle via OpenCode's experimental hooks API. Shared file I/O lives in infra/store.mjs.

This replaced the old layout of 21 individual plugins. Same behavior, fewer files, one entry point.

Domain Modules

ModuleHooksWhat it doesAbsorbed
observetool.execute.before/after, chat.responseTracing, evaluation scoring, guardrails (injection/PII/tool-input), semantic cachemetrics, observability, evaluation, guardrails, cost-optimizer
memorysystem.transform, chat.message, chat.responseAuto-capture (preferences/corrections/constraints to SQLite), knowledge graph context injection, error detectionmemory, reflection, knowledge
flowsystem.transform (conditional), event, chat.messageSession handoff, goals, loops, bedtime ritual, auto-resumeflow, compaction, scratchpad, auto-resume
devtools onlyEngineering principles, sandbox exec, HITL confidencesenior-dev, codebase, hitl
socialsystem.transformLeadership coaching, team knowledge, music playerleadership, team, music
evolvesystem.transform (conditional)Micro-tools, swarm coordination, workflow rulesevolve, swarm, compaction, scratchpad
empathyonEvent, onMessage, injectLongitudinal emotional tracking, sentiment, burnout detection, growth tracking(new)
relationshiponEvent, injectOpen threads, milestones, shared references, emotional bookmarks, persistent stances, identity anchor, temporal awareness(new)
voicesystem.transformAnti-AI writing enforcement, banned word/phrase injection, rotating drift checks(new)
workspacesystem.transform, toolsShared agent memory, cross-agent context propagation(new)
debatetoolsMulti-agent deliberation, position sanitization, context compression(new)
harnessonEvent, injectAutomated self-improvement (failure mining, diagnosis, fix proposal) + security audit on session start(new)
infra(shared)File I/O utilities, path resolution, store.mjs - used by all modules(shared library)

Hook Types

HookWhen it firesToken cost
system.transform (inject)Every turn (before LLM call)Adds to system prompt
chat.messageOn user/assistant messageZero (processing only)
chat.responseOn assistant responseZero (processing only)
eventOn session events (created/ended/compacting)Zero
tool.execute.before/afterAround every tool callZero (processing only)
tools onlyWhen user/LLM calls a toolZero until invoked

Token Budget

Active inject() injections per turn (worst case):

  • memory: ~50-200 tokens (knowledge graph context only; main memory inject via MCP)
  • social: ~15 tokens (one-liner user context + now-playing if active)
  • flow: ~50-200 tokens (only if active session state)
  • evolve: ~100-300 tokens (only if micro-tools/rules exist)
  • empathy: ~15 tokens (only on burnout alert)
  • relationship: ~60-120 tokens (identity anchor + stage + due threads + temporal signals)
  • voice: ~50-80 tokens (hot-path crib + rotating drift check)
  • harness: ~0-100 tokens (only on critical security findings)

Typical total: ~400-600 tokens/turn (most conditionals won't fire).

Adding a Module

  1. Create .opencode/plugin/zara/<name>/index.mjs exporting a create<Name>(config) factory.
  2. Return { onEvent?, inject?, onMessage?, onResponse?, beforeTool?, afterTool?, onCompact?, tools, dispose? }.
  3. Import and register it in zara.mjs (add to the each() dispatch list and tool spread).
  4. Verify: node --check .opencode/plugin/zara/<name>/index.mjs and node --check .opencode/plugin/zara.mjs.