opencode Plugin
Capture every opencode session as a trace in Neatlogs via its plugin system.
opencode is a standalone CLI coding agent. Neatlogs hooks
into its plugin system: opencode loads the Neatlogs plugin in-process and the
plugin records each turn as its own trace — the assistant turn, tool
executions, token counts, and cost — then ships it to Neatlogs. No init() call
or code changes in your project are required.
Each turn is a separate trace (opened on chat.message, closed on session.idle
after the turn's full tool-loop settles). All the turn-traces of one session are
grouped together in the UI by neatlogs.session.id.
The plugin ships spans with a direct, awaited export on each turn (the same
model as the Claude Code plugin), so traces land
reliably even though opencode run is short-lived. An awaited dispose hook lets
any in-flight span POSTs settle before a short-lived opencode run exits.
What gets captured
Each opencode turn becomes a trace with this span tree:
| Span | What it represents |
|---|---|
| Workflow | opencode.turn — the turn root, with the prompt as input and the final reply as output |
| LLM | One per assistant message — model, provider, token counts, cost, neatlogs.llm.finish_reason, and the assistant text (or the tool call it decided to make) |
| Tool | Each tool execution (read, edit, bash, …) with its input and output |
Every span carries the opencode session id as both neatlogs.conversation.id and
neatlogs.session.id, so all of a session's turn-traces group together in the UI.
Set up (local plugin file)
opencode auto-loads any *.ts under .opencode/plugin/ in your project (or
~/.config/opencode/plugin/ globally). Create a plugin file that re-exports the
Neatlogs plugin:
export { NeatlogsOpencodePlugin as default } from 'neatlogs/opencode';Add a package.json next to your project so opencode can resolve the neatlogs
import:
{
"type": "module",
"dependencies": {
"neatlogs": "^1.1.11"
}
}Then run npm install (or pnpm install).
Once neatlogs is installed as an npm dependency you can alternatively register
it through opencode.json with { "plugin": ["neatlogs/opencode"] }. Use the
neatlogs/opencode subpath — the package root doesn't export the plugin as its
default.
Run
Set your project key in the environment, then use opencode as usual:
export NEATLOGS_API_KEY=YOUR_PROJECT_KEY
# one-shot
opencode run -m openrouter/openai/gpt-4o-mini "Read README.md and summarize it"
# or interactive
opencodeEach turn shows up in Neatlogs as its own trace — LLM spans and tool spans
nested under the opencode.turn workflow root — with all of a session's turns
grouped by neatlogs.session.id.
Configuration
The plugin reads these environment variables:
| Variable | Purpose |
|---|---|
NEATLOGS_API_KEY | Required — your Neatlogs project key |
NEATLOGS_ENDPOINT | Backend base URL (default: https://ingest.neatlogs.com) |
System prompts are captured by the plugin without a separate opt-in environment variable. The workflow label is opencode.
YOUR_PROJECT_KEY is the same Neatlogs project API key you use for the SDK —
opencode sessions land in that project alongside your application traces.
