Logging
Four orthogonal knobs, the env-var overrides, and the startup diagnostics block.
Configure via opencode.jsonc (launch-method-independent) or env vars
(temporary override for a single process). The plugin has four orthogonal
knobs:
| Field | Values | Default | Effect |
|---|---|---|---|
file |
true | false |
false |
Persist log entries to disk |
dir |
path string | ~/.local/share/opencode-claude-code/ |
Custom file location |
mode |
"silent" | "debug" |
"silent" |
TUI policy |
level |
"debug" | "info" | "notice" | "warn" | "error" |
"info" |
Minimum level to emit |
Rails-style threshold: anything below level is dropped before either
destination decides what to do. mode: "silent" routes DEBUG/INFO/NOTICE
to file only and lets WARN/ERROR bubble in the TUI (they always do).
mode: "debug" additionally echoes every emitted level to the TUI (which
opencode surfaces as warning bubbles).
logging is an ordinary provider option, so it goes under provider.claude-code.options like every other one. Keying it on the package name instead is the common mistake: opencode accepts that config without complaint and the plugin never reads it, so you get no log and no error.
Recommended dev setup, capturing an audit trail to disk while keeping the TUI quiet:
{ "provider": { "claude-code": { "options": { "logging": { "file": true } } } }}The snippets below abbreviate to the logging value alone; each one belongs at that same path.
Full firehose for deep debugging (every DEBUG stream event captured):
"logging": { "file": true, "level": "debug" }Live TUI noise (everything echoes to opencode’s stderr → warning bubbles):
"logging": { "file": true, "mode": "debug" }Env-var overrides
Set explicitly to override config for one process, which is useful for one-off
debugging without editing opencode.jsonc:
OPENCODE_CLAUDE_CODE_LOG_FILE=1 opencode # file onOPENCODE_CLAUDE_CODE_LOG_FILE=0 opencode # file off (overrides config:true)OPENCODE_CLAUDE_CODE_LOG_DIR=/tmp/cc opencode # custom dirOPENCODE_CLAUDE_CODE_LOG_LEVEL=debug opencode # capture every levelDEBUG=opencode-claude-code opencode # promote to mode:"debug"Boolean env vars accept 1/true/on/yes for on and 0/false/no/off for
off; empty / unset falls through to config. Invalid level values fall
through to config.
Startup diagnostics
Once per process, right after the provider(s) register, the plugin logs a
single NOTICE: claude-code plugin ready line summarizing everything worth
knowing before you start debugging anything else:
OPENCODE_CLAUDE_CODE_LOG_FILE=1 opencodegrep "plugin ready" ~/.local/share/opencode-claude-code/plugin.log{ "plugin": "0.11.1", "opencode": "1.18.5", "cwd": { "resolved": "/Users/you/code/app", "source": "process" }, "providers": ["claude-code-default", "claude-code-work"], "accounts": ["default", "work"], "proxyTools": ["Bash", "Edit", "Write", "WebFetch", "Task"], "mcpServers": ["github", "slack"], "permissionPresets": [ { "provider": "claude-code-default", "preset": "none", "applied": false, "overrides": [] }, { "provider": "claude-code-work", "preset": "read-only", "applied": true, "overrides": ["skipPermissions: forced to false; ..."] } ], "interactiveTransport": false, "anthropicApiKeyInEnv": false, "claudeCli": { "path": "claude", "version": "2.1.211 (Claude Code)" }}Reading it:
cwd.sourceis which rule picked the working directory Claude will be spawned in:configured(you pinnedoptions.cwd),process(normal),captured(process.cwd()was unusable and opencode’s project directory rescued it, the macOS GUI-launch case), orunresolved(neither worked). The per-session tier thatopencode serveuses is resolved per call and so cannot appear here; this line mirrors the synchronous order only.claudeCli.versionreadingnot detectedmeans theclaudebinary at that path didn’t answer--version, which also disables version-gated flags like--thinking-display.mcpServersis the on-disk merge, before opencode’s runtime toggles are applied (those aren’t settled yet at startup).permissionPresetsis one row per provider rather than a single value, because a preset is a safety posture and two accounts can be configured with different ones.presetis the configured name ornone;appliedis false fornoneand for a name the plugin does not recognise, which applies nothing at all;overridesare the operator settings the preset replaced, the same lines logged at NOTICE when it was applied.opencodeis read from the running opencode binary (--version), since opencode still does not hand its version to plugins. It readsunknownwhen opencode is run from source rather than as the packaged binary.
This block is logged once, to a file that is off by default. For the same
fields plus live process and proxy state, without enabling logging, run
/claude-code-doctor in the session.
Default behavior (no config, no env)
Nothing persists; only WARN and ERROR bubble in the TUI. The plugin doesn’t accrete a log file on every user’s disk by default. Opt in when you need to inspect auto-continue decisions, broker state, or other plugin internals.
