Skip to main content

Claude Code Status Line: Live Usage, Context & Reset Timers

A custom Claude Code status line with context usage, plan limits, reset countdowns and colour-coded bars, plus a safe install and uninstall guide.

Updated 16 min readMarkdown
Claude Code Status Line: Live Usage, Context & Reset Timers

When I work in Claude Code, I keep asking the same questions: how full is this conversation, how much of my 5-hour and weekly limit have I used, and when does it reset? Built-in commands answer each one, but only when I stop and run them. I wanted the answers on screen all the time, next to the model, the git branch and the session's estimated cost.

Claude Code supports this through its status line, a row at the bottom of the terminal that shows whatever a script of yours prints. This post covers the status line I use every day: what it shows, how to install it safely, how it works, the design mistakes I made building it, and how to remove it again.

The status line: live dot and branch, session ID, model, context bar, 5-hour bar with reset countdown, weekly bar and estimated session cost

The finished status line. In the terminal it's one row; it's split in two here so the labels fit.

Shortcut: let Claude Code do it for you

Use Claude Code? Open the original post and click Copy Claude Code prompt. Paste it into Claude Code and it does the setup for you: it downloads the installer, tells you what it will change and asks before running it.

Not using Claude Code? Follow the steps below by hand.

What the status line shows

● main │ Session: 1fb4ade2 │ Opus 5.5 │ ctx ■■■□□□□□  32% │ 5h ■□□□□□□□   4% ↻03:20 │ wk ■■■■■□□□  65% │ Est. usage: $6.44
Segment What it is Where it comes from
● main Git branch, or the folder name outside a repo Read locally with git on every run
Session: 1fb4ade2 First 8 characters of the session ID session_id
Opus 5.5 The current model model.display_name
ctx bar How full the conversation's context window is context_window.used_percentage
5h bar + ↻03:20 Use of your 5-hour limit, and the time until it resets rate_limits.five_hour
wk bar Use of your weekly (7-day) limit rate_limits.seven_day
Est. usage Estimated cost of this session in US dollars cost.total_cost_usd

Each bar is 8 squares; the filled part is coloured and the rest stays dark grey (shown as □ above).

Not every value is equally fresh:

  • Live, worked out on your machine: the git branch, the ↻ countdown (your clock compared with the reset time) and the animation.

  • Updated when Claude Code gets a new response: the ctx, 5h and wk percentages and the cost. The script redraws every second, but these numbers only change when Claude Code itself receives new data.

  • An estimate: Est. usage is computed by Claude Code at list price and resets to $0 when /clear starts a new session. It may differ from your actual bill, and on a Pro or Max plan it isn't a charge at all.

  • Sometimes unavailable: if a field is missing, its segment is simply left out. Nothing is guessed.

