oc-lens
v0.4.0
Published
Local, read-only analytics dashboard for opencode
Downloads
1,163
Maintainers
Readme
oc-lens
Local, read-only analytics for your opencode history.
[!IMPORTANT] oc-lens opens opencode's SQLite database in read-only mode. It never writes to the database, opencode configuration, or session files. Its only write is your optional model-price configuration at
~/.config/oc-lens/config.json. See SECURITY.md for the enforced guarantees.
opencode web is the browser interface for working with live sessions, and opencode stats is a terminal summary. oc-lens complements them with history analytics: activity and streaks, token and user-priced cost trends, project and agent breakdowns, tool adoption and failures, todos, subagent trees, loop detection, exports, and conversation replay.
Everything runs on your machine. There is no account, cloud sync, or telemetry.
Requirements
- Node.js 22.5 or newer
- An opencode SQLite database (normally
~/.local/share/opencode/opencode.db) - Model prices you enter yourself if you want cost figures
oc-lens is verified against the database schema produced by opencode 1.17.7 (opencode-1.17.7). A schema guard checks required tables and columns before analytics run. If the database is missing, the UI shows the locations it checked. If its schema differs, the UI reports that the database is incompatible and refuses to render potentially wrong numbers; update oc-lens to a compatible release instead of trusting partial results.
Install and run
Run the published CLI without installing it globally:
npx oc-lensThe dashboard binds only to loopback (127.0.0.1), starts on the first free port from 3000, and opens your browser. Available flags:
Usage: oc-lens [options]
Options:
--port <port> Bind exactly this loopback port (default: first free from 3000)
--db <path> Use only this opencode database path
--no-open Do not open a browser
--help, -h Show help
--version, -v Show the package versionExamples:
# Use a specific database without changing it
npx oc-lens --db /absolute/path/to/opencode.db
# Choose an exact port and leave browser opening to you
npx oc-lens --port 4313 --no-openWhen --db is omitted, discovery checks OC_LENS_DB, then $XDG_DATA_HOME/opencode/opencode.db, then ~/.local/share/opencode/opencode.db.
Set up honest cost analytics
opencode's stored cost field is not treated as your bill: some providers report zero and arbitrary providers cannot be priced accurately from a bundled table. oc-lens calculates user cost only from prices you supply.
- Open Settings → Model pricing.
- Review the
providerID/modelIDvalues observed in your database and their token volumes. - Enter your provider's current USD price per one million tokens for input, output, cache-read, and cache-write tokens.
- Save. Cost cards, charts, projects, agents, sessions, replay, and exports use the same local pricing configuration.
Until every model involved has a price, affected totals say not priced or identify unpriced models; they do not silently become $0.00. Provider-reported stored cost remains separately labelled for comparison. Prices stay local in ~/.config/oc-lens/config.json, the product's single sanctioned write path.
Features
- Overview KPIs, recent sessions, project/model breakdowns, and activity heatmap
- Calendar activity, streaks, hourly and weekday patterns
- Searchable/filterable session history and detailed conversation replay
- Project portfolio and per-project activity, model, token, and cost analytics
- Tool rankings, durations, error analysis, MCP usage, skills, adoption, and version history
- Native opencode todo browsing and status filters
- Cost trends by model, project, and agent using your prices
- Agent usage, handoffs, and nested subagent trees
- Loop detection: repeated tool calls, failed retries, and files rewritten back and forth
- Local JSON/ZIP export with cancellation and progress
- Redacted environment settings and editable local pricing
- Empty, sparse, populated, missing-database, and schema-mismatch states
- Persistent light and dark themes
Loop detection
The Loops page answers a question the other pages cannot: where did the agent repeat itself without getting anywhere. Three shapes are reported.
| Kind | What it means | | --- | --- | | Error retry | The same call failed over and over — including a shell command that kept exiting non-zero | | Redundant repeat | The same call succeeded over and over, returning nothing new | | Oscillation | One file rewritten back and forth between contents it already had |
A call counts as failed when the tool errored or when it recorded a non-zero exit code. That distinction matters: opencode marks a shell command as completed whenever the tool itself ran, regardless of what the command returned, so a build retried until it passes is invisible to a status-only check. Tools that record no exit code fall back to tool status rather than being guessed at from output text.
Two calls are "the same" when the tool name and a hash of the recorded tool input match. The input itself is hashed and never stored or displayed, because tool inputs hold shell command lines and whole file contents.
What is deliberately not reported matters as much:
- Calls to different targets. Reading five different files is ordinary work, not a loop.
- A call that ran only twice. The threshold starts at 3, because a pair is nearly always legitimate — re-reading a file after a context compaction, for example.
- A re-read of a file that was modified in between, which is edit-then-verify, not repetition.
- Calls whose input opencode did not record. They cannot be compared, so the page reports how many it could not check rather than implying a clean result.
Each incident links into replay, where the individual repeated calls are marked in place with controls to jump between the runs. Session replay carries the same panel and threshold control, scoped to that session.
[!NOTE] The "repeated turns cost" figure is the cost of the turns that contained the repeats, not money you would save. opencode records cost per message rather than per tool call, so a message's cost is split across its calls and is dominated by context tokens the turn would have paid anyway. Treat it as an upper bound.
Calibration export
GET /api/diagnostics/loops returns shape-only evidence for tuning thresholds on a machine with more history than the one you are on:
curl -s http://127.0.0.1:3000/api/diagnostics/loops > oc-lens-diagnostics.jsonIt contains tool names, input key names, the JSON types of those keys, counts, histograms, and incident counts across several thresholds. It contains no values — no ids, paths, titles, commands, or file contents — so it is safe to carry off the machine that produced it. The redaction policy is restated inside the payload, and enforced by test.
Screenshots
The complete 15-route, 30-asset ledger is in docs/screenshots/README.md, captured against the deterministic fixture database with documentation-only pricing — never a personal opencode database or real pricing configuration.
| Page | Light | Dark |
| --- | --- | --- |
| Overview (/) |
|
|
| Activity (/activity) |
|
|
| Sessions (/sessions) |
|
|
| Session replay (/sessions/ses_0000) |
|
|
| Projects (/projects) |
|
|
| Project detail (/projects/proj_infra) |
|
|
| Tools (/tools) |
|
|
| Todos (/todos) |
|
|
| Costs (/costs) |
|
|
| Agents (/agents) |
|
|
| Subagent tree (/agents/tree) |
|
|
| Export (/export) |
|
|
| Settings (/settings) |
|
|
| Model pricing (/settings/pricing) |
|
|
| Style guide (/style-guide) |
|
|
Develop
pnpm install
pnpm fixture
OC_LENS_DB="$PWD/test/fixtures/populated.db" pnpm devThe fixture is synthetic and deterministic. Tests must use fixture databases, never a developer's real opencode history. See CONTRIBUTING.md before taking a ticket.
Security and privacy
- The opencode database connection is opened with SQLite
readOnly: true. - SQL access rejects credential-bearing tables before SQLite executes the query.
- Routes do not write to opencode data or files.
- The only mutating route is
PUT /api/pricing, and it can write only oc-lens's own fixed config path. - Safe settings are allowlisted and unknown configuration keys are redacted.
- The server listens on loopback; oc-lens has no telemetry or remote service.
The full threat boundary and enforced tests are documented in SECURITY.md.
Licence and attribution
oc-lens is released under the MIT License.
Its information architecture and interaction design were inspired by cc-lens v0.4.1, which is also MIT-licensed. oc-lens is independently implemented against opencode's data model; cc-lens code and its Claude Code data-access layer are not copied.
