Show Context Usage and Cost in the Claude Code Status Line

Show Context Usage and Cost in the Claude Code Status Line

Long Claude Code sessions get slower and pricier as the conversation grows, yet nothing on screen tells you when that is happening. The fix is a small script that lets the claude code status line show context usage, an estimated cost and more, all in the row under your prompt. In this guide we built one, ran it in a real session and measured what the numbers actually do.

This is Part 34 of 45 in our Claude Code Deep Dives, part of our Claude Code tutorials. In the last part we covered every CLAUDE.md location, and for the basics of styling the bar itself, see our guide to customizing the status line.

Tested with Claude Code v2.1.322 on November 12, 2026, on macOS. Everything ran in a throwaway demo folder with --setting-sources project, so our personal Claude Code setup stayed untouched. We did not use any Windows or Linux machine; the Windows steps come from Anthropic’s official docs.

Quick Summary

What you want to seeField to readGood to know
How full the context iscontext_window.used_percentageCounts input tokens only, not output
Token count and window sizecontext_window.total_input_tokens and context_window.context_window_sizeSize was 1,000,000 on our model
Session costcost.total_cost_usdAn estimate at list price, not your bill
Cache healthprompt_cache.hit_ratioA number from 0 to 1
Session timecost.total_duration_msIn milliseconds

What the Claude Code Status Line Is

The status line is a bar at the bottom of Claude Code that runs a shell command you choose. Claude Code sends your script a block of JSON about the session on stdin, and whatever your script prints becomes the bar. That makes it the easiest way to keep context usage and cost in view without typing a command.

The official docs say it runs locally and does not use API tokens. So adding one costs you nothing in usage, which is a good reason to try it.

Flow diagram showing Claude Code sending JSON to a script that prints the status line
Claude Code hands your script the numbers; your script decides how to show them

Which Fields Show Context Usage and Cost

The docs list every field your script receives. Four of them cover most of what people want to watch.

  • context_window.used_percentage is a ready-made percentage, so you do not have to do any math.
  • context_window.context_window_size is the maximum size, 200,000 by default or 1,000,000 for models with extended context.
  • cost.total_cost_usd is the running cost of the session.
  • prompt_cache.hit_ratio shows how much of your input is served from the cache.

One detail trips people up. The docs say used_percentage is calculated from input tokens only, meaning input_tokens, cache_creation_input_tokens and cache_read_input_tokens. Output tokens are not part of it.

Claude Code docs table row for context_window.used_percentage highlighted with a red box
The docs field for context percentage, highlighted

The cost field has its own caveat. The docs describe it as an estimate computed on your machine at list price, so it may differ from your actual bill. It also resets to zero when /clear starts a new session.

Claude Code docs table row for cost.total_cost_usd highlighted with a red box
The cost field is an estimate, and the docs say so

Build a Status Line With Context Usage and Cost

You can ask Claude to build one with /statusline and a plain sentence. We wanted full control, so we wrote our own script in a demo project. It prints two lines: a colored bar with token counts, then cost, time and cache hit rate.

Step 1: Write the Script

Save this as .claude/statusline.py in your project. It uses Python, so you do not need jq.

#!/usr/bin/env python3
import json, sys

d = json.load(sys.stdin)
model = d.get("model", {}).get("display_name", "?")
cw = d.get("context_window", {}) or {}
pct = int(cw.get("used_percentage") or 0)
size = cw.get("context_window_size") or 200000
used = cw.get("total_input_tokens") or 0
cost = (d.get("cost", {}) or {}).get("total_cost_usd") or 0
mins = int(((d.get("cost", {}) or {}).get("total_duration_ms") or 0) // 60000)
ratio = (d.get("prompt_cache") or {}).get("hit_ratio")

GREEN, YELLOW, RED, DIM, RESET = "\033[32m", "\033[33m", "\033[31m", "\033[2m", "\033[0m"
color = GREEN if pct < 50 else YELLOW if pct < 80 else RED
filled = pct * 10 // 100
bar = "▓" * filled + "░" * (10 - filled)

print(f"[{model}] {color}{bar} {pct}%{RESET} {DIM}{used:,} / {size:,} tokens{RESET}")
line2 = f"${cost:.2f} · {mins}m"
if ratio is not None:
    line2 += f" · cache hit {int(ratio * 100)}%"
print(line2)

Every field has a fallback, so the script still prints something when a value is missing. That matters early in a session, because the docs say used_percentage may be null before the first response.

Step 2: Make It Runnable and Add It to Settings

Run chmod +x .claude/statusline.py, then add a statusLine entry to .claude/settings.json.

{
  "statusLine": {
    "type": "command",
    "command": "python3 .claude/statusline.py"
  }
}

We put this in the project file so it stays inside the demo. You can put the same block in your user settings instead if you want it everywhere. Our settings guide explains the difference.

Step 3: Test It Before You Trust It

The docs suggest feeding the script fake JSON first, which is much faster than waiting for a real session. We piped three made-up sessions at 20, 65 and 92 percent through it. This output is from our script in a plain terminal, not from Claude Code.

Terminal output of the status line script showing a green bar at 20 percent, yellow at 65 percent and red at 92 percent
Mock input proves the colors work: green, yellow and red

The colors switch at 50 and 80 percent, which are our own picks. Change them to whatever warns you early enough, since the docs do not set any threshold.

See It Work in a Real Session

Next we started Claude Code in the demo folder with --setting-sources project. Before we typed anything, the bar already showed up under the prompt.

Claude Code showing the custom status line at 0 percent context and zero dollars before any prompt
The bar at the start of a fresh session

It read 0 percent, 0 tokens and $0.00. That fits the docs, which say the script runs once when a session starts, before any API call.

After the First Reply

We asked Claude to read a tiny file and explain it in two sentences. When the reply arrived, the bar updated by itself.

Claude Code after one reply, with the status line showing 4 percent, 37,529 tokens, 5 cents and an 86 percent cache hit
After one short reply: 4 percent, 37,529 tokens and about 5 cents

Here is the surprise. A two-sentence answer about a six-line file already used 37,529 input tokens and about five cents.

The file was not the cause. The rest is Claude Code’s own starting context, such as its instructions, tool definitions and skill lists, which you can see by running /context.

The window size shown was 1,000,000 tokens on this model, so 37,529 tokens rounds to 4 percent. On a 200,000 window the same count would read about 19 percent, so always check the size next to the percentage.

After the Second Reply

We then asked for one test case idea. The bar moved again, but only a little.

Claude Code after two replies with the status line showing 37,635 tokens, 5 cents and a 91 percent cache hit
The second reply added only about 100 tokens

Tokens went from 37,529 to 37,635, so the second small prompt added about 100. The cache hit rate rose from 86 to 91 percent. That is what you want to see, since cached input is cheaper than fresh input.

Cost stayed at $0.05 in both screenshots. Our two prompts were tiny, so you would need much longer work before the number visibly climbs. We did not run a long task, so we cannot show a bar near the red zone from a real session.

When the Status Line Refreshes

The bar does not update every second. The docs list the triggers: a new assistant message, /compact finishing, a permission mode change, a Vim mode toggle, a changed command setting, and timers when you configure them.

Claude Code docs list of status line update triggers highlighted with a red box
The official list of events that re-run your script

Updates are debounced at 300ms, and a new update cancels a script that is still running. If your bar shows a clock or other live data, set refreshInterval so it re-runs every N seconds. For context and cost you do not need it, since both only change when a reply arrives.

Read the Numbers Without Fooling Yourself

A few facts keep you from misreading the bar.

  • The percentage is input only, so a very long reply does not move it directly.
  • Right after /compact, the docs say current_usage is null until the next API call, so numbers can look odd for one turn.
  • The cost is an estimate at list price, so use it to compare sessions, not to reconcile a bill.
  • Cost resets with /clear, so a $0.00 after clearing is expected.

If you track memory files and their size, our memory system guide shows where much of that starting context comes from. For a related token worry, see a token usage fix.

The status line costs no tokens, so there is no reason to fly blind on context and cost.

Try It Yourself

Make a tiny project, add the script and settings above, and start Claude Code there. Then paste this prompt and watch the bar change.

Read every file in this folder and summarize each one in one line. Do not edit files.

Run /context afterward and compare its total with the token count on your bar. If you want a challenge, change the thresholds and add cost.total_lines_added so you can see how much code changed.

Common Mistakes

  • Forgetting chmod +x, which leaves the bar blank.
  • Printing to stderr instead of stdout. Only stdout is shown.
  • Using a path that depends on your current folder. Use a project-relative or absolute path you have tested.
  • Making the script slow. The docs warn that slow scripts block updates, so avoid heavy commands.
  • Treating the cost as your invoice.
  • Reading the percentage without looking at the window size.

Pro Tips

  • Test with fake JSON first, then with a real session.
  • Run claude --debug to see your script’s errors when the bar goes blank.
  • Keep the output short, because long lines get truncated on narrow terminals.
  • Use /statusline and describe what you want if you would rather not write the script yourself.
  • Show the cache hit rate only if you care about it. Fewer items make a calmer bar.

Cheat Sheet

Cheat sheet of status line fields for context and cost and the settings used to add them
Status line context and cost in one card

Frequently Asked Questions

Does the Claude Code status line cost tokens?

No. The docs say it runs locally and does not consume API tokens.

How do I show context usage in the status line?

Read context_window.used_percentage from the JSON your script receives and print it, ideally next to context_window_size.

Is the cost in the status line my real bill?

No. It is an estimate at list price and may differ from your actual bill, according to the docs.

Why is my context already at a few percent before I do anything?

Claude Code adds its own instructions, tools and skill lists to every session. In our test, one tiny reply already showed 37,529 tokens.

Why is my status line blank?

Check that the script is executable, prints to stdout and exits cleanly. Run it by hand with fake JSON, or start Claude Code with claude --debug.

Conclusion

A short script is all it takes to keep context usage, estimated cost and cache health on screen while you work. In our real session, the bar showed a 37,529-token starting context, about five cents and a rising cache hit rate, none of which we would have noticed otherwise. Build the script, test it with fake JSON, pick thresholds that suit you, and read the official cost documentation or our overview of Claude for more.

Previous in the series: Part 33: CLAUDE.md Locations

Next in the series: Part 35: Claude Code Stop Hook: Examples You Can Copy.

Newsletter

New AI tools in your inbox

The best new tools and the AI news that matters, in one short email. Unsubscribe any time.

Free · No spam · Unsubscribe any time

✓ Looks like you’re subscribed

Loading Google’s sign-up form…

Looks like you’re already subscribed

Thanks for reading! New AI tools and the AI news that matters will land in your inbox.

Not subscribed yet? Refresh the page to load the sign-up form.

The sign-up form couldn’t load. If you use an ad or content blocker, allow news.google.com and reload the page.

Free instant check before you pay. Takes a few seconds.

Scroll to Top