Prerequisites and compatibility

  • Claude Code with status line support. I built and tested this with Claude Code 2.1.292 on macOS (Apple Terminal).

  • bash, plus jq or python3 (the installer uses one of them to edit your settings, and the script uses one to read Claude Code's data). Check with which jq python3.

  • git (optional) for the branch segment.

  • A terminal with 256-colour support. Almost every modern terminal has it.

  • For the 5h and wk bars: a Claude.ai Pro or Max subscription. Claude Code only sends the 5-hour and weekly limits to Pro and Max subscribers, and only after the first API response in a session. With an API key, Amazon Bedrock or Google Vertex, those two segments don't appear; the rest still works.

It's written for macOS and Linux. I've only tested it on macOS. On Windows, Claude Code runs status line commands through Git Bash or PowerShell; this bash script may work under Git Bash, but I haven't tested it.

Optional: make the terminal nicer for prompts

This is separate from the status line, but it's the first thing I set up. Run this inside Claude Code:

/terminal-setup

What it does depends on your terminal:

Terminal What /terminal-setup changes
Apple Terminal (macOS) Turns on "Use Option as Meta Key" and turns off the audible bell (the bell is left on in screen reader mode)
iTerm2 Lets terminal apps access the clipboard, so /copy works (restart iTerm2 afterwards)
VS Code, Cursor, Devin Desktop, Alacritty before 0.16, Zed Adds a Shift+Enter key binding for new lines. In VS Code, Cursor and Devin Desktop it also turns off the integrated terminal's GPU acceleration and adjusts scroll sensitivity

If you accepted Claude Code's terminal setup prompt on first run, this has already been done. With Option as Meta, these shortcuts work:

Option+Enter adds a second line to the prompt; Option+Left jumps the cursor back one word at a time

Option+Enter for a new line, Option+Arrow to move by word.

Keys Action
⌥ + Enter New line inside your message
⌥ + ← / ⌥ + → Jump back / forward one word
⌥ + Delete Delete the previous word
⌥ + D Delete the next word

In any terminal, Ctrl+J or typing \ then Enter also adds a new line, and Shift+Enter already works in Apple Terminal, iTerm2 and several others without setup.

Trade-off: with Option as Meta, Option no longer types characters like ©, € or ñ in Terminal. To undo it, untick Terminal → Settings → Profiles → Keyboard → "Use Option as Meta Key".

Install

The installer is a single bash file. Download it, read it, then run it:

curl -fsSL https://siddarammetri.in/blog/claude-code-status-line/install.sh \
  -o /tmp/statusline-install.sh
less /tmp/statusline-install.sh   # read it first (q to quit)
bash /tmp/statusline-install.sh

Read scripts before you run them. Don't pipe curl straight into bash, for this installer or any other. The file is short, and the top of it lists exactly what it changes.

It makes exactly these changes, and nothing else:

File Change Backup
~/.claude/statusline-command.sh Written (replaced if it already exists) and made executable An existing file is copied to statusline-command.sh.bak-<date-time> first
~/.claude/settings.json Created if missing. Its statusLine entry is set to run the script every second; a statusLine you already had is replaced. Your other settings are kept The file is always copied to settings.json.bak-<date-time> first

It doesn't touch your terminal, fonts or shell configuration.

A successful run looks like this (in your terminal the bars are coloured):

✓ Wrote /Users/you/.claude/statusline-command.sh
✓ Updated /Users/you/.claude/settings.json (backup: /Users/you/.claude/settings.json.bak-20261019-031500)

Preview with sample data:
● main │ Session: 1fb4ade2 │ Opus 5.5 │ ctx ■■■■■■■■  32% │ 5h ■■■■■■■■   4% ↻03:20 │ wk ■■■■■■■■  65% │ Est. usage: $6.44

Done. It appears at the bottom of Claude Code within a second (bars show after the first reply).
Undo: restore /Users/you/.claude/settings.json.bak-20261019-031500

The preview uses sample numbers, not your real usage.

Check that it worked

  1. Confirm the setting is in place:

    jq .statusLine ~/.claude/settings.json
    

    You should see "type": "command", "command": "bash /Users/you/.claude/statusline-command.sh" and "refreshInterval": 1.

  2. Start Claude Code (claude) and send any message. The branch, session and model appear straight away; the ctx, 5h, wk and cost segments appear after the first reply.

If the install fails

Message or symptom What it means Fix
Couldn't find jq or python3 Neither is installed. The script was written, but no statusLine was added (a backup copy of settings.json was still made). The status line script also needs one of them to read Claude Code's data Install one (brew install jq on macOS) and run the installer again
A jq parse error or a Python JSONDecodeError Your settings.json isn't valid JSON, so it was left unchanged Fix the file (jq . ~/.claude/settings.json shows where), then run the installer again
curl: (22) … 404 The download URL is wrong Copy the command again; the file lives under /blog/, not /blogs/

Configure and customize

The installer adds this to ~/.claude/settings.json:

{
  "statusLine": {
    "type": "command",
    "command": "bash /Users/you/.claude/statusline-command.sh",
    "refreshInterval": 1
  }
}

refreshInterval re-runs the script every N seconds in addition to Claude Code's normal updates. One second keeps the countdown and animation moving. On my Mac one run takes about 0.1 seconds; raise the number if you'd rather it ran less often, or remove the line to update only on events.

Everything else lives in ~/.claude/statusline-command.sh:

To change Edit
Bar length BAR_WIDTH=8
Colour thresholds the level() function (50 / 80 / 90 / 95%)
Colours the 256-colour numbers in level() and glow()
Bar character the ■ in the bar() function (▬ and ▄ also work)
Which segments show the lines that build out+= near the bottom; delete one to hide it

Your changes show up the next time the script runs. The installer overwrites the script, so re-running it replaces your edits (the previous version is backed up first).

How it works

Claude Code sends JSON on stdin to your script, which prints text on stdout that appears in the status bar

Claude Code supplies the data; the script decides how it looks.

The status line is an official Claude Code feature:

  1. Claude Code runs your command and passes the session's details to it as JSON on stdin.

  2. Your script prints one line of text (more lines are allowed; ANSI colours are fine).

  3. Claude Code shows that output at the bottom of the terminal.

It runs locally and doesn't use API tokens. Claude Code re-runs it when a session starts, when a new assistant message arrives, after /compact, when the permission mode changes, when a refreshInterval timer elapses, and when a usage window reaches its reset time. Updates are batched over about 300 ms.

The fields this script reads look like this (trimmed; Claude Code sends more):

{
  "session_id": "1fb4ade2-…",
  "model": { "display_name": "Opus 5.5" },
  "workspace": { "current_dir": "/Users/you/project" },
  "cost": { "total_cost_usd": 6.44 },
  "context_window": { "used_percentage": 32 },
  "rate_limits": {
    "five_hour": { "used_percentage": 4, "resets_at": 1792371600 },
    "seven_day": { "used_percentage": 65, "resets_at": 1792890000 }
  }
}

resets_at is a Unix timestamp in seconds. A few fields come and go, and the script handles each one:

  • The 5-hour and weekly rate_limits are only sent to Pro and Max subscribers, only after the first response, and each window can be missing on its own. Claude Code drops a window once its reset time passes, so a bar can briefly disappear right after a reset.

  • context_window.used_percentage can be empty early in a session.

  • The script reads every field with a fallback, so a missing field means a missing segment rather than an error.

Design decisions (and mistakes)

Colours that mean something

One colour for everything tells you nothing. Each bar changes colour at four points:

Bars at 25, 55, 85, 92 and 97 percent in green, yellow, orange, red and blinking bright red

Each bar is coloured on its own, so a green context bar can sit next to a yellow weekly bar.

Usage Colour Meaning
below 50% green Plenty left
50–79% yellow Halfway
80–89% orange Slow down
90–94% red Nearly out
95%+ bright red, blinking About to hit the limit

The bar character matters more than you'd think

My first version used full blocks (█), which were far too chunky. The thin line ━ disappeared. Then I tried the lower ¾ block ▆, and it looked wrong without me knowing why: the bars seemed to sit lower than the text.

That's exactly what was happening. Block characters are anchored to the bottom of the character cell, so ▆ hangs below the baseline. A square ■ is centred in the cell and lines up with the letters.

The lower block hangs below the text baseline; the square is centred and lines up

Same font, same size: the block sits low, the square lines up with the text.

I found this by rendering each candidate next to text in the same font and comparing them, rather than guessing. And one rule I'd keep: don't change your terminal font to make a status line look right. Change the characters instead.

Numbers that don't make the line jump

4% is narrower than 19%, so everything after it shifted sideways whenever a value crossed 10%. Padding every number to three characters (printf '%3s') keeps every separator in a fixed place.

Animation with one frame per second

A shell script can't animate on its own, but with refreshInterval: 1 each run is a frame. The script uses the current second (date +%s) to move a lighter "shine" square along each bar, pulse the leading square so even a one-square bar visibly moves, blink the whole bar from 95%, and pulse the ● dot.

Troubleshooting and limitations

Problem Fix
Nothing appears Run jq .statusLine ~/.claude/settings.json to check the setting, then test the script by hand: `echo '{"model":{"display_name":"Test"}}'
Only branch, session and model show Normal before the first reply; the other values arrive with it
5h / wk never appear You're not on a Pro or Max plan in this session (for example an API key, Bedrock or Vertex), so Claude Code sends no plan-limit data
A bar vanishes right after a reset Claude Code drops the expired window; it comes back with the next reply
Usage looks out of date The numbers update with Claude Code's responses. If you've used Claude elsewhere, send a message here or run /usage
Squares look misaligned or gappy Font-dependent. Swap ■ for ▬ or ▄ in bar(), and keep your font
Line too long for the window Lower BAR_WIDTH, or remove the Session: segment

Claude Code's built-in commands are still useful for anything the line doesn't show:

Command Shows
/usage Session cost, plan usage limits and activity stats (/cost and /stats are aliases)
/context A coloured grid of what's using the context window
/status Version, model, account and connectivity
/statusline Claude Code's own helper for setting up a status line

Known limitations:

  • The 5h and wk bars need a Pro or Max plan; the spend-limit data a Claude apps gateway can send isn't shown.

  • Tested only on macOS with Apple Terminal. Linux should behave the same; Windows is untested.

  • How ■ looks depends on your font.

Uninstall and recovery

There's no uninstall script, so here are the manual steps.

Easiest: run /statusline remove it inside Claude Code, which removes the statusLine setting for you. Then delete the script with rm ~/.claude/statusline-command.sh.

Or remove it by hand, keeping every other setting:

jq 'del(.statusLine)' ~/.claude/settings.json > /tmp/claude-settings.json \
  && mv /tmp/claude-settings.json ~/.claude/settings.json
rm ~/.claude/statusline-command.sh

Or restore your settings from the installer's backup:

ls ~/.claude/settings.json.bak-*            # pick the one from before the install
cp ~/.claude/settings.json.bak-<date-time> ~/.claude/settings.json

Restoring a backup also undoes any other settings changes you've made since, so the first option is usually better. If you had a status line script before, the installer kept it as ~/.claude/statusline-command.sh.bak-<date-time>; rename it back to bring it back. Once you're happy, you can delete the .bak- files.

FAQ

Does it make extra API requests or use tokens? No. The script only reads the data Claude Code passes to it and runs git locally. Claude Code states that the status line doesn't consume API tokens.

Does it work with an API key, Bedrock or Vertex? Mostly. The branch, session, model, context bar and estimated cost work. The 5h and wk bars don't appear, because Claude Code only sends plan-limit data to Pro and Max subscribers.

How often does it refresh? The script runs every second (refreshInterval: 1), and Claude Code also re-runs it after events such as each reply or a usage window resetting. The countdown and animation change every second; the usage and cost numbers change only when Claude Code receives new data.

What happens when data is unavailable? That segment is left out. The script never fills in or estimates a value.

How do I change the colours or bars? Edit ~/.claude/statusline-command.sh: BAR_WIDTH, the level() thresholds and colours, and the ■ character in bar(). See Configure and customize.

How do I turn it off? Run /statusline remove it, or delete the statusLine entry from ~/.claude/settings.json (see Uninstall and recovery). Claude Code goes back to its default bottom bar.

Wrap-up

  • Claude Code sends the data; a short bash script decides how it looks.

  • refreshInterval: 1 keeps the countdown and animation live, while usage numbers update with each response.

  • Pick characters that line up with your text, keep numbers fixed-width, and colour by meaning.

The full script is inside the installer, so you can read it before running anything. The official status line documentation lists every field Claude Code sends if you want to add your own segments. More posts are on my blog.


Originally published on siddarammetri.in.

No comments yet. Be the first to comment.