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

Statusline and output styles

A statusline is a program that reads the session as JSON and prints one line at the bottom of the screen.

Last updated: 28 Sep, 2026 · Claude Code

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.

The statusline is 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

A real statusline reads the JSON Claude Code sends, exactly as documented, and prints a line with the branch, a context bar and the cost.

Reading the session JSON

The script reads the session Claude Code hands it as JSON.

python
import json

# the session Claude Code writes to the script
data = json.loads(open("session.json").read())

Pulling the fields worth showing

Pull the model, the folder, the branch, the context percentage and the cost out of that JSON.

python
model = data["model"]["display_name"]
folder = data["workspace"]["current_dir"].rstrip("/").split("/")[-1]
branch = data["workspace"].get("git_worktree") or "no branch"  # None when off a branch
used = data["context_window"]["used_percentage"]
cost = data["cost"]["total_cost_usd"]

Drawing a context bar and printing the line

Turn the percentage into a ten-character bar and print the single line the status bar shows.

python
# ten characters: filled for the used share, dots for the rest
bar = "#" * (used // 10) + "." * (10 - used // 10)

print(f"[{model}] {folder} on {branch}  {bar} {used}% context  ${cost:.2f}")

A statusline line from real session JSON

Save the session JSON as session.json next to the script:

json
{
  "session_id": "abc123",
  "model": {
    "id": "claude-opus-5-5",
    "display_name": "Opus"
  },
  "workspace": {
    "current_dir": "/Users/you/link-shortener",
    "project_dir": "/Users/you/link-shortener",
    "git_worktree": "fix-collisions"
  },
  "output_style": {
    "name": "default"
  },
  "cost": {
    "total_cost_usd": 0.01234,
    "total_duration_ms": 45000,
    "total_lines_added": 156,
    "total_lines_removed": 23
  },
  "context_window": {
    "total_input_tokens": 15500,
    "total_output_tokens": 1200,
    "context_window_size": 200000,
    "used_percentage": 8,
    "remaining_percentage": 92
  },
  "exceeds_200k_tokens": false
}
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.
PreviousSkills

This is what real progress feels like.