Claude CodeClaude Code 2.1 · macOS, Linux, Windows
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
31 small wins to finish your pathNext lesson

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:

FieldWhat it holds
model.display_nameOpus, Sonnet, Haiku
workspace.current_dirWhere the session is running
workspace.git_worktreeThe branch this session is on
context_window.used_percentageHow full the window is
cost.total_cost_usdSession cost so far, estimated
session_id, transcript_pathWhich 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.

Example
"""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.

json
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.py"
  }
}
Or ask for it
/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.

Try it yourself
  • Change the context percentage in session.json to 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.