Docs & Manual  ·  Token Usage Plugin

Understanding Token Usage
in Claude Code

Token Usage is an Obsidian community plugin that reads your Claude Code session logs and shows live token consumption directly in your sidebar. No API key required, no account, no data leaves your machine — it only reads JSONL log files that Claude Code already writes locally. This single page is both the glossary and the full manual: installation, every term you'll see in the sidebar/dashboard, exactly what the plugin reads and does not read, and what the numbers mean for your costs.

Getting Started#

Install. Inside Obsidian: Settings → Community plugins → Browse → search "Token Usage" → Install → Enable. That's the entire setup — no account to create, no API key to paste in, no external service to sign up for. Works the same way on Windows, macOS, and Linux — see Data Sources & Transparency for the one platform-specific detail (Claude Desktop's Agent Mode session location).

Open it. Click the bar-chart icon in the left ribbon, or run "Open Token Usage" from the Command Palette (Ctrl/Cmd+P). Either opens the view in the right sidebar, where it stays like any other Obsidian pane.

"No data yet"? Expected on a fresh install if Claude Code hasn't written any activity in the current read window. Start (or continue) a Claude Code session anywhere — terminal, editor, or Obsidian — and the sidebar picks it up automatically via a file watcher, within 30 seconds at the latest, with a fallback poll as a safety net.

Nothing to configure to get useful numbers. The sidebar works immediately: an icon rail on the left with four pages — Today, Calendar, Analytics and Settings — see below. Since 2.0 there is only this one layout; the older "Classic" view and the setting that switched between them are gone.

Commands available from day one (Command Palette):

CommandWhat it does
Open Token UsageOpens (or focuses) the sidebar view
Create Token Usage reportWrites a Markdown usage report into your vault
Open Token Usage dashboardBuilds the HTML dashboard and opens it in your default browser
Create Vault Token Usage Projects reportWrites a per-vault/per-project Markdown breakdown, handy for billing multiple clients or workspaces
Show what's newRe-opens the highlights popup for the currently installed version, any time
Export all CSV filesWrites all three CSV exports into your vault — see Exporting Your Data
Export projects CSVVault/project overview as a single CSV
Export daily detail CSVThe day-by-vault matrix as a single CSV
Export key figures CSVThe headline numbers, the official limit readings and the span of your limit hits as a single CSV

Data Sources & Transparency#

This plugin needs direct filesystem access to work at all — Obsidian's own Community Plugin review flags that as an expected warning, not a defect, since reading local session files is the entire point. Rather than ask you to trust that blindly, here is exactly where those files live, exactly which fields the plugin reads, and exactly what it never touches. Every claim below is verifiable directly in the plugin's own source: main.js is unminified and public on GitHub.

Where the JSONL files actually live. Claude Code — whether run from a terminal, inside an editor like VS Code, or from within Obsidian — writes one JSONL file per session under ~/.claude/projects/<workspace-id>/<session-id>.jsonl, one subfolder per working directory. This is identical on Windows (C:\Users\<you>\.claude\projects\...), macOS (/Users/<you>/.claude/projects/...), and Linux (/home/<you>/.claude/projects/...) — the plugin resolves it via Node's os.homedir(), which is platform-neutral by design, so this part has always worked the same way everywhere. One more file is involved, read-only unless you actively use the in-plugin retention control: Claude Code's own ~/.claude/settings.json, checked purely for the cleanupPeriodDays value — if you change it from plugin settings, a .bak backup of the whole file is written automatically first. And only if you set up the optional feed: ~/.claude/ratelimit-log.jsonl, read-only, the official percentages with their reset times.

Claude Desktop Agent Mode — a Windows-only exception, as of today's evidence. The Windows build of the Claude desktop app runs its embedded Claude Code inside an MSIX app-container sandbox, which virtualises the filesystem — so Agent Mode sessions there physically land somewhere other than the ordinary path above: %APPDATA%\Claude\local-agent-mode-sessions\..., or for the Microsoft-Store-packaged build, the sandboxed %LOCALAPPDATA%\Packages\<package-id>\LocalCache\Roaming\Claude\local-agent-mode-sessions\.... The plugin has walked this second location automatically since v1.8.0, on Windows only. macOS and Linux have no equivalent app-container sandboxing layer, and per available documentation, Claude Code — CLI, editor integrations, and the desktop app alike — writes to the same ~/.claude/projects/ on every platform. So on macOS/Linux, Agent Mode sessions (where the feature exists) are expected to already land in the standard location the plugin reads by default, with no extra code needed. This is the current best evidence, not an Anthropic primary source — if you use Claude Desktop's Agent Mode on macOS or Linux and notice usage that doesn't show up, please open a GitHub issue.

Field read from a session lineWhat it is used for
message.usageInput / output / cache-write / cache-read token counts — every number in the sidebar and dashboard
message.modelWhich model the row belongs to (Haiku / Sonnet / Opus / Fable)
cwd, sessionIdWhich vault, sub-project and session a data point belongs to
timestampWhen — drives every time-based view, the 5h window, and the archive
compactMetadata (system entries)Pre-/post-compaction token counts, shown as compaction events
error (system entries)Rate-limit and connection-failure detection only — never message content
aiTitleThe one exception below

The one thing that isn't a number. Claude Code itself writes a short, auto-generated title for each session into the same JSONL file (an ai-title entry). The dashboard's Top Sessions table reads that single short string and shows it in place of a raw session UUID, purely so the list is readable. It is the only field this plugin surfaces that is derived from conversation content rather than pure usage numbers — Claude Code's own summary, not anything the plugin generates or expands on.

What it never reads. The actual prompt text, Claude's responses, tool calls, file contents, or anything else in a session line beyond the fields above are never parsed, displayed, stored, or sent anywhere — the code simply never opens those object keys. Verify it yourself: search main.js for .usage, .model, .cwd, .sessionId, and .aiTitle, and you will find every place this plugin ever touches your data.

What leaves your machine: nothing. No network requests, no telemetry, no external server — every number is computed locally. The plugin writes exactly two kinds of new files, both inside your own vault, both aggregate-only: the daily archive under Token Usage Archive/ (see Archive & Long-term Data) and, only when you actively trigger it, the Markdown report, HTML dashboard, vault/projects export and CSV exports. None of them ever contain a prompt or a response.

If you want to check the browser yourself. Your browser's own developer tools (F12 → Network tab, filtered to XHR/Fetch) will show every request while you use claude.ai. Two honest caveats: this plugin does none of that for you — no browser integration, no extension, no proxy, a deliberate boundary rather than a missing feature. And claude.ai's web client talks to Anthropic's internal, undocumented endpoints, not the same as the public Claude API that Claude Code uses — so any token-like numbers visible there are internal implementation details that can change without notice, not a documented data source. The public API's usage object, the one Claude Code writes to your local JSONL files and the one this plugin actually reads, remains the only stable, documented source of exact token counts.

Limits: Percentages Only from Anthropic#

Percentages now come from Anthropic only. Up to 2.1, Token Usage estimated a percentage for the 5-hour window and for the week, either from your own limit hits or extrapolated from the feed. We put that estimate next to the official figures for eleven days. For the 5-hour window it was off by 36 points on average, and at the moment a window was officially full, our ring stood anywhere between 61 and 217 percent (our own measurement, 37 readings, 6 to 17 October 2026). How fast a window fills up depends heavily on how much context a session carries along, and the local logs cannot tell that reliably. The rings suggested a precision they never had. That was our decision, and it was wrong.

From 2.5 on, one simple rule applies: we only show a percentage for a limit when it comes from Anthropic, together with the time it was read. For that you need the feed (see Official Percentages from Anthropic). We make one exception for the week: between two readings we carry the last official figure forward with your counted tokens and label it as such, because the weekly limit proved stable in the same measurement (1.2 points off on average). Without the feed you see what we know for certain: your tokens in the current window and in the week, the time until the reset, and the range at which your 5-hour window has filled up so far. The Today ring no longer shows a percentage but a multiple of your usual day. Everything else in the plugin is counted and stays as it is.

RingWith the feedWithout the feed
5h windowThe official percentage from a reading taken in the current window, "as of hh:mm", plus the tokens counted since. Within a window the official value can only rise, so it is a lower bound. A reading from an earlier window is not shownGrey: tokens in the current window and the time to the reset
This weekThe official percentage. Between readings it is carried forward with your counted tokens, labelled "projected", with the official value and its time underneath. After a weekly reset without a new reading it carries on from 0% with last week's limit, labelled "projected since reset"Grey: tokens this week and the time to the reset
TodayA multiple of your usual day, for example "1.7x your usual day". Never a limit, see Today RingThe same

Why the tokens under a ring do not match its percentage. The plugin counts input and output. Anthropic also counts the context a session sends along with every request, so percentage and tokens do not match directly. A long session that carries a large context can fill a window with comparatively few counted tokens. The percentage is the figure to go by.

What stays: the span of your limit hits. Under the rings the plugin names the lowest and the highest token count at which your 5-hour window has filled up so far, for example "Your 5h window has filled up after 51K to 316K so far (102 limit hits)". It counts input and output from the start of the window up to each hit. It is neither a limit nor a forecast; it shows how wide the range really is. With the feed the window start comes from Anthropic. Without it, the start is rebuilt from your logs and can be a few minutes off if claude.ai or another device opened the window. Without the feed a short line under the rings links straight to the setup.

Why not a better estimate instead? We tried one: weighting cache tokens as well brought the weekly figure very close, but the 5-hour window stayed roughly 25 percent off in either direction on our own data. Anthropic can change how a limit is counted at any time, and a number you cannot rely on is worse than no number. Counted tokens, the reset and the span are certain; the percentage comes from the source.

Up to 2.1 this section was called "Rate Limit Estimates" and said the estimate would get more precise with every limit hit. The measurement above showed that it did not.

What is a Token?#

A token is a small chunk of text — roughly three quarters of a word in English. It is not exactly a word and not exactly a character. The sentence "Good morning, how are you today?" breaks into roughly 7 tokens. Longer or unusual words may cost more; common short words often share one. Both your input and Claude's response are counted, separately.

Every API call is billed on two counts: how many tokens go in, and how many tokens come out. That is all that matters for the bill.

Input and Output#

Input is everything Claude receives in a single request: your message, the system prompt, file contents, tool results, and the conversation history re-sent with each new turn.

Output is what Claude writes back. Output tokens are consistently more expensive than input tokens across all models — typically 3–5× more.

A single question is cheap. The costs grow with volume, context size, and repetition — not with the complexity of what you ask.

C.Write — Cache Write#

When Claude Code sends a large, repeated block of text (project files, a long system prompt, an entire codebase), Anthropic's infrastructure can cache it. The first time that block is processed, it is written into the cache. This is a cache write.

There are two kinds of cache write, priced differently: a 5-minute cache write costs 1.25× the standard input price, a 1-hour cache write costs 2×. In our own logs about 90% of the cache writes from Claude Code on a subscription were the 1-hour kind, while subagents wrote 5-minute caches. Since 2.1.0, hovering over a C.Write row in the sidebar shows the split for that period. It is an investment: you pay more upfront so that subsequent requests can skip reprocessing the same content. Cache writes also count toward the 5-hour limit, see What Counts Toward a Limit.

The plugin displays C.Write in aqua throughout the sidebar.

C.Read — Cache Read#

Once a block is cached, Claude can read it from the cache on subsequent requests instead of processing it from scratch. This is a cache read.

Cache reads cost only a fraction of the standard input price: 0.1× on most models, 0.05× on Opus 5.5 and Sonnet 5.5, 0.025× on Fable 5.1. If the same context is used many times, cache reads make large sessions significantly more affordable than they would otherwise be.

The plugin displays C.Read in violet to signal high volume but low cost per token.

C.Write vs. C.Read — The Reuse Factor, and What It Tells You About How You Work#

The relationship between these two numbers is more than a cost detail — it is a direct, honest readout of whether a stretch of work was focused or scattered.

Reuse Factor = C.Read ÷ C.Write

Reuse FactorWhat it signals
≥ 8×Deep focus — excellent cache return, the same context is carrying many requests.
3–8×Balanced — focused work with some variety mixed in.
1–3×Exploratory — frequent new context, typical of research or scoping work.
< 1×Minimal reuse — mostly independent, short, one-off sessions.

High reuse means you kept returning to the same context with follow-ups instead of constantly starting over; low reuse means near-constant context switching. Neither is "wrong" — exploration has its place — but if your goal was deep, sustained work and the Reuse Factor says otherwise, that's worth noticing. The dashboard shows this ratio in the Cache Efficiency section, including a line chart with C.Write in aqua and C.Read in violet — matching the sidebar colors.

Focus Score — a second, independent signal. The dashboard's Focus Score (0–100) combines three things the plugin can already see: cache reuse (the Reuse Factor bands above, 50% of the score), continuity (fewer, longer sessions per active day score higher than many short ones, 30%), and depth (more back-and-forth turns per session score higher than one-shot exchanges, 20%). The result maps to a badge — Deep Work Mode (80+), Focused (60+), Balanced (40+), or Scattered (below 40).

Reading the signals together, in practice. A high Reuse Factor and a high Focus Score on a day you spent deep in one problem is a good sign, not a vanity metric — Claude kept re-using what it already understood about your context instead of re-deriving it, which is both cheaper and usually faster. If those numbers come back low on a day you expected to be focused, the likely causes are: rewriting or repasting long context instead of continuing the same thread, opening a fresh session for follow-ups that belonged in the original one, or interleaving several unrelated tasks in quick succession — all visible directly in these numbers, days or weeks later.

For beginners: the single highest-leverage habit is staying in one continuous session for one continuous problem, and asking follow-ups instead of restating context in a new message — that alone tends to lift both numbers, and is usually just a better way to work. For experienced users: a consistently low Reuse Factor across a whole project might mean the system prompt or shared context is being rebuilt every time rather than reused — worth fixing at the workflow level (longer-lived sessions, a shared reference file, sub-agents that inherit context) rather than accepted as the cost of doing business.

Current 5h Window#

Claude Code enforces a 5-hour window, and it is anchored, not rolling. The window opens with your first message and runs exactly five hours; a new one only starts once that span has fully elapsed, chained in fixed five-hour blocks regardless of how much idle time falls in between. It is not "the last five hours counted backwards from now" — and it is independent of the weekly reset, which runs on its own schedule and does not also start a fresh 5-hour window.

The plugin reconstructs those real windows from your activity and sums the one that is currently open, showing Input, Output, C.Write, and C.Read as separate rows. This matters at the moment a window turns over: a rolling calculation would add the tail of the window that just closed to the head of the one that just opened, producing a figure that belongs to neither — exactly when you most want to see that you have fresh budget.

This is the most immediate view of your current session. If you have been working for a while without a long break, this window captures what you have spent since the window opened.

Why the countdown shows a tilde (~)

The reset countdown in the sidebar footer reads "Claude 5h resets in: ~Xh Ym". The tilde is intentional — it signals that this is an approximation, not an exact value.

Claude Code writes session data to local files after each response is fully completed, not at the exact moment you send your first message. When a session starts, the first request is often a long one — loading context, reading files, thinking. That first response can take 10 to 25 minutes. During that time, nothing is written to the local session log yet. So the earliest timestamp the plugin can read is not your actual session start — it is the moment your first response landed.

This means the plugin's countdown may run 10 to 25 minutes behind Claude's own display. For the precise reset time, check the plan usage section in Claude Code or on claude.ai. The plugin value is a reliable orientation, but Claude's own display is the authoritative source.

With the feed (see Official Percentages from Anthropic) this gap closes: every reading carries the moment the current window resets, so as soon as there is a reading from the current window, the plugin uses the official start, even if the window was opened on claude.ai, another device or another tool.

The three time views — how they relate#

The sidebar shows three different summaries of your activity: Current 5h Window, This Session, and Today. These are three independent cuts through the same data — they do not automatically nest inside each other like hours, days, and weeks would.

ViewWhat it coversResets when
Current 5h WindowAnchored window: everything since it openedWhen it expires — the next message opens a fresh one, in fixed five-hour steps regardless of pauses
This SessionAll entries with the current session ID, regardless of calendar dateWhen you start a new Claude Code session (new JSONL file)
TodayCalendar day: everything since midnightEvery day at midnight

The key implication: a session can span multiple days. If you started a long session yesterday and continued it today, "This Session" will show more tokens than "Today". That is expected — the session accumulates across calendar boundaries while "Today" only counts from this midnight.

Similarly, the 5-hour window is not a subset of "Today": a window that opened late yesterday evening reaches back across midnight, and everything in it still counts toward the same limit. Equally, the two can be identical — if your window opened this morning and you have not worked before that today, both figures show the same number until the window closes.

The plugin makes this visible: a small sub-label under each section title explains its scope. "This Session" shows when the session started, so you can immediately see whether the numbers span multiple days.

Models#

Claude Code routes requests to different models depending on the task. The sidebar shows a stacked percentage bar of model distribution over the last 7 days, with each model family in its own color:

ModelSidebar colorTypical role
HaikuTealFast, lightweight tasks, lowest cost
SonnetBlueBalanced capability and cost
OpusPinkComplex reasoning, demanding work
FableVioletHighest capability, highest cost
OtherGreyUnrecognized or future model strings

Model colours deliberately avoid green, amber and red. In this plugin those three mean good, warning and critical: a colour either identifies something or judges it, never both. Until October 2026 this table still listed the colours from before 2.0 (cyan, blue, purple, amber).

Knowing your model mix explains a lot of day-to-day cost variation. A day heavy on Opus looks very different in cost from a day spent mostly in Haiku. For the current model lineup and exact pricing, Anthropic's own pricing page is the source of truth — see also API Pricing Reference below.

Sessions#

Claude Code writes one JSONL log file per session. The plugin reads all files under ~/.claude/projects/ and groups usage by session. The dashboard's Top Sessions table shows which individual runs consumed the most tokens — useful for spotting unexpectedly expensive sessions.

What Counts Toward a Limit#

Anthropic enforces two limits and nothing else: the 5-hour window above, and a weekly cap that resets at a fixed weekday and hour. There is no daily limit — so the Today panel is not a quota (see Today Ring).

Input and output tokens count, and cache is not free either. Measurements against the official percentages Claude Code reports (October 2026) indicate that cache writes clearly count toward the 5-hour window and cache reads count a little. An earlier analysis of observed limit hits had pointed the other way. The newer measurements are more direct. The plugin's figures still count input and output only. When a long session has to rebuild its cache, for example in a new 5-hour window after a pause or when a large context is loaded for the first time, the official figure can therefore run ahead of the plugin. In practice: long sessions with a large context use up the 5-hour window faster per answer than fresh, short ones.

Anthropic does not publish either limit in tokens. Since 2.5, Token Usage therefore shows a percentage for a limit only when it comes from Anthropic, always with the time of the reading (see Limits: Percentages Only from Anthropic). That needs the feed, a small file with the official percentages (see Official Percentages from Anthropic). Between two readings the week is carried forward with your counted tokens and labelled "projected". The 5-hour window is not, because how fast it fills depends mostly on how much context a session carries, and the local logs cannot tell that reliably. Without the feed you see counted tokens, the time to the reset and the span at which your 5-hour window has filled up so far.

Today Ring#

There is no daily limit. Anthropic only limits the 5-hour window and the week. The Today ring compares what you have used today with your own average per active day, taken over every day Claude Code keeps on disk (your data retention setting, cleanupPeriodDays).

Since 2.5 it shows this as a multiple, not a percentage: "2.0x your usual day" means you are working twice as much as usual today, nothing more. A busy day is a change in how you work, not a warning, which is why the ring stays neutral grey (since 2.1.0). How close you are to a limit is shown only by the rings for the 5-hour window and the week, and only with an official value. Up to 2.1 the same comparison read "200%"; the multiple makes sure that every percentage on screen comes from Anthropic or is a labelled weekly projection from an Anthropic value.

Official Percentages from Anthropic (the Feed)#

Optional, since 2.1.0. Claude Code knows the official rate-limit percentages of your plan, the numbers /usage shows. Two small scripts from the plugin repository write them to ~/.claude/ratelimit-log.jsonl. Since 2.5 this file is the only source of limit percentages in Token Usage: without it the rings for the 5-hour window and the week stay grey and show counted tokens and the time to the reset; everything else works the same. The complete guide is in the extras folder on GitHub.

What you gain

Without a feedWith a feed
5-hour window startReconstructed from your first logged messageThe official start, also when the window was opened on claude.ai, another device or another tool
5-hour ringGrey: tokens in the window and time to the resetThe official percentage from a reading in the current window, with its time and the tokens counted since
Weekly ringGrey: tokens this week and time to the resetThe official percentage, carried forward between readings with your counted tokens and labelled "projected"
Weekly resetFrom your weekly-limit message, once you have hit the capFrom the feed, to the minute, also across daylight saving

A real example from our own data, 27 October 2026: at 13:10 the plugin carried the week forward from an official 24% to about 28%; the next official reading six minutes later said 29%.

Requirements

  • A Pro or Max subscription that Claude Code is logged in with. With an API key there are no plan percentages.
  • Node.js, because both scripts are small Node programs. Check with node --version. If it is missing, install the LTS version from the Node.js website. Claude Code installed with the native installer does not bring Node.js along.
  • A recent Claude Code version, and for the poll the Claude Code CLI claude.

Which script do I need?

Where you workScript
In a terminalratelimit-statusline.js as your status line. Free, readings come in while you work
Inside Obsidian, an editor or another client without a status lineratelimit-poll.js, run on a schedule
BothBoth. They write to the same file

A status line only runs while Claude Code's interactive terminal is open. Clients that embed Claude Code do not run it, so the status line alone produces few or no readings there.

Option A: status line script

Copy the script to ~/.claude/ratelimit-statusline.js and add this entry to ~/.claude/settings.json, next to any keys that are already there:

"statusLine": { "type": "command", "command": "node ~/.claude/ratelimit-statusline.js" }

On Windows use the full path with forward slashes, for example node C:/Users/<you>/.claude/ratelimit-statusline.js. Restart Claude Code; the status line then reads 5h 12% | week 34%. Already using a status line of your own? Keep it and add the logging part of our script to it.

Option B: scheduled poll

Before you set it up: every run is a real, tiny request (the prompt ok to Haiku, no session saved) and counts toward your usage. If no 5-hour window is open at that moment, the request opens one, so your next window starts at the poll time. Schedule it for times you work anyway; three times a day is plenty for the week, which the plugin carries forward between readings. The 5-hour ring only shows a reading from the current window, so with three polls a day it is grey most of the time; that is the honest state, not an error. Since 2.5 the script tries once more after a timeout: a run right after the computer wakes from sleep often has no network yet.

Or only while you work (since 2.5, recommended if you want the 5-hour ring). Started with --only-when-active, the script first checks whether Claude Code wrote to its session logs in the last 20 minutes and otherwise exits without a request. While you work a 5-hour window is open anyway, so the poll practically never opens one of its own, and you can schedule it every hour. The 5-hour ring then shows an official value most of the time you work. Each run while active is one tiny request; idle runs cost nothing. Up to 2.5.0 we suggested every 30 minutes; that is twice the requests for a reading at most half an hour fresher. The commands for this variant on Windows, macOS and Linux are in the extras guide linked above; with cron it is simply 0 7-23 * * * and the flag at the end.

Copy the script to ~/.claude/ratelimit-poll.js and run it once by hand with node ~/.claude/ratelimit-poll.js. It prints 5h 12% | week 34%. Then schedule it.

Windows (PowerShell, runs at 12:00, 17:00 and 22:00, catches up after the computer was off, without a console window):

$node     = (Get-Command node).Source
$script   = "$env:USERPROFILE\.claude\ratelimit-poll.js"
$action   = New-ScheduledTaskAction -Execute 'conhost.exe' -Argument "--headless `"$node`" `"$script`""
$triggers = '12:00','17:00','22:00' | ForEach-Object { New-ScheduledTaskTrigger -Daily -At $_ }
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable
Register-ScheduledTask -TaskName 'TokenUsageLimitPoll' -Action $action -Trigger $triggers -Settings $settings

Why conhost.exe --headless (since 2.5.1): node.exe is a console program, so Task Scheduler opens a console window on every run, even on runs that ask nothing. Up to 2.5.0 our commands started node.exe directly and did exactly that. Started this way, the run stays invisible. We tested it on Windows 11. Microsoft does not document this switch, and some security software reports hidden console starts as suspicious. If yours does, or the task does not run, use -Execute $node -Argument "`"$script`"" instead and accept the short window.

Already scheduled it with an earlier guide? This keeps your task, times and options and only adds the hidden start:

$old = (Get-ScheduledTask -TaskName 'TokenUsageLimitPoll').Actions[0]
if ($old.Execute -notmatch 'conhost') {
  $new = New-ScheduledTaskAction -Execute 'conhost.exe' -Argument "--headless `"$($old.Execute)`" $($old.Arguments)"
  Set-ScheduledTask -TaskName 'TokenUsageLimitPoll' -Action $new
}

macOS and Linux (crontab -e, with full paths from which node and which claude, because cron runs with a minimal PATH):

0 12,17,22 * * * CLAUDE_BIN=/full/path/to/claude /full/path/to/node /Users/<you>/.claude/ratelimit-poll.js

On Linux the home folder is usually /home/<you>. Errors of scheduled runs go to ~/.claude/ratelimit-poll-errors.log. If the script cannot find the Claude Code CLI, set CLAUDE_BIN to its full path.

Check that it works

  • The file ~/.claude/ratelimit-log.jsonl exists and gets new lines.
  • Refresh the sidebar. The week ring shows a percentage with "as of hh:mm" (or "projected" with the official value underneath), and the hint "Official percentages need the feed" under the rings is gone. The 5-hour ring shows a percentage right after a reading in the current window. In the dashboard the panels read "official percentage from Anthropic" or "projected from the last official value".
  • Right after a reading, /usage in Claude Code and the plugin's rings show the same percentages.

How the plugin uses the readings

  • Window start: every reading carries the moment the current 5-hour window resets. The window is the five hours before that, so the plugin knows the real start even if the window was opened somewhere it cannot see.
  • 5-hour ring: shows the latest reading only while its window is still open, with the time of the reading and the tokens counted since. Within a window the official value can only rise, so it is a lower bound. Nothing is carried forward. A reading from an earlier window is not shown.
  • Weekly ring: shows the latest reading of the current week. Between readings it is carried forward with your counted tokens against the weekly limit the readings imply (tokens of the week up to a reading divided by its percentage, from readings of 10% upwards; below that the whole-number rounding is too coarse) and labelled "projected". After a weekly reset without a new reading it carries on from 0% with last week's limit, labelled "projected since reset".
  • Usage credits: with usage credits you can keep working after the weekly limit. Readings at 100% or more, and anything after them in the same week, are not used for the weekly limit; a week at 100% shows the official value without carrying it forward.
  • Weekly reset: taken from the reading as an exact moment, so it stays right across daylight saving.
  • Further windows: if Anthropic reports more than the 5-hour window and the week (for example a separate weekly limit for one model), both scripts record it and the plugin shows it under the rings, as reported.
  • No feed for a while: without a fitting reading the rings go grey again and show counted tokens and the time to the reset. Nothing is estimated in between.

Known limits

  • The weekly projection counts input and output only. Officially, cache writes also count (cache reads a little). Over a week this evens out well (1.2 points off on average in our measurement), but a large cache rebuild shows up fully only with the next reading.
  • Readings only exist when a script runs: while a status line is shown or at the scheduled times.
  • Whole percentages: the official figures come rounded. One percent of a 5-hour window can be a few thousand tokens.

Troubleshooting

What you seeWhat to do
The status line is emptyNode.js not found. Check node --version; on Windows put the full path to node.exe into the command
5h ? | week ?No percentages delivered. Log in with your subscription instead of an API key, update Claude Code
Poll: "Claude Code CLI not found"Set CLAUDE_BIN to the full path of claude
Poll: "No rate_limit_event in the output"Run claude once by hand and log in with your subscription
5-hour ring grey with "no reading in this window yet"Normal between polls at fixed times. Run the poll once by hand, then refresh, or schedule it every hour with --only-when-active
Windows: a console window opens on every pollThe task starts node.exe directly (our guide up to 2.5.0). Switch to the hidden start, see "Already scheduled it with an earlier guide?"
Windows: the task with --headless does not run, or security software reports itUse the plain start with node.exe and accept the short window
Week ring grey with "no reading this week yet"No reading since the weekly reset, and none last week either. Wait for the next reading or run the poll once by hand

Privacy and removal

Everything stays on your machine. Each line holds a timestamp, the percentages with their reset times and, from the status line, the session and model ID. The plugin only reads the file and never runs the scripts itself. To remove it, delete the statusLine entry, the scheduled task (Unregister-ScheduledTask -TaskName 'TokenUsageLimitPoll') or the cron line, and if you like the log file. The rings for the 5-hour window and the week then stay grey and show counted tokens and the time to the reset.

Updated 10 October 2026: the first version of this section did not mention Node.js and offered only the status line, which does not run in clients like Obsidian. Both are added. Updated for 2.5: up to 2.1 the plugin used the readings to correct its own limit estimates and fell back to those estimates without them; since 2.5 the readings are the only source of percentages.

Weekly Reset#

The weekly limit resets at a fixed moment that differs per account. Everything week-shaped depends on it: the week ring, the forecast and the activity heatmap.

You normally do not have to set this. With the feed, the plugin takes the exact reset from the official reading. Without it, it reads the reset from the message Claude writes when you hit a weekly limit. Either way Settings shows a green check and where the value came from. Until a reset has been detected, the plugin assumes Sunday 18:00 and says so.

Daylight saving. Anthropic's reset is fixed in UTC, so its local clock time moves by an hour when the clocks change. Up to 2.1 the plugin stored it as a local weekday and hour, so after the switch to winter time every week boundary sat an hour off. Since 2.5 a detected reset is kept as an exact moment and follows the change automatically.

You can set it by hand under Settings → Weekly reset. A manual setting wins and stays in local time: automatic detection will not overwrite it, it only confirms it.

An icon rail on the left switches between four pages. Since 2.0 this is the only layout — the former "Classic" view and the setting that switched between them have been removed.

PageWhat is on it
TodayThree rings (5h window, today, this week) with the span of your limit hits underneath, the activity heatmap for the current billing week, your last action, and the token breakdown. The rings for the 5-hour window and the week carry a percentage only when it comes from Anthropic, with the time of the reading; without one they stay grey and show counted tokens and the time to the reset. The Today ring shows a multiple of your usual day
CalendarThe last two months as month grids
AnalyticsThe 7-day and N-day summaries as KPI tiles with trend sparklines, plus the model distribution
SettingsThe same settings as the Obsidian settings tab, without leaving the sidebar

Everything on Today is from today or the current week by design; anything covering a longer span lives on Analytics or in the dashboard. In the header, Dashboard and Report generate files, CSV exports into your vault, and the arrow forces an immediate refresh.

Each of Today's four token rows carries a compact verdict marker — a green dot when the value is close to your own recent average, an amber arrow when it is running noticeably higher. The comparison window follows your Claude data retention setting, not a fixed number of days.

Activity heatmap

The grid on the Today page covers your current billing week. One row per calendar day, one cell per two hours, twelve cells a day.

It spans eight rows, not seven: a week running from, say, Sunday 17:00 to the next Sunday 17:00 touches eight calendar dates, so the first and last rows are deliberately partial. Cells outside the window are drawn as empty outlines — that is what makes the boundary of your cycle visible rather than hiding it inside artificial 24-hour slices.

Colour compares each cell with your own usual 2-hour block: the average of all 2-hour blocks with activity over the stored days (the figure is named under the grid). Low is under half of that, medium up to it, high up to twice, red more than twice. Shading within a band shows where inside it a cell sits. Up to 2.1 the cells were measured against an estimated 5-hour limit, which no longer exists.

Three kinds of nothing are kept apart: outside the window (outline only), not yet reached (faint), and genuinely no activity (filled). Only the last one says anything about how your week went. Beside the grid, Active days counts the days of this billing week with any activity.

Activity calendar

The Calendar page shows the last two months side by side. Two rather than one, because at the start of a month a single grid would show only a handful of usable days and hide exactly the run-up you are looking for. The arrows move the pair further back, as far as the archive reaches; the calendar never goes into the future.

Each past day carries a coloured dot sized against your own recent daily average: green below average, amber around it, red for a spike (2x or more). Days with no activity have no dot. Click any day to add a private note — it is stored in the plugin settings, never in your session data.

Exporting Your Data (CSV)#

Three CSV files: the project overview, the day-by-vault matrix, and the key figures. Two ways to get them, and they land in different places.

CSV button in the sidebar header — the plugin writes the files into your vault, into the folder set under Settings → CSV export folder. The menu names that folder before you click, so you know where they go. The same exports are in the Command Palette under "Export".

CSV Export menu in the dashboard — the dashboard is a browser page, so it hands the file to your browser and the browser decides where it goes, usually your Downloads folder. A web page cannot choose a target folder; that is a browser rule, not a missing feature.

Both routes produce raw numbers and ISO dates, ready to calculate with in Excel, Sheets or a script. Everything is generated locally — no upload, no network, same as the rest of the plugin.

The key figures follow the same rule as the rings (since 2.5): the official 5-hour and weekly values with the time of the reading, the labelled weekly projection, the weekly limit the feed implies, and the span of your limit hits (lowest and highest). The former rows with estimated limits are gone. Text cells that start with =, +, - or @, such as an unusual folder name, get a leading apostrophe so that Excel or LibreOffice cannot run them as a formula; plain numbers stay as they are.

Archive & Long-term Data#

Why this exists at all. Claude Code manages its own local session files and deletes them on a schedule — 30 days by default, controlled by cleanupPeriodDays in its own ~/.claude/settings.json. Without a copy kept elsewhere, anything older than that window is simply gone.

What gets written, and where. Every time Obsidian is open (on every refresh, from the fallback poll or the file watcher), the plugin checks which recent days already have an archive file and writes one for any day that is missing — including today's, updated in place as the day continues. Files land in a plain folder inside your vault, one per calendar day: Token Usage Archive/YYYY-MM-DD.md (folder name configurable in Settings). Each file holds aggregated totals only — token counts by type, session count, per-model token volume, and the vault/project breakdown for that day — never a prompt, a response, or anything resembling conversation content.

Once written, a past day's file is treated as final and left alone on later refreshes. The one deliberate exception: when a release adds an entirely new data source (agent-mode desktop sessions arrived this way in v1.8.0), a one-time rebuild silently rewrites the affected recent days once, so totals that were incomplete before that source existed don't quietly look wrong forever.

The honest limit. The archive can only save what still exists at the moment Obsidian is actually open. If Obsidian stays closed longer than Claude Code's own retention window, the days in between are deleted before the plugin ever gets a chance to see them — there is no way around this without running continuously. If you open Obsidian less than daily, increase Settings → Claude data retention (writes directly to Claude Code's own cleanupPeriodDays, with an automatic .bak backup first) to give yourself a wider safety margin. For serious long-term controlling — cost trends, contract comparisons across months — 90–180 days is more realistic than the 30-day default.

Archiving can be turned off entirely (Settings → Enable daily archive) if you would rather the plugin never create files in your vault — everything still works, but historical reach is then limited to whatever Claude Code itself still has on disk.

Dashboard & Vault/Project Reporting#

The sidebar is built for a quick glance; the HTML dashboard (Command Palette → "Open Token Usage dashboard") is built for sitting down with the numbers. It regenerates a static HTML file and opens it in your browser — a snapshot, not a live connection, honestly timestamped as such in the corner.

Three tabs. Dashboard: the budget panels for the 5-hour window, today and the week, then five KPI cards (Weekly Forecast, Limit Health, Cache Efficiency, Daily Velocity, Focus Score), a week status bar, the daily chart, model distribution, histogram, Top Sessions, and the rate limits you hit with their span. Reports: the same figures laid out like the Markdown report. Projects: the vault/project breakdown, below.

Same rule as the sidebar (since 2.5): the budget panels, the overall zone, the Limit Health card and the verdict of the week bar use official values only, with the time of the reading, or the labelled weekly projection from them. Without the feed the panels show counted tokens and the time to the reset, and Limit Health points to the setup instead of guessing. The Weekly Forecast stays: it projects your own counted usage to the end of the billing week, it is not a limit.

The period dropdown (30/60/180/360 days) reshapes the summary cards, daily chart, and cache chart instantly, client-side — a full 360-day window is always embedded. Model distribution, the histogram, Top Sessions, and rate-limit detection stay on the live data window regardless, since the archive that powers longer periods only holds daily aggregates, not that level of session detail. This also applies to the span of your limit hits: it is measured from the tokens counted up to each hit, which only the live window still holds.

Folder and model names are escaped (since 2.5). The project name in the dashboard is the last folder of the working directory a session started in. Up to 2.1 the dashboard put these names into the page unescaped, so a crafted folder name, for example of a cloned repository, could have run script inside the dashboard page in your browser. We found this in our own security check in October 2026 and have no indication it was ever used. The sidebar inside Obsidian was not affected.

Projects tab — for more than one vault or client. Each row is a folder a Claude Code session started in: your Obsidian vault, the desktop app's Agent Mode bucket (shown as Claude Desktop (Agent Mode)), or any other directory you ran Claude Code in directly. Folders under 1% of the total collapse into a single "Other" row. Tick "Show sub-project detail" to expand any vault whose working directory drifted during a session into its own per-subfolder split, right inline in the table — the same breakdown is also in the standalone Vault_Token_Usage_Projects.md export, handy for splitting costs across clients when billing. Columns are sortable by clicking their header.

Export commands (Command Palette), each overwriting its target file in your vault on every run: Create Token Usage report (Token Usage Report.md), Open Token Usage dashboard (Token Usage Dashboard.html), Create Vault Token Usage Projects report (Vault_Token_Usage_Projects.md). All three paths are configurable, see Settings Reference.

What is Measured (and What Is Not)#

The plugin covers every way you run Claude Code: terminal, Obsidian, an editor such as VS Code, and desktop Agent Mode — all flowing into the same numbers (see Data Sources & Transparency for exactly how). What it cannot show is ordinary chat — conversations in the Claude desktop app's normal chat window, or on claude.ai in a browser. Those never write token counts to disk in the format this plugin reads; the only signal available there is a rounded percentage of your plan limit. If a day's actual usage feels higher than the dashboard shows, this is very often why.

Settings Reference#

Every setting the plugin has, in the order it appears in Settings → Token Usage. Defaults are chosen so a fresh install works well untouched.

SettingDefaultWhat it does
LanguageEnglishDisplay language for the plugin UI (English, German, French, Italian, Spanish). Takes effect immediately.
Weekly resetauto-detectedWhen your weekly limit resets. Taken from the feed or from your own weekly-limit messages as an exact moment, so it follows daylight saving; a manual setting always wins and stays in local time. See Weekly Reset.
Report period30 daysHow far back the dashboard and report look. Beyond your Claude data retention window, older days are filled in from the archive automatically.
Enable daily archiveOnWrites one small Markdown summary file per day into your vault. Turn off if you don't want the plugin creating files in your vault.
Claude data retention30 days (Claude Code's own default)How long Claude Code itself keeps session files, read from and — if changed here — written back to Claude Code's own settings.
Auto-refresh interval30 secondsFallback polling interval; the file watcher picks up new Claude responses by itself, within 30 seconds at the latest.
Report path in vaultToken Usage Report.mdVault-relative path for the Markdown report.
Vault report path in vaultVault_Token_Usage_Projects.mdVault-relative path for the standalone per-vault/per-project export.
Dashboard path in vaultToken Usage Dashboard.htmlVault-relative path for the HTML dashboard.
Archive folder in vaultToken Usage ArchiveVault-relative folder holding the daily archive files.
CSV export folder in vaultToken Usage ExportsVault-relative folder the plugin writes CSV exports into. See Exporting Your Data.

Every path/folder field has a "Show in folder" button next to it that opens the exact location in your system file manager.

API Pricing Reference#

Anthropic's API prices per million tokens — standard input / output, as of October 2026:

ModelInput / 1MOutput / 1M
Haiku 5.5 *$0.10$0.50
Haiku 4.5$1.00$5.00
Sonnet 5.5$2.00$10.00
Sonnet 5 **$2.00$10.00
Sonnet 4.6$3.00$15.00
Opus 5.5$4.00$20.00
Opus 5$5.00$25.00
Fable 5.1$10.00$50.00
Fable 5$10.00$50.00

* Haiku 5.5 for prompts up to 100,000 tokens; above that $0.50 input / $2.50 output.
** Sonnet 5 launched with $2 / $10 as introductory pricing until 31 August 2026. Anthropic has since made it the standard price; the announced increase to $3 / $15 did not happen. Our earlier version of this page still said it would.

Cache pricing on top of standard input rates:

  • C.Write: 1.25× the model's standard input price for a 5-minute cache, 2× for a 1-hour cache (the usual kind for Claude Code on a subscription)
  • C.Read: 0.1× the model's standard input price; 0.05× on Opus 5.5 and Sonnet 5.5, 0.025× on Fable 5.1

These are API usage prices, not monthly subscription prices for the Claude app or Claude Code Max. The Token Usage plugin reads locally logged data — it makes no API calls and has no access to your Anthropic billing account.

Why Costs Accumulate#

A single request is rarely expensive. Quick calculation with Sonnet 5 at its standard price of $2 / $10 per million:

  • 10,000 input tokens × $2 / 1M = $0.02
  • 2,000 output tokens × $10 / 1M = $0.02
  • Total: roughly $0.04

That is almost nothing. The issue is repetition and context growth. Each new message in a session typically re-sends the conversation history and any open files as input. After ten exchanges, message ten carries all nine previous turns plus any attached documents — so the total input count grows with every step, even when you only type a short question.

The question itself is rarely the cost driver. What gets sent along with it is.

What Drives Costs Up#

  • Long sessions where a large context window is re-sent with every request
  • Attaching large files or entire codebases that travel as input with each message
  • Frequent rapid requests in a short time span
  • Using a high-tier model for tasks a cheaper one handles equally well

Practical Tips#

Measure first. The plugin's daily chart and session table show where tokens actually go. You cannot optimize what you have not looked at.

Avoid unnecessary context. Large files attached "just in case" add to every input count. Attach only what Claude needs for the current task.

Choose the model by task. Not every request needs Opus. Quick questions, formatting tasks, and simple code edits often work well with Haiku or Sonnet at a fraction of the cost. Compare quality and total cost per completed task, not just price per token.

Understand the cache. A spike in C.Write at the start of a session is normal — a large context was established. What matters is whether C.Read follows. If the same context is reused across many requests, the upfront write cost amortizes quickly and your effective cost per request drops significantly.

Use the dashboard. The HTML dashboard (opened via the chart button in the sidebar) shows your usage history — 30, 60, 180, or 360 days via the period selector in the header — plus model distribution and the cache efficiency trend. Looking at data over days reveals patterns a single session view cannot.

FAQ & Troubleshooting#

Does this work on macOS and Linux, or only Windows? All platforms — the core plugin has always been platform-neutral. The only platform-specific detail is Claude Desktop's Agent Mode session location, which is a Windows-only quirk; see Data Sources & Transparency for the full explanation.

"This Session" shows more tokens than "Today" — is that a bug? No. A Claude Code session can run across a midnight boundary; see the three time views above.

Why are my 5-hour and week rings grey, without a percentage? Since 2.5 the plugin shows a limit percentage only when it comes from Anthropic. That needs the optional feed. Without it, the rings show counted tokens and the time to the reset, and a short line under them links to the setup. With a poll at fixed times, a few times a day, the 5-hour ring is still grey most of the time, because a 5-hour reading only counts inside the window it was taken in. Running the poll every hour with --only-when-active changes that. See Limits: Percentages Only from Anthropic.

Why does the dashboard's "Limit Health" card not show a value? Same reason: it needs an official weekly value from the feed. Until one exists, the card points to the setup instead of guessing.

Where did the estimated limit go? It was removed in 2.5 because it was wrong too often: for the 5-hour window it was off by 36 points on average against the official values. What stays is the span at which your 5-hour window has filled up so far.

My browser chat (claude.ai) or the desktop app's normal chat usage doesn't show up anywhere. Expected, not a bug — see What is Measured and Data Sources & Transparency above.

Obsidian's plugin review flagged "Direct Filesystem Access" — should I be worried? No, that warning is expected and unavoidable for what this plugin does — see Data Sources & Transparency for exactly what is and isn't read.

A day's numbers changed after I updated the plugin — did old data get corrupted? Almost certainly not — see the one-time rebuild mechanic under Archive & Long-term Data.

Can I track more than one Obsidian vault, or split usage by client? Yes — see Dashboard & Vault/Project Reporting.

Do I need an API key or an Anthropic account to use this plugin? No. It reads local files Claude Code already writes on your own machine.

I closed Obsidian for a few weeks — is that usage gone for good? If it fell outside your configured Claude data retention window while Obsidian was closed, yes — see the honest-limit box under Archive & Long-term Data.

Compatibility & Claude Code Updates#

Token Usage reads the JSONL session files that Claude Code writes locally. Anthropic updates Claude Code regularly — sometimes in ways that affect how session data is recorded or how internal telemetry is counted.

We review Anthropic's release notes with each major Claude Code release and update the plugin where necessary. Significant compatibility changes are documented in the plugin changelog on GitHub.

About This Plugin#

Token Usage is an open-source Obsidian community plugin. It reads local JSONL files written by Claude Code — no data is sent anywhere. Something not covered above? Issues and feature requests are welcome any time.

Prices cited on this page are sourced from Anthropic Platform Docs. Last updated October 2026. Prices may change — always check the current rates on the Anthropic website.