Skip to content

About

Totalizer for Claude Code — a status line plugin showing context left, prompt-cache tokens, session cost, and Pro/Max usage windows

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

Totalizer for Claude Code

A status line for Claude Code that shows, under the prompt, what the session is spending: the model, how much context is left, the prompt-cache read and write tokens of the last call, the session cost, and your Pro/Max usage windows with their reset countdowns.

image

Version 0.0.2. Python 3 standard library only. Windows, macOS, and Linux.

Install

Add the marketplace and install the plugin from inside Claude Code:

/plugin marketplace add gabgoss/totalizer-for-claude-code
/plugin install totalizer@totalizer-marketplace

Then register the status line. Pick a scope:

/totalizer:install                  # every project on this machine (user scope, full layout)
/totalizer:install project          # this project only
/totalizer:install user compact     # one abbreviated line instead of two

A new session shows it at once. Sessions already open pick it up on their next refresh. The VS Code extension's "Open Claude in terminal" runs the same CLI, so a user-scope install covers it. No terminal profile is needed.

Other commands:

Command Effect
/totalizer:status Shows which scope carries a status line and whether it is Totalizer's.
/totalizer:uninstall [user|project] Removes the registration from that scope.

Scope is a toggle. Installing at one scope removes Totalizer's registration from the other, so one copy is active. Project settings override user settings in Claude Code. A status line from another tool is reported, never removed.

Why the install command exists

A Claude Code plugin cannot set the statusLine setting by itself, so /totalizer:install runs a small installer. It copies statusline.py to ~/.claude/totalizer/ and points the setting at that copy. Claude Code keeps each plugin version in its own cache directory and purges old ones, so pointing at the cache would break on the first update. After a plugin update, run /totalizer:install again to refresh the copy.

The installer can also run by hand from a checkout:

python plugins/totalizer/scripts/install.py --scope user
python plugins/totalizer/scripts/install.py --status
python plugins/totalizer/scripts/install.py --scope user --uninstall

--python picks the interpreter, --project-dir the project root for project scope, --shared writes the committed .claude/settings.json instead of settings.local.json, and --no-copy points the setting at the checkout for development.

What the line shows

Claude Code pipes a JSON snapshot of the session to the script after every assistant message. Every value comes from that payload, except the plan type.

📈 Session: Opus 5/high · Tokens: 129K · Remaining: 87% · Cache Read: 128K · Cache Write: 333 · Cache Status: 🔥 52m
⚡ Usage: Cost: $6.87 · Session (5hr): 48% (resets in 1h) · Weekly (7 day): 70% (resets in 3d)
Full label Compact Source field Rule
📈 Session: Opus 5/high Opus 5/high model.display_name, effort.level Parenthetical dropped from the name.
Tokens: 129K ctx 13% 129k sum of current_usage input + cache_creation + cache_read The true context of the last call. Compact also shows used_percentage.
Remaining: 87% n/a 100 - context_window.used_percentage Share of the model's context window still free. Green above 50, yellow above 20, red below.
Cache Read: 128K cr 128k current_usage.cache_read_input_tokens Served from the prompt cache. The group reads no call yet before the first call and right after a compaction.
Cache Write: 333 cw 333 current_usage.cache_creation_input_tokens Written into the cache by the last call.
Cache Status: 🔥 52m 🔥 52m prompt_cache.warm, prompt_cache.expires_at See "Cache status" under this table. Omitted until a call reports it.
⚡ Usage: Cost: $6.87 $6.87 cost.total_cost_usd Session cost. The ⚡ is a visual cue for the Usage line and carries no data.
Session (5hr): 48% (resets in 1h) 5h 48% ↻1h rate_limits.five_hour Subscription only. Green under 50 used, yellow under 80, red from 80.
Weekly (7 day): 70% (resets in 3d) 7d 70% ↻3d rate_limits.seven_day Same.
Weekly Fable: 86% Fable 86% any other rate_limits key Rendered generically, so a per-model window appears if the CLI sends one.

TOTALIZER_NO_COLOR=1 disables colour.

Cache status

Every message re-sends the whole conversation. The API caches that prefix, so the next call can read it instead of re-processing it. A cache read costs about a tenth of the normal input price. A cache write costs about 1.25 times it. The cache lives for a fixed time after each call (the session's TTL, 5 minutes or 1 hour).

  • 🔥 52m — the cache is warm and expires in 52 minutes. Your next message reads it cheaply.
  • ❄️ cold — the cache expired. Your next message rewrites the whole context at the write price.

On a large session, one message sent after the cache went cold costs more than many sent while it was warm. The countdown tells you where that line is.

Subscription or pay-as-you-go

The usage windows appear only on a subscription. Detection, first match wins:

  1. TOTALIZER_PLAN=payg|sub — explicit override.
  2. ~/.claude/.credentials.json → claudeAiOauth.subscriptionType — present on a claude.ai login (pro, max, team, enterprise), absent on an API-key login. The script reads that one field and nothing else. The field is undocumented, so treat it as best effort.
  3. rate_limits present in the payload — the documented signal (subscribers only). It lags the first API response, so it is the last resort.

On pay-as-you-go the Usage line shows cost only.

The per-model weekly window

/usage shows a per-model weekly line. The documented status-line schema has only five_hour, seven_day, and spend_limit. Live payloads on CLI 2.1.269 carried the first two. The generic branch renders any extra key without a code change. To see what a session receives, run it with TOTALIZER_DUMP=1 and read ~/.claude/totalizer/last-payload.json.

The ledger

Every distinct reading is appended to ~/.claude/totalizer/log.jsonl (override the directory with TOTALIZER_HOME). One file for all projects. A row carries ts, session_id, cwd, project_dir, model, effort, used_percentage, total_input_tokens, current_usage, cost_usd, rate_limits, cache_hit_ratio, transcript_path, version.

Parallel sessions are handled: appends take a lock file (Windows append mode seeks then writes, so two unlocked appends tear each other), and dedupe compares against the newest row of the same session. A writer that cannot get the lock within about 500 ms drops its row rather than delay the status line.

The script never raises. A bad or empty payload still prints a line and exits 0.

Environment variables

Variable Effect
TOTALIZER_HOME Directory for the script copy, log.jsonl, and last-payload.json. Default ~/.claude/totalizer.
TOTALIZER_MODE full or compact. The --mode flag written by the installer wins.
TOTALIZER_PLAN payg or sub. Overrides plan detection.
TOTALIZER_NO_COLOR 1 disables ANSI colour.
TOTALIZER_DUMP 1 also writes the raw payload to last-payload.json.

Development

Layout:

.claude-plugin/marketplace.json     the marketplace this repo serves
plugins/totalizer/                  the shipped plugin (everything under here reaches consumers)
  .claude-plugin/plugin.json
  commands/install.md, status.md, uninstall.md
  scripts/statusline.py, install.py
tests/selftest.py, tests/fixtures/  not shipped

Test:

python tests/selftest.py

Runs the fixtures through the shipped script in a temporary home and checks both layouts, the pay-as-you-go branch, the dedupe, the no-line-ending rule, and eight parallel writers. Expected last line: OK.

Before a release, validate the plugin and confirm the shipped subtree carries no cache or test files:

claude plugin validate plugins/totalizer

The second check is a directory listing of plugins/totalizer/ with no __pycache__ in it.

Roadmap

  • Ledger reset: on the weekly window boundary for Pro/Max, on budget replenishment for pay-as-you-go.
  • Per-model weekly window, once the CLI sends it or another source is documented.

License

Apache License 2.0. See LICENSE.

About

Totalizer for Claude Code — a status line plugin showing context left, prompt-cache tokens, session cost, and Pro/Max usage windows

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages