You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Non-cached input tokens are dropped from usage, so input is always 0 and cost is under-reported #146
This finding & PR is 100% AI. Apologies if its completely inaccurate and pointless.
Versions
@stablekernel/opencode-cursor 0.10.0
@cursor/sdk 1.0.37
opencode v2.1.2
Summary
mapUsage passes Cursor's inputTokens to opencode as inputTokens.total. Cursor's inputTokens doesn't include cached tokens: the SDK's own totalTokens is inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens. opencode treats total as including cache and subtracts cache read and cache write to get the non-cached input. On any cached turn that comes out negative and gets clamped to 0, so non-cached input tokens never show up in opencode's token counts or cost.
opencode stats --days 0 --cost --models for one day of cursor/claude-opus-5-5 use, 18 steps:
Token type
opencode
input
0
output
~51k
cache read
~8.9M
cache write
~1.2M
total
~10.15M
The Cursor usage dashboard showed about 14.9M tokens for the same day. The ~4.75M gap is about what you'd expect for missing non-cached input. Input has been 0 for every Cursor-model step I checked.
Expected
Non-cached input tokens are reported and priced at the model's input rate.
The suggestion also passes reasoningTokens through, since the SDK includes it in the turn-ended usage when present.
Possibly related
The price table (MODEL_COST) is applied through two routes: the config hook, which lets user provider.cursor.models entries override it, and the provider.models route, which always uses the built-in table. If list prices don't match a user's actual Cursor rates, there's no reliable way to override them. Could user-configured cost be honoured on both routes?
Thanks for the detailed report. The bug was real, but the cause was different from the one you described.
Cursor's inputTokens already includes cache reads and writes. @cursor/sdk computes totalTokens = inputTokens + outputTokens, with no separate cache terms. So passing inputTokens as inputTokens.total was correct.
The bug: the plugin left noCache undefined. opencode 2.x reads noCache directly as the non-cached input, so input always showed as 0 and was never priced. The fix (#147) sets noCache = inputTokens − cacheRead − cacheWrite, clamped at 0, and passes reasoning tokens through as outputTokens.reasoning.
Fixed in 0.10.1 and later. To upgrade: run opencode plugin update, or delete ~/.cache/opencode/npm/@stablekernel/opencode-cursor@latest and restart opencode.
Honoring a cost you configure yourself on provider.models is a separate problem. Open a new issue if you want it tracked.
Activity
chore: patch security advisories, report non-cached input tokens (#146)…
chore(release): 0.10.1 (#149)
justin-carper commentedon Oct 28, 2026
Thanks for the detailed report. The bug was real, but the cause was different from the one you described.
Cursor's
inputTokensalready includes cache reads and writes.@cursor/sdkcomputestotalTokens = inputTokens + outputTokens, with no separate cache terms. So passinginputTokensasinputTokens.totalwas correct.The bug: the plugin left
noCacheundefined. opencode 2.x readsnoCachedirectly as the non-cached input, so input always showed as 0 and was never priced. The fix (#147) setsnoCache = inputTokens − cacheRead − cacheWrite, clamped at 0, and passes reasoning tokens through asoutputTokens.reasoning.Fixed in 0.10.1 and later. To upgrade: run
opencode plugin update, or delete~/.cache/opencode/npm/@stablekernel/opencode-cursor@latestand restart opencode.Honoring a
costyou configure yourself onprovider.modelsis a separate problem. Open a new issue if you want it tracked.