Skip to content

Instantly share code, notes, and snippets.

@sudopower
Last active July 7, 2026 14:43
Show Gist options
  • Select an option

  • Save sudopower/29e885cfc51487a992628edebe24951a to your computer and use it in GitHub Desktop.

Select an option

Save sudopower/29e885cfc51487a992628edebe24951a to your computer and use it in GitHub Desktop.
Claude Code status line: live context-window meter (auto-detects 200k vs 1M windows)

Claude Code context + usage status line

A tiny, dependency-free Python status line for Claude Code that shows live context-window usage and your account rate limits (the 5-hour session window and the weekly limit), all read from the JSON Claude Code pipes on stdin, at zero API cost.

⏺ Opus 4.8 Β· πŸ“ argus-charts Β· 🧠 325.2k/1.0M 33% β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘ Β· ↑2 out Β· ⏳ 5h 11% β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ Β· πŸ“† wk 34% β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘

It reads Claude Code's native context_window object (v2.1.132+) for the context meter, so the denominator is always correct: it auto-detects 200k vs 1M extended-context windows instead of hardcoding a per-model table. Falls back to parsing the transcript on older Claude Code.

For Claude.ai Pro/Max accounts it also reads the rate_limits object (five_hour and seven_day) and renders each as its own accent-coloured bar. That block only appears after the session's first API response; API-key sessions simply show the context meter, and any window that is missing is skipped.

Install

# 1. Save the script
curl -L <raw-gist-url>/statusline-context.py -o ~/.claude/statusline-context.py

# 2. Point Claude Code at it, add to ~/.claude/settings.json:
{
  "statusLine": {
    "type": "command",
    "command": "python3 /Users/YOU/.claude/statusline-context.py",
    "padding": 0
  }
}

Restart Claude Code. The status line runs locally and costs zero API tokens.

Colours

  • Context (🧠): 🟒 green under 50%, 🟑 yellow under 80%, πŸ”΄ red beyond, so you notice before auto-compaction hits.
  • Session (⏳ 5h): blue accent, escalates to yellow past 60% and red past 80%.
  • Weekly (πŸ“† wk): magenta accent, same escalation.

Needs Python 3. No third-party packages.

#!/usr/bin/env python3
"""Claude Code status line: live context / token-usage meter.
Claude Code pipes session JSON on stdin. As of CC v2.1.132 the payload carries
a native `context_window` object with the real window size and current usage β€”
including the correct denominator for extended-context (1M) models. We use it
directly so the meter auto-detects the window instead of guessing per model.
For older Claude Code (no `context_window`) we fall back to the transcript:
`transcript_path` is a JSONL log where each assistant turn records
`message.usage`, and context occupancy = input + cache_read + cache_creation.
The same stdin payload also carries a `rate_limits` object for Claude.ai
Pro/Max accounts (present after the first API response of a session):
`five_hour` is the rolling session limit and `seven_day` is the weekly account
limit, each with a `used_percentage`. We render those as their own meters, so
the line shows both how full the window is and how much of the plan is spent β€”
all from stdin, so still zero API cost.
"""
import sys, json, os
# Fallback denominator only β€” used when the native context_window object is
# absent (pre-2.1.132 Claude Code). Current Claude Code reports the true
# window (200k, or 1M for extended-context models) on stdin, so no table is
# consulted in normal operation.
DEFAULT_LIMIT = 200_000
def c(code, s): return f"\033[{code}m{s}\033[0m"
DIM, CYAN, GREEN, YELLOW, RED, BLUE, MAGENTA = "2", "36", "32", "33", "31", "34", "35"
def human(n):
if n >= 1_000_000:
return f"{n/1_000_000:.1f}M"
if n >= 1000:
return f"{n/1000:.1f}k"
return str(n)
def bar(pct, width=10):
"""A width-cell block meter for a 0-100 percentage."""
filled = min(width, int(pct / 100 * width))
return "β–ˆ" * filled + "β–‘" * (width - filled)
def limit_col(pct, accent):
"""Rate-limit colour: each meter keeps its own accent until it fills, then
escalates to yellow/red so a nearly-spent limit stands out at a glance."""
if pct >= 80:
return RED
if pct >= 60:
return YELLOW
return accent
def last_usage(path):
"""Return the most recent usage dict from the transcript, or None."""
try:
with open(path, "r") as f:
lines = f.readlines()
except Exception:
return None
for line in reversed(lines):
line = line.strip()
if not line or '"usage"' not in line:
continue
try:
obj = json.loads(line)
except Exception:
continue
msg = obj.get("message") or {}
usage = msg.get("usage") or obj.get("usage")
if isinstance(usage, dict) and usage.get("input_tokens") is not None:
return usage
return None
def main():
try:
d = json.load(sys.stdin)
except Exception:
print("🧠 ctx ?")
return
parts = []
model_obj = d.get("model") or {}
model = model_obj.get("display_name") or "Claude"
parts.append(c(CYAN, f"⏺ {model}"))
cur = (d.get("workspace") or {}).get("current_dir") or d.get("cwd") or ""
if cur:
parts.append(c(DIM, f"πŸ“ {os.path.basename(cur.rstrip('/')) or cur}"))
# Prefer Claude Code's native context_window object (v2.1.132+): it carries
# the true window size β€” auto-detecting 1M extended-context models β€” and the
# current occupancy, so we never divide by a guessed denominator.
cw = d.get("context_window") or {}
ctx = cw.get("total_input_tokens")
limit = cw.get("context_window_size")
out = cw.get("total_output_tokens")
# Fallback for older Claude Code with no context_window object.
if not limit:
limit = DEFAULT_LIMIT
if ctx is None:
usage = last_usage(d.get("transcript_path", ""))
if usage:
ctx = (usage.get("input_tokens", 0)
+ usage.get("cache_read_input_tokens", 0)
+ usage.get("cache_creation_input_tokens", 0))
out = usage.get("output_tokens")
if ctx:
pct = cw.get("used_percentage")
if pct is None:
pct = ctx / limit * 100
col = GREEN if pct < 50 else (YELLOW if pct < 80 else RED)
parts.append(c(col, f"🧠 {human(ctx)}/{human(limit)} {pct:.0f}% {bar(pct)}"))
if out:
parts.append(c(DIM, f"↑{human(out)} out"))
else:
# nothing to report yet (before first API call, or just after /compact)
flag = d.get("exceeds_200k_tokens")
parts.append(c(RED if flag else DIM, "🧠 200k+" if flag else "🧠 …"))
# Account rate limits (Claude.ai Pro/Max only; present once the session has
# made an API call). five_hour is the rolling session limit, seven_day the
# weekly account limit. Each is its own accent-coloured meter, and any window
# may be independently absent, so we skip whatever is missing.
rl = d.get("rate_limits") or {}
for key, icon, label, accent in (("five_hour", "⏳", "5h", BLUE),
("seven_day", "πŸ“†", "wk", MAGENTA)):
pct = (rl.get(key) or {}).get("used_percentage")
if pct is None:
continue
parts.append(c(limit_col(pct, accent), f"{icon} {label} {pct:.0f}% {bar(pct)}"))
print(c(DIM, " Β· ").join(parts))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment