@kimchi-by-castai/opencode-otel-plugin
v1.3.0
Published
OpenCode OTEL plugin for Kimchi - sends usage telemetry
Readme
OpenCode OTEL Plugin for Kimchi
Sends usage telemetry and productivity metrics from OpenCode to the Kimchi service.
OpenCode version 1.2.20+
Installation
Option 1: NPM package (recommended)
Add to your ~/.config/opencode/opencode.json:
{
"plugin": ["@kimchi-by-castai/opencode-otel-plugin@latest"]
}To pin to a specific version:
{
"plugin": ["@kimchi-by-castai/[email protected]"]
}Set environment variables (see Configuration section below), then restart OpenCode.
Option 2: Local plugin
- Copy
plugin.tsto your OpenCode plugins directory:
mkdir -p ~/.config/opencode/plugins
cp plugin.ts ~/.config/opencode/plugins/otel.tsSet environment variables (see Configuration section below)
Restart OpenCode.
Option 3: Project-level plugin
- Create the plugins directory in your project:
mkdir -p .opencode/pluginsCopy
plugin.tsto.opencode/plugins/otel.tsSet the environment variables (same as above)
Configuration
Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| OPENCODE_ENABLE_TELEMETRY | Yes | Set to 1 to enable telemetry |
| OPENCODE_OTLP_ENDPOINT | Yes | Kimchi logs ingest endpoint URL |
| OPENCODE_OTLP_METRICS_ENDPOINT | Yes | Kimchi metrics ingest endpoint URL |
| OPENCODE_OTLP_HEADERS | Yes | Authorization header with your Kimchi API key |
Example Environment Variables
Add these to your shell config (~/.zshrc, ~/.bashrc, etc.):
# Enable the plugin
export OPENCODE_ENABLE_TELEMETRY=1
# Kimchi endpoint for log ingestion (api_request events)
export OPENCODE_OTLP_ENDPOINT=https://api.cast.ai/ai-optimizer/v1beta/logs:ingest
# Kimchi endpoint for metrics ingestion (productivity metrics)
export OPENCODE_OTLP_METRICS_ENDPOINT=https://api.cast.ai/ai-optimizer/v1beta/metrics:ingest
# Authorization header with your Kimchi API key
export OPENCODE_OTLP_HEADERS="Authorization=Bearer YOUR_API_KEY_HERE"After adding, restart your shell or run source ~/.zshrc.
Provider Configuration
The plugin reads provider information from your OpenCode config (~/.config/opencode/opencode.json). Ensure your provider key matches one of the valid values below.
Valid Provider Values
| Provider Key | Description |
|--------------|-------------|
| openai | OpenAI |
| anthropic | Anthropic (Claude) |
| azure | Azure OpenAI |
| azure_ai | Azure AI |
| gemini | Google Gemini |
| vertex_ai-language-models | Vertex AI Gemini |
| vertex_ai-anthropic_models | Vertex AI Anthropic |
| groq | Groq |
| mistral | Mistral |
| codestral | Codestral |
| cohere_chat | Cohere |
| anyscale | Anyscale |
| openrouter | OpenRouter |
| databricks | Databricks |
| perplexity | Perplexity |
| hosted_vllm | Hosted vLLM |
| bedrock | AWS Bedrock |
| ai-enabler | Kimchi (serverless models) |
Important: If your provider key does not match one of the valid values listed above, the request will be rejected and you will see an error toast notification in OpenCode. Make sure to use a provider key from the list above to ensure your usage data is recorded correctly.
Example OpenCode Config
{
"model": "ai-enabler/glm-5-fp8",
"provider": {
"ai-enabler": {
"npm": "@ai-sdk/openai-compatible",
"name": "Kimchi",
"options": {
"baseURL": "https://llm.cast.ai/openai/v1",
"apiKey": "your-api-key"
},
"models": {
"glm-5-fp8": {
"name": "glm-5-fp8",
"tool_call": true
}
}
}
}
}Data Sent
The plugin sends two types of OTEL data:
1. API Request Logs (to logs:ingest)
Sent for each completed assistant message with token usage.
| Attribute | Description |
|-----------|-------------|
| event.name | Always "api_request" |
| client | Always "opencode" |
| model | Model identifier |
| provider | Provider identifier |
| input_tokens | Number of input tokens |
| output_tokens | Number of output tokens |
| cost_usd | Cost in USD |
| duration_ms | Request duration in milliseconds (always 0 - OpenCode doesn't expose this data) |
2. Productivity Metrics (to metrics:ingest)
Sent as cumulative OTLP Sum metrics with session-level granularity. Metrics are flushed every 30 seconds.
| Metric Name | Dashboard Widget | Description | Attributes |
|-------------|-----------------|-------------|------------|
| claude_code.token.usage | Tokens Used | Cumulative token count per model | session.id, type (input/output), model |
| claude_code.cost.usage | Total Cost | Cumulative cost per model | session.id, model |
| claude_code.commit.count | Git Commits | Detected from git commit bash commands | session.id |
| claude_code.pull_request.count | Pull Requests | Detected from gh pr create bash commands | session.id |
| claude_code.lines_of_code.count | Lines Modified | Lines added/removed from edit, write, patch tools | session.id, type (added/removed) |
| claude_code.code_edit_tool.decision | Edit Decisions | Edit/write/patch tool invocations by tool and language | session.id, tool_name, language, decision, source |
Session Duration
Session duration is derived on the backend from ClickHouse data: for a given session.id, the duration is MAX(created_at) - MIN(created_at) across all productivity metrics. No dedicated session metric is needed.
How Metrics Are Collected
| Dashboard Widget | OpenCode Hook | Detection Method |
|-----------------|---------------|-----------------|
| CLI Sessions | session.created event | Each session gets a unique session.id attribute on all metrics |
| Git Commits | tool.execute.after (bash) | Regex match on git commit commands |
| Pull Requests | tool.execute.after (bash) | Regex match on gh pr create commands |
| Lines Modified | tool.execute.after (edit/write/patch) | Line diff counting from tool args |
| Edit Decisions | tool.execute.after (edit/write/patch) | Count per tool name + inferred language |
| Tokens Used | message.updated event | Accumulated from assistant message token counts |
| Total Cost | message.updated event | Accumulated from assistant message cost |
Troubleshooting
The plugin shows error notifications via OpenCode toasts when issues occur:
Error Toast Messages
- "Invalid provider" - Your provider key is not recognized. Update your
opencode.jsonto use a valid provider key from the list above. - "Telemetry error" - Other errors (network issues, auth failures, etc.)
Debugging Steps
- Verify environment variables are set correctly
- Check your Kimchi API key is valid
- Ensure the provider key in your OpenCode config matches a valid value
- Verify the endpoint URLs are correct
