---
title: Customizing the Claude Code statusline
description: Did you know Claude Code has a customizable status bar similar to
  Oh-My-Posh? I didn't until Anthropic chose to remove context tracking from the
  default interface. And I'm glad they did, because the alternative is pretty
  neat.
date: 2026-08-12
tags:
  - ai
url: https://skurekjakub.dev/blog/cc-statusline
author: Jakub Skurek
---

> Agent instructions:
> Take page paths from the index rather than constructing them — guessed paths 404. Links inside this document already point at `.md`; following them, or sending `Accept: text/markdown`, keeps you in Markdown.
> When citing this page, use the `url` in its frontmatter — the HTML page; this `.md` address is a rendering of it.
>
> - [llms.txt](https://skurekjakub.dev/llms.txt) — every page with a Markdown twin, with descriptions.
> - [skill.md](https://skurekjakub.dev/skill.md) — how to read this site as an agent.

A couple of months ago Claude Code (CC) really ticked me off. For seemingly no reason, a random update got rid of the default context window token tracker in the bottom right corner.

My first thought was a corrupted installation or a temporary regression, because I simply refused to believe they would remove such a useful feature. Back then, not all models shipped with million-token context windows, and having at-a-glance info for how close you were to a compaction was extremely useful. You could still access the information via `/context`, but having to use a slash command felt way worse than if it were gone forever.

Anyway, that change finally caused me to read the docs and discover **statusline**: <https://code.claude.com/docs/en/statusline>

The basic idea is that each CC session exposes metadata about its state and progress (see [Extras](#extras) for details), and you can choose to display and format them as you like under the input bar.

![A Claude Code session pipes its metadata as JSON to statusline.sh on stdin; the script extracts fields with jq, formats them, and prints one ANSI line that renders under the input bar. The loop repeats on every update.](https://skurekjakub.dev/blog/cc-statusline/statusline-flow.drawio.svg)

_JSON in on stdin, formatted line out._

A simple implementation can look like this:

![Status line example](https://skurekjakub.dev/blog/cc-statusline/cc-statusline.webp)

Which under the hood is just a few lines of bash:

```bash
# Reads the session metadata
input=$(cat)

# Extracts info from session context
model=$(echo "$input" | jq -r '.model.display_name // "claude"')
dir=$(echo "$input" | jq -r '.workspace.current_dir // ""')
size=$(echo "$input" | jq -r '.context_window.context_window_size // 0')
pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0')

# Tokens currently sitting in the context window
used=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')

# ... 

# Composes and prints the data
separator="${DIM} · ${RESET}"
line="${CYAN}${model}${RESET}"
line="${line}${separator}${context_color}$(human "$used")/$(human "$size") (${pct}%)${RESET}"

printf '%s\n' "$line" 

```

(Download the full annotated script here: [statusline.sh](https://skurekjakub.dev/downloads/statusline/statusline.sh))

The version I actually run lives on GitHub: [skurekjakub/cc-statusline](https://github.com/skurekjakub/cc-statusline). Same idea, but tuned for a one-second refresh (a single `jq` pass, no `git` subprocess), with an effort indicator and a prompt cache expiration countdown to better manage individual sessions.

The nice thing is that just like with any other piece of software nowadays, you can use Claude itself to make it. CC exposes the `/statusline` slash command where you simply describe what you want and watch the magic happen.

The prompt I used to make the statusline above was:

```prompt
/statusline Make a statusline that displays the currently selected model, 
the current branch and folder, and context window usage formatted as X/Y (%) 
```

## Pushing statusline boundaries

On the surface this all looks fairly simple. You're given the tools to put together a summary of data that you want to keep close at hand. Well, as it turns out, you can take it much further.

### Track the session as a boss fight

The Speedrun/Gaming entry in [this set of ten themes](https://www.dontsleeponai.com/statusline) visualizes context exhaustion as a boss health bar.

```prompt
Make an RPG HUD statusline.

Line 1: a heart matching current context window usage (💚 under 50%, 💛 60-70%, 🧡 70-80%,
❤️ 80-85%, ☠️ over 85%). Follow this by a "Lvl." indicator which is cost.total_lines_added divided by 100.
Then the model name and the directory basename. Then a 10-heart HP
bar draining as context usage rises, each heart is 10%: ❤️ for remaining, 💔 for the one
being lost now, 🖤 for gone. Then the percentage.

Line 2: a banner keyed to the same percentage. Under 60% "⚔️ exploring". 60-70%
"⚔️ CHECKPOINT: consider a handoff". 70-80% "🛡️ BOSS INCOMING". 80-85% "💀 BOSS FIGHT,
/compact now". Over 85% "☠️ auto-compact imminent".
```

And the zero-shot output produced by Opus 5: [rpg-hud.sh](https://skurekjakub.dev/downloads/statusline/rpg-hud.sh)

![Statusline showing a green heart, Lv.9, the model name, the repo, a ten-heart HP bar at 25% context, and an 'exploring' banner](https://skurekjakub.dev/blog/cc-statusline/rpg-hud.webp)

_Tested in a session as I'm writing this_

### Track your CO₂ emissions

[claude-carbon](https://github.com/gwittebolle/claude-carbon) uses research from [How Hungry is AI? - Jegham et al. 2025](https://arxiv.org/abs/2505.09598) to estimate your session's carbon footprint.

```prompt
Add a live CO2 estimate next to the session cost, one line. Multiply per model context window by the following values: Haiku 20 input / 413 output, Sonnet 39 / 826, Opus 78 / 1652, Fable 156 / 3304.

Print to one decimal place, prefixed 🌱 under 100g,
🌤 under 1kg, 🏭 above. Accumulate a per-session total in ~/.claude/carbon/<session_id>
and a daily total in ~/.claude/carbon/<YYYY-MM-DD>, rendered together like
"12.4g / 1.2kg today".
```

And the zero-shot output produced by Opus 5: [carbon.sh](https://skurekjakub.dev/downloads/statusline/carbon.sh)

![Statusline showing the model name, a context bar at 26%, a session cost of $27.5531, and 21.1g of CO2e for the session against 64.5g for the day](https://skurekjakub.dev/blog/cc-statusline/carbon.webp)

_Tested in a session as I'm writing this_

### Track external data

You can also add and track data external to the session.

```prompt
Add the following statusline:

Line 1: model name, current directory basename, git branch.
Line 2: a context bar, the percentage, cost.total_cost_usd, and
session duration from cost.total_duration_ms.
Line 3: the time as HH:MM, then the temperature and condition for Prague from
"wttr.in/Prague?format=%t+%C", then the BTC spot price from
"api.coinbase.com/v2/prices/BTC-USD/spot".
```

And the zero-shot output produced by Opus 5: [ambient.sh](https://skurekjakub.dev/downloads/statusline/ambient.sh)

![External data in a status line](https://skurekjakub.dev/blog/cc-statusline/ambient.webp)

_Tested in a session as I'm writing this_

## Extras

The full payload that you can access from inside the script as of CC 2.1.228 is listed here. For the latest info, read the official docs: <https://code.claude.com/docs/en/statusline#available-data>

**Full session metadata JSON**

```json
{
  "cwd": "/current/working/directory",
  "session_id": "abc123...",
  "session_name": "my-session",
  "prompt_id": "550e8400-e29b-41d4-a716-446655440000",
  "transcript_path": "/path/to/transcript.jsonl",
  "model": { "id": "claude-opus-5", "display_name": "Opus" },
  "workspace": {
    "current_dir": "/current/working/directory",
    "project_dir": "/original/project/directory",
    "added_dirs": [],
    "git_worktree": "feature-xyz",
    "repo": { "host": "github.com", "owner": "anthropics", "name": "claude-code" }
  },
  "version": "2.1.90",
  "output_style": { "name": "default" },
  "cost": {
    "total_cost_usd": 0.01234,
    "total_duration_ms": 45000,
    "total_api_duration_ms": 2300,
    "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,
    "current_usage": {
      "input_tokens": 8500,
      "output_tokens": 1200,
      "cache_creation_input_tokens": 5000,
      "cache_read_input_tokens": 2000
    }
  },
  "exceeds_200k_tokens": false,
  "fast_mode": false,
  "effort": { "level": "high" },
  "thinking": { "enabled": true },
  "rate_limits": {
    "five_hour": { "used_percentage": 23.5, "resets_at": 1738425600 },
    "seven_day": { "used_percentage": 41.2, "resets_at": 1738857600 }
  },
  "vim": { "mode": "NORMAL" },
  "agent": { "name": "security-reviewer" },
  "pr": {
    "number": 1234,
    "url": "https://github.com/anthropics/claude-code/pull/1234",
    "review_state": "pending"
  },
  "worktree": {
    "name": "my-feature",
    "path": "/path/to/.claude/worktrees/my-feature",
    "branch": "worktree-my-feature",
    "original_cwd": "/path/to/project",
    "original_branch": "main"
  }
}
```

---

Sources:

- <https://code.claude.com/docs/en/statusline>
- <https://github.com/skurekjakub/cc-statusline>
- <https://www.dontsleeponai.com/statusline>
- <https://github.com/gwittebolle/claude-carbon>
