import "github.com/glonlas/aicliobserve/adapter/opencode"
mgr := opencode.New("aicliobserve-receiver")OpenCode uses a plugin system for event delivery. Unlike Claude and Gemini, there is no config mutation API in v1 — plugins must be registered manually.
status, err := mgr.Inspect(ctx, workDir)type OpenCodeStatus struct {
PluginReady bool // plugin config found with receiver?
ReceiverMatches bool // receiver command present in plugins?
ReadyForObserve bool // both above true
Details map[string]any // files_found, plugin_source, config_found
}| Priority | Path |
|---|---|
| 1 | ~/.opencode/plugins.json |
| 2 | ~/.config/opencode/config.json |
| 3 | <workDir>/.opencode/plugins.json |
| 4 | <workDir>/.opencode/config.json |
The library looks for a plugins array with an entry whose command contains
the receiver string:
{
"plugins": [
{ "command": "aicliobserve-receiver" }
]
}Substring matching works — "/usr/local/bin/aicliobserve-receiver --port 9000"
matches receiver "aicliobserve-receiver".
Create or edit ~/.opencode/plugins.json:
{
"plugins": [
{ "command": "aicliobserve-receiver" }
]
}Or project-local at .opencode/plugins.json.
When the OpenCode plugin sends events, pass them to:
evt := opencode.NormalizePluginEvent(sessionID, mode, rawJSON)| Plugin event type | Normalized state |
|---|---|
permission.asked |
waiting_for_user |
session.idle |
turn_complete_waiting |
session.error |
error |
| anything else | nil (ignored) |
package main
import (
"context"
"fmt"
"github.com/glonlas/aicliobserve/adapter/opencode"
"github.com/glonlas/aicliobserve"
)
func main() {
ctx := context.Background()
mgr := opencode.New("aicliobserve-receiver")
// Check plugin readiness
status, _ := mgr.Inspect(ctx, ".")
if !status.ReadyForObserve {
fmt.Println("Register plugin in ~/.opencode/plugins.json:")
fmt.Println(` { "plugins": [{ "command": "aicliobserve-receiver" }] }`)
return
}
// Run session
sv := aicliobserve.NewSupervisor(aicliobserve.WithOpenCodeManager(mgr))
events, _ := sv.Subscribe(ctx)
resp, _ := sv.Launch(ctx, aicliobserve.LaunchRequest{
Adapter: aicliobserve.AdapterOpenCode, WorkDir: ".", PreferHybrid: true,
})
for evt := range events {
if evt.SessionID == resp.SessionID {
fmt.Printf("[%s] %s\n", evt.State, evt.Adapter)
if evt.State == aicliobserve.StateExited { break }
}
}
}