The statusline, and output styles
The bar at the bottom of the screen runs a program you choose. It gets the session as JSON and prints one line, so it can show anything you can compute.
This matters more than decoration. The two numbers that decide how a long session goes, how full the context window is and what it has cost so far, are both in that JSON and neither is on screen by default.
What it is sent
Claude Code runs the script when something in the session changes, debounced so a burst of changes becomes one run, and writes the session to its standard input as JSON. There is a refreshInterval setting when you want it re-run on a timer as well. The useful fields, out of a longer list:
| Field | What it holds |
|---|---|
model.display_name | Opus, Sonnet, Haiku |
workspace.current_dir | Where the session is running |
workspace.git_worktree | The branch this session is on |
context_window.used_percentage | How full the window is |
cost.total_cost_usd | Session cost so far, estimated |
session_id, transcript_path | Which session this is, and its transcript file |
A statusline you can run
The panel beside this has a real one. It reads the JSON Claude Code sends, exactly as documented, and prints a line with the branch, a context bar and the cost. Press Run.
"""A statusline is a program that reads JSON and prints one line.
Claude Code runs it when the session changes and puts the output
at the bottom of the screen. This is the JSON it sends, cut down
to the fields worth showing.
"""
import json
data = json.loads(open("session.json").read())
model = data["model"]["display_name"]
folder = data["workspace"]["current_dir"].rstrip("/").split("/")[-1]
branch = data["workspace"].get("git_worktree") or "no branch"
used = data["context_window"]["used_percentage"]
cost = data["cost"]["total_cost_usd"]
bar = "#" * (used // 10) + "." * (10 - used // 10)
print(f"[{model}] {folder} on {branch} {bar} {used}% context ${cost:.2f}")On your machine it is the same program with the JSON arriving on standard input instead of from a file, and one line of settings pointing at it.
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.py"
}
}/statusline writes one for you. Describe what you want to see in plain English and it generates the script and wires up the setting. Reading what it produced is a decent way to learn the JSON.Output styles, in a paragraph
An output style changes how Claude writes back to you rather than what it can do: shorter, more explanatory, or in a house format. It shows up in that same JSON as output_style.name. It is worth knowing the feature exists, and worth leaving alone until the default annoys you.
- Change the context percentage in
session.jsonto 94 and run it again. - Add the rate limit fields to your own statusline and see how close you run to them.
This is what real progress feels like.