Skip to content
| Marketplace
Sign in
Visual Studio Code>Visualization>Kiyo AI StatusNew to Visual Studio Code? Get it now.
Kiyo AI Status

Kiyo AI Status

0xpratyadev7x

|
9 installs
| (0) | Free
Claude Code & Codex CLI usage in the VS Code status bar, read entirely from local files. No network requests, no credentials.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Kiyo AI Status

Claude Code and Codex CLI usage in the VS Code status bar, read entirely from files the two CLIs already write on your machine.

No network requests. No credential stores read. Nothing leaves your computer.

   [claude] Claude Code 5h ■■■□□ 54% · 15m  7d ■■□□□ 46% · 3d
──────────────────────────────────────────────────────────────

Each window shows a bar, the percentage consumed, and how long until it resets — in a single unit: 3d once a day or more remains, then 15h, then 42m.

Hover for the full picture; click for a detail panel.

What it shows

Claude Code Codex
5-hour window ✅ plan dependent
7-day window ✅ ✅
Reset countdown ✅ ✅
Plan type ✅ ✅
Usage credits spent ✅ —
Context window of last turn tokens only tokens + %

The percentages are the providers' own numbers — the same ones /usage prints in the CLI. A percentage written ~42% is that figure projected forward from local token counts, because the CLIs refresh their own only occasionally; see Keeping it fresh.

Where the data comes from

Both CLIs already record their own rate limits on disk. This extension reads those records and nothing else.

Claude Code caches the usage bars that /usage renders:

  • ~/.claude.json → cachedUsageUtilization (respects CLAUDE_CONFIG_DIR)
  • Context tokens: the tail of the newest log under ~/.claude/projects/**/*.jsonl

Codex writes its rate limits into every session log:

  • ~/.codex/sessions/**/rollout-*.jsonl → the last token_count event's rate_limits (respects CODEX_HOME)

Only the last 512 KB of a session log is read, so multi-megabyte files stay cheap.

Usage log

The panel's Usage log tab breaks token spend down by project, model, day, hour, session or source, over today / 7 days / 30 days / all time. It answers "where did my usage actually go", which the percentages alone cannot.

Column What it is
Turns API responses counted
Fresh in Input tokens not served from cache
Output Tokens generated
Cache read Context re-read from cache
Cache write Context written into cache
Fresh + out The two columns that reflect work done, and what rows are ranked on
Share That row's portion of Fresh + out for the range

Which axis answers what

project, model and day answer "what have I been spending on". The other three answer "where is this coming from", which is a different question and the harder one.

Axis Row is Answers
hour 2026-08-05 14:00 Spend at hours nobody was typing
session my-project · 019f829c What one task actually cost
source claude-vscode · subagent What drove the turn

source is built from three things, and they are not equally reliable:

  • entrypoint — claude-vscode, sdk-cli, cli, or Codex's originator such as codex_vscode and codex_exec. Written on every response that carries a usage payload, so this part is exact.
  • subagent — from isSidechain, also on the response itself, also exact.
  • origin — human, task-notification, coordinator. This one is written on the prompt, not on the response that spends the tokens, so it is carried forward from the last genuine prompt and cleared by the next one that does not carry an origin.

That last part is why a row naming an origin is a floor rather than a total. Measured on one machine, origin was present on 66 of 2,187 prompts; carrying it forward labelled 37% of turns and left the rest under the bare entrypoint. A turn genuinely driven by a notification can land in the unlabelled row, but nothing is ever filed under an origin it did not record. Tool results are skipped without being parsed — toolUseResult marks every one, and they are the large lines.

Rows are ranked by spend on every axis, hour included, so the top of the table is the hour that cost the most rather than the most recent one.

Cache reads are shown but excluded from the ranking on purpose. A long session re-reads its whole context every turn, so cache reads are both the largest and the cheapest number in the row — ranking on the grand total would rank by session length rather than by work done. In one real sample, 3,681 turns came to 15.6M fresh + output tokens against 420M cache reads.

Three quirks of the logs are handled, because ignoring any of them skews the totals:

  • Claude Code writes one log entry per content block, repeating the same usage payload on each. Consecutive entries sharing a requestId are one response, counted once — without this the totals run roughly 2.2× high.
  • Codex counts cached tokens inside input_tokens, where Claude reports them separately, so the cached part is subtracted back out or it lands in two columns at once.
  • Codex reports cumulative counters, so a turn's cost is the difference between consecutive token_count events. Diffing the running total reproduces the CLI's own figure exactly (verified across 188 sessions, zero drift) and puts each turn on its own calendar day.

Subagent logs are included — that work spends quota too, and on one machine it came to 478 turns. The walk goes six levels deep rather than looking in one place, because where they sit under ~/.claude/projects varies.

The scan runs when the tab is first opened, never at startup. Logs are append-only, so a byte offset per file is remembered and later scans read only what is new: a full first pass over 91 MB takes about 0.3 s, and a rescan with nothing changed about 10 ms.

Is it worth it?

The Summary tab's Worth it? cards compare each plan's monthly price against what its last 30 days of usage would have cost at public API rates — the same per-token estimate the cost note below uses, just totalled per provider over a fixed 30-day window rather than whatever range is selected elsewhere on the page. A monthly plan only means anything measured against a monthly window.

Enter a price directly in the card (or set claude.subscriptionPriceUsd / codex.subscriptionPriceUsd) and a pill marks the plan Worth it or Not yet. Left at 0, that provider's card shows the 30-day estimate without a verdict. Prices you type in the panel are written back to the same settings, so they persist between sessions.

Why it works this way

Reading local files is the only approach that is unambiguously within both vendors' terms.

Anthropic's Consumer Terms §3 prohibit accessing the Services "through automated or non-human means, whether through a bot, script, or otherwise", except via an Anthropic API Key. OpenAI's Terms of Use prohibit using "any automated or programmatic method to extract data or output from the Services" except through their API.

A third-party tool that calls api.anthropic.com/api/oauth/usage or chatgpt.com/backend-api/wham/usage with the CLI's OAuth token — which is what comparable taskbar monitors do — runs against those clauses. This extension does not do that. The CLIs perform their own authorised fetches; the extension only reads the results they leave behind.

The trade-off is freshness: figures are only as current as the last time each CLI recorded them. That is surfaced rather than hidden — see below.

Keeping it fresh

The CLIs rewrite their cached percentages only occasionally — measured on one machine, Claude Code refreshed roughly hourly even under continuous use, and Codex only while a session is running. Re-reading the files more often cannot help: the number on disk has not changed. Two things address that, both entirely local.

A watcher (watchFiles, on) reads the moment a CLI writes, rather than waiting out refreshInterval. The interval keeps running as a backstop, since a watcher can miss events on network drives.

A projection (estimate.enabled, on) carries the last authoritative figure forward:

estimate = last recorded % + (tokens spent since) × points-per-token

The rate is measured, not assumed. Two consecutive readings an hour apart, with the tokens spent between them from the session logs, give points-per-token directly; every new reading re-measures it, so drift from a model switch corrects itself within the hour. The median of the last few measurements is used, so one skewed interval cannot move the number far. Projected figures are always written ~42%, and the provider's own figure stays visible beside them.

Measuring instead against the start of a window — treating a reset as a known zero, so a single reading would give a rate — was tried and discarded: on real data it disagreed with the differential measurement by 6.6×, because a window's usage is not all visible locally. The consequence is that a window has no projection until two readings land inside it, which is why a freshly reset 5-hour window shows the recorded figure and a staleness marker instead of a guess.

What the projection cannot know:

  • Only this machine. Usage from another device or from claude.ai is invisible to it. Claude Code's own usage breakdown carries the same caveat.
  • Model weighting. A session that switches models mid-interval skews the measured rate until the next reading corrects it.
  • Cache reads. Whatever weight they carry toward a limit is folded into the measured rate rather than modelled, since the logs do not say.

Set estimate.enabled to false to show only the providers' own figures.

Fetching on demand

AI Status: Fetch Current Usage from CLI runs claude -p /usage and takes the percentages from what it prints — the exact figures, right now. Bind it to a status bar click by setting statusBar.click to fetch, or use the Fetch now link in the tooltip.

Measured on one machine, the call reports num_turns: 0 and total_cost_usd: 0: /usage is handled locally by the CLI rather than by the model, so asking does not consume any of the allowance it reports on. It takes about 9 seconds, and the session log it leaves behind contains no assistant turns, so it never appears in the usage table.

It does not always answer. The CLI includes the two rate-limit lines on the first call after a pause and leaves them out of the ones that follow — its own formatRateLimits returns null when it has no rate limits in hand, which drops the whole block. Measured on CLI 2.1.199, six consecutive calls came back 1 reporting and 5 not, and the ones that reported nothing returned in ~90ms against ~500ms for the one that did, so retrying straight away does not help.

A call like that is not treated as a failure, because it is the CLI behaving normally: nothing is carried forward, the figures already on screen stay as they are, and asking for the fetch by hand says so rather than raising a warning. Earlier versions reported it as `/usage` output had no percentages in it, which read like a break in this extension and was the most common thing it ever said.

It is also the only path here that makes the CLI talk to Anthropic, which is why by default it only runs when you ask for it. Anthropic's Consumer Terms §3 prohibit accessing the Services "through automated or non-human means, whether through a bot, script, or otherwise" — a timer doing this would be exactly that, while a person pressing a button is a person using their own account.

autoFetchFromCli (default off) puts it on a timer regardless, every autoFetchInterval seconds (default 300, minimum 60). Turning it on means the exact percentages stay current on their own, with no projection needed — and it means accepting the clause above on your own account, which is why it ships off rather than on. Switching it on from the panel's checkbox asks for confirmation first, citing that same clause, before the setting changes; declining leaves it off and just unchecks the box. A background fetch shows no progress indicator, and a failure goes to the diagnostic log instead of a notification. Each open VS Code window fetches on its own timer, so several windows means several calls per interval.

It also changes what AI Status: Refresh Usage does. By default that command re-reads the files and nothing more, which is honest but looks inert: the CLIs rewrite their percentages roughly hourly, so pressing it normally repaints the figure already on screen. With autoFetchFromCli on, the decision to let the CLI be driven automatically has already been made, so the command runs /usage instead — the same thing the timer does, only sooner. This covers the Refresh link in the tooltip and statusBar.click: refresh as well, since both go through that command.

Opening the detail panel takes the same path, so the default statusBar.click: panel both shows the panel and brings the figures behind it up to date. The panel appears immediately either way — the fetch is not waited on, and the panel updates when it lands.

Each fetch also becomes a true anchor for the projection above, so clicking it twice inside a window is the fastest way to get ~% working after a reset.

Note that /usage does not rewrite the CLI's own cache, so the fetched figures are held in memory and shown until the CLI writes something at least as new.

Staleness

When a CLI has not refreshed its own figures for kiyoAiStatus.staleAfter minutes (default 60), the status bar appends a history icon and the tooltip says how old the numbers are and how to refresh them:

  • Claude Code — run /usage in the CLI
  • Codex — send any message in codex

Language

The detail panel is available in Thai and English, set by language (default th) or by the picker in the panel's own header. Each language is labelled in itself — ไทย, EN — so it can be found without being able to read the current one. Relative times follow the copy (2h ago becomes 2 ชม.ที่แล้ว), while absolute reset times keep the host's locale.

Terms Thai developers normally leave in English — token, cache, session, context, turn, CLI — are kept in English rather than translated. The status bar and its tooltip are English only, as are each provider's own diagnostic messages and source lines, which are mostly file paths and CLI commands and are shared with the tooltip.

Privacy

The extension opens no network connections of its own. The bundle imports fs, fs/promises, os, path, crypto, child_process and vscode — there is no HTTP client in it, and it never reads ~/.claude/.credentials.json, ~/.codex/auth.json, or any other credential store.

child_process is there for one thing only: fetching on demand, which spawns claude -p /usage when you ask it to. The argument list is fixed and no shell is used, so nothing that could be configured gets interpreted as a command. Nothing else in the extension starts a process.

Reading the OAuth token out of the CLI's credential file and calling Anthropic's endpoints directly — which is how comparable taskbar monitors get a live figure — is not something this extension does, and not something it should. Anthropic confirmed in February 2026 that subscription OAuth tokens are only authorised for Claude Code itself, third-party requests now get This credential is only authorized for use with Claude Code, and accounts have been banned over it. Asking the official client to run its own command is the supported way to get the same number.

Being precise about what it does read: to reach cachedUsageUtilization it parses the whole of ~/.claude.json, a file that also holds your account details, project history and any secrets you have put in an MCP server's env; and it reads the last 512 KB of the newest session log, which is conversation text. The usage log tab goes further and reads session logs in full. Only the usage figures are taken out of any of it. Nothing else is kept, displayed, written anywhere, or sent anywhere — the parsed data goes out of scope as soon as the numbers have been extracted.

The usage log's index, in the extension's own global storage directory, holds only token counters, project paths, model names, session ids, the entrypoint/origin strings behind the source axis, and a byte offset per file. No part of a conversation is written to it — a session id is the CLI's own opaque identifier for a log, not anything from inside it. Deleting that directory just makes the next scan a full one.

The two path settings are machine-scoped, so only your user settings can change which files are read; a workspace cannot redirect them. Values that do come off disk — the Codex plan type and log filename — are stripped of markdown syntax before they reach the status bar tooltip, and that tooltip's links are restricted to this extension's own three commands.

Settings

All settings live under kiyoAiStatus.*.

Display

Setting Default Notes
statusBar.window both 5h, 7d, both, or max (whichever is closest to the limit)
statusBar.alignment right left or right
statusBar.priority 100 Higher sits further left
statusBar.showIcon true Logo before the percentage
statusBar.labelStyle full full (Claude Code 42%), short (CC 42%), none (42%)
statusBar.showBar true The ■■■□□ meter
statusBar.barStyle squares squares (■■■□□), blocks (███░░), bars (▰▰▰▱▱)
statusBar.barWidth 5 Cells per bar
statusBar.showWindowLabels true The 5h / 7d prefixes
statusBar.showReset true The reset countdown

To shorten the status bar, turn off showBar, set labelStyle to short or none, or set window to max so only the window nearest its limit is shown. | statusBar.click | panel | panel, refresh, fetch, settings, none | | hideWhenUnavailable | false | Hide rather than show a hint |

Thresholds

Setting Default
thresholds.warning 75
thresholds.critical 90
statusBar.useBackgroundColor false — tint the text only; true highlights the whole item

Data

Setting Default Notes
refreshInterval 300 Seconds between disk reads (5 minutes)
claude.enabled / codex.enabled true
claude.configPath (auto) Override ~/.claude.json (user settings only)
claude.cliPath (auto) Path to the claude executable for fetching on demand; leave empty to find it on PATH
codex.home (auto) Override ~/.codex (user settings only)
claude.subscriptionPriceUsd / codex.subscriptionPriceUsd 0 Monthly plan price in USD, for the Summary tab's Worth it? cards; 0 hides that provider's card
staleAfter 60 Minutes before the stale warning appears
watchFiles true Read the moment a CLI writes, not just on the interval
estimate.enabled true Project the last figure forward as ~42%
language th Panel language, th or en — also switchable in the panel header
autoFetchFromCli false Run claude -p /usage on a timer — read this first
autoFetchInterval 300 Seconds between those fetches (minimum 60)

Re-reads also happen when the VS Code window regains focus, so the numbers are current when you come back to the editor without waiting out the interval. Reset countdowns are recomputed every 30 seconds from the already-loaded data, which costs no disk access.

Commands

  • AI Status: Refresh Usage — re-read what the CLIs have written
  • AI Status: Fetch Current Usage from CLI — run claude -p /usage for the exact figures now
  • AI Status: Show Usage Details
  • AI Status: Open Settings
  • AI Status: Show Diagnostic Log

Build

npm install
npm run compile        # typecheck + bundle to dist/
npm run watch          # rebuild on change
npm run build-icons    # rebuild media/kiyo-ai-icons.woff from media/svg/*.svg
npm run package        # produce a .vsix

The icon font is committed, so build-icons only needs re-running when the SVGs change. Logo sources and their trademark note are in media/svg/ATTRIBUTION.md.

Press F5 to launch an Extension Development Host.

Notes and limits

  • Claude Code's own VS Code extension has an Account & usage dialog with the same 5-hour and 7-day breakdown (Claude Code v2.1.174+). This extension puts the figures on the status bar so they are visible without opening anything.
  • On plans that report only one Codex window (Team accounts report a 7-day primary and no secondary), the missing window shows as —, and the status bar falls back to the window that does exist. Windows are classified by declared length rather than by Codex's primary/secondary labels, so this stays correct across plans.
  • Claude Code's session log does not record the model's context limit, so the tooltip reports the last turn's token count without a percentage rather than guessing a denominator.

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft