WakaTime plugin for OpenCode V2 - Track your AI coding activity, lines of code, and time spent.
Inspired by claude-code-wakatime.
Tip
Also check out codex-wakatime for OpenAI Codex CLI!
Important
This version of the plugin targets the V2 plugin API (Plugin.define from @opencode-ai/plugin@next).
For the V1 plugin API, use opencode-wakatime@1.x.
- Automatic CLI management - Downloads and updates wakatime-cli automatically
- Detailed file tracking - Tracks file reads and modifications (edit, write, apply_patch)
- AI coding metrics - Sends
--ai-line-changesfor WakaTime AI coding analytics - Rate-limited heartbeats - 1 per minute per project to avoid API spam
- Session lifecycle - Sends final heartbeat on session idle/end
Ensure you have a WakaTime API key configured in ~/.wakatime.cfg
(or $WAKATIME_HOME/.wakatime.cfg when WAKATIME_HOME is set):
[settings]
api_key = waka_your_api_key_hereYou can get your API key from WakaTime Settings.
In case of manual install, the plugin will automatically download wakatime-cli if not found. However, you can also install it yourself:
macOS:
brew install wakatime-cliOther platforms: Download from WakaTime releases.
opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugins": ["opencode-wakatime"]
}Note the V2 config key is plugins (the V1 key was plugin).
npm i -g opencode-wakatime
opencode-wakatime --installThis installs the plugin to ~/.config/opencode/plugins/wakatime.js.
To update, run the same commands again.
git clone https://github.com/angristan/opencode-wakatime
cd opencode-wakatime
npm install && npm run build
node bin/cli.js --installThe plugin will be automatically loaded by OpenCode - no configuration needed.
The plugin hooks into OpenCode V2's plugin API:
flowchart TB
subgraph OpenCode["OpenCode V2"]
A[Tool Execution<br/>read, edit, write, apply_patch] --> H1[tool.execute.after hook]
B[Session Events<br/>idle, deleted] --> H2[event stream]
end
subgraph Plugin["opencode-wakatime Plugin"]
H1 --> P1[Extract File Changes<br/>path, additions, deletions]
P1 --> Q[Heartbeat Queue]
Q --> P2[Process Queue]
P2 --> R[Rate Limiter<br/>1 per minute per project]
H2 --> P3[Flush Final<br/>Heartbeat]
P3 --> R
end
subgraph WakaTime["WakaTime"]
R --> CLI[wakatime-cli]
CLI --> API[WakaTime API]
API --> D[Dashboard<br/>AI Coding Metrics]
end
| Hook | Purpose |
|---|---|
tool.execute.after |
Tracks completed tool executions (edit, write, read, apply_patch) |
event stream |
Tracks session.idle / session.deleted for final heartbeats |
| Tool | Data Extracted |
|---|---|
read |
File path (from input path or result display.path) |
edit |
File path, additions, deletions (from result files metadata or input path) |
write |
File path (from input path; new-file flag when exists metadata is present) |
apply_patch |
File paths and additions/deletions per file (files metadata) |
Tool paths are read from the tool input (path/filePath) because current
V2 builds return minimal result metadata for read and write. Line counts
are taken from result metadata when available (files entries for
edit/apply_patch).
See Migration notes and limitations for tools that were removed in V2 and can no longer be tracked.
Each heartbeat includes:
- Entity: File path being worked on
- Project folder: Session working directory
- AI line changes: Net lines added/removed (
additions - deletions) - Category: "ai coding"
- Plugin identifier:
opencode-<client>/<version> opencode-wakatime/<version>(e.g.opencode-cli/0.0.0-next-17394 opencode-wakatime/2.0.0)
By default, plugin files are stored in ~/.wakatime/.
When WAKATIME_HOME is set, the same files are stored in $WAKATIME_HOME/.
| File | Purpose |
|---|---|
opencode.log |
Debug logs (enabled via debug=true in ~/.wakatime.cfg) |
opencode-{hash}.json |
Per-project state (last heartbeat timestamp) |
opencode-cli-state.json |
CLI version tracking |
wakatime-cli-* |
Auto-downloaded CLI binary |
This section documents what changed when porting the plugin from the V1 to the V2 plugin API, and which V1 features could not be carried over.
| V1 | V2 |
|---|---|
export default (ctx) => hooks |
Plugin.define({ id, setup }) |
event hook (message.part.updated) |
ctx.tool.hook("execute.after") for tools, ctx.event.subscribe() for the event stream |
chat.message hook |
Removed from the V2 plugin API; heartbeat processing now runs directly on tool completion |
ctx.project.worktree / ctx.worktree |
Removed from the context; the session directory is fetched via ctx.session.get() |
OpenCode version via internal HTTP client (/global/health) |
Provided by the context as ctx.app.version (no more version cache file) |
plugin config key |
plugins config key |
~/.config/opencode/plugin/ |
~/.config/opencode/plugins/ (auto-discovered) |
-
batchtool tracking - The V1batchtool executed child tools in parallel and each child emittedmessage.part.updatedevents that the plugin tracked. In V2 the batch tool was replaced by the CodeModeexecutetool, which only runs MCP tools and reports child calls as{ tool, status, input }in its result metadata — no file paths or diffs. File-level tracking is therefore not possible forexecute; it is skipped. -
multiedittool tracking - Themultiedittool no longer exists in V2; multi-file edits go throughapply_patch, which is fully tracked. -
patchtool tracking - Renamed toapply_patchin V2; it now returns per-file additions/deletions in result metadata, which is tracked. -
chat.messageactivity trigger - The V1chat.messagehook fired on chat activity to flush queued heartbeats. The V2 plugin API has no equivalent hook, so heartbeats are flushed directly after each tracked tool execution and onsession.idle/session.deleted. Behavior is equivalent: heartbeats are sent at most once per minute per project, and always flushed when a session ends. -
Blocking hooks - Tool hooks run inside the server's tool execution path. The plugin therefore keeps
execute.afterfully synchronous and runs all async work (session lookup, heartbeat CLI spawns) in background tasks, so a slowwakatime-clior unreachable session API can never stall tool execution or freeze the client (especially when the server is embedded in the TUI process).
# Install dependencies
npm install
# Type check
npm run typecheck
# Build
npm run build- Check your config file syntax (
opencode.jsonc) - Verify the plugin path is correct
- Check logs at
~/.wakatime/opencode.log
- Verify API key in
~/.wakatime.cfg - Check if wakatime-cli is working:
wakatime-cli --version - Enable debug logging and check
~/.wakatime/opencode.log(or$WAKATIME_HOME/opencode.logwhen set)
- Check network connectivity
- Verify write permissions to
~/.wakatime/(or$WAKATIME_HOME/when set) - Manually install:
brew install wakatime-cli
MIT