Contributing
March 30, 2026 · View on GitHub
Prerequisites
- Bun v1.0+
- An opencode installation for manual testing
Getting started
git clone https://github.com/devtheops/opencode-plugin-otel
cd opencode-plugin-otel
bun install
Development workflow
Point your local opencode config at the repo so changes are picked up immediately without a build step. In ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["/path/to/opencode-plugin-otel/src/index.ts"]
}
opencode loads TypeScript natively via Bun, so there is no build step required during development.
Commands
| Command | Description |
|---|---|
bun run lint | Run ESLint, including JSDoc formatting checks |
bun run check:jsdoc-coverage | Enforce minimum JSDoc coverage for exported API declarations |
bun run typecheck | Type-check all sources without emitting |
bun test | Run the test suite |
Project structure
src/
├── index.ts — Plugin entrypoint, wires everything together
├── types.ts — Shared types (Level, HandlerContext, Instruments, etc.)
├── config.ts — Environment config loading and log level resolution
├── otel.ts — OTel SDK setup, resource construction, instrument creation
├── probe.ts — TCP connectivity probe for the OTLP endpoint
├── util.ts — Utility functions (errorSummary, setBoundedMap)
└── handlers/
├── session.ts — session.created / session.idle / session.error
├── message.ts — message.updated / message.part.updated
├── permission.ts — permission.updated / permission.replied
└── activity.ts — session.diff / command.executed
Testing locally with a collector
The easiest way to verify telemetry is being emitted is to run a local OpenTelemetry collector:
docker run --rm -p 4317:4317 \
otel/opentelemetry-collector:latest
Then set OPENCODE_ENABLE_TELEMETRY=1 and start opencode. The collector will print received spans and metrics to stdout.
Commit messages
This project follows Conventional Commits. All commits must be structured as:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types
| Type | When to use |
|---|---|
feat | A new feature (triggers a minor version bump) |
fix | A bug fix (triggers a patch version bump) |
perf | A performance improvement |
refactor | Code change that is neither a fix nor a feature |
test | Adding or updating tests |
docs | Documentation only changes |
ci | CI/CD configuration changes |
chore | Maintenance tasks (dependency updates, etc.) |
build | Changes to the build system |
Breaking changes
Append ! after the type or add a BREAKING CHANGE: footer:
feat!: drop support for OTLP HTTP
BREAKING CHANGE: only OTLP/gRPC is supported going forward
Examples
feat(handlers): add support for file.edited event
fix(probe): handle malformed endpoint URL without throwing
docs: update Datadog configuration example
chore(deps): bump @opentelemetry/api to 1.10.0
Submitting changes
- Fork the repo and create a branch from
main:git checkout -b feat/my-feature - Make your changes and ensure
bun run lint,bun run check:jsdoc-coverage,bun run typecheck, andbun testpass - Commit using Conventional Commits format
- Open a pull request with a clear, human-readable title and link any related issues in the description
Releasing
Releases are handled via GitHub Actions. See the release workflow. To cut a release, push a version tag:
git tag v1.2.3
git push origin v1.2.3
The version bump should follow SemVer based on the commits since the last release:
fixcommits → patch (1.0.x)featcommits → minor (1.x.0)BREAKING CHANGEcommits → major (x.0.0)