# Claude Code status line: show model and token usage

> A status line is a script that runs locally and prints the model name, context percentage and token counts at the bottom of Claude Code. Setup takes three steps or one command.

URL: https://claudegpt.si/news/claude-code-status-line-model-token-usage  
Published: 2026-11-04T02:51:17.454Z  
Author: ClaudeGPT Si Newsroom  
Section: Guides  
Topics: Claude Code, Anthropic, Status line, Token usage  
Publisher: ClaudeGPT Si

## Key takeaways

- Run /statusline with a plain-English request, or add a statusLine entry to ~/.claude/settings.json that points to a script.
- The script receives JSON on stdin with the model name, context window token counts and used percentage.
- The status line runs locally and, per the docs, does not consume API tokens.

The Claude Code status line is a bar at the bottom of the terminal that runs a shell script you choose and prints whatever the script returns. To show the model and token usage, run `/statusline` with a plain-English request, or add a short script and a `statusLine` entry to `~/.claude/settings.json`. The [Claude Code docs](https://code.claude.com/docs/en/statusline) describe both routes, and this guide follows them.

The status line runs on your machine and, according to the docs, does not consume API tokens. So you can show as much as you like without it adding to your usage.

## How to set up a Claude Code status line the fast way

Type `/statusline` followed by what you want to see. The docs give this example:

```text
/statusline show model name and context percentage with a progress bar
```

Claude Code writes a script into `~/.claude/` and updates your settings for you. Approve the file edit prompts if it asks. To remove the status line later, run `/statusline delete`, or delete the `statusLine` field from `settings.json` by hand.

## How to set up a status line by hand

You need `jq`, a command-line JSON parser, for the Bash version below. Python and Node.js scripts can parse JSON without it. The steps follow the docs, with the output line changed to show tokens. I ran this script in a test shell with mock JSON input, as the docs suggest. I did not run it inside Claude Code itself.

**1. Save a script to `~/.claude/statusline.sh`:**

```bash
#!/bin/bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
IN=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
OUT=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
echo "[$MODEL] ${PCT}% context | in ${IN} out ${OUT}"
```

**2. Make it executable:**

```bash
chmod +x ~/.claude/statusline.sh
```

**3. Point Claude Code at it** in `~/.claude/settings.json`:

```json
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh"
  }
}
```

Claude Code reloads settings when you save the file, so the bar appears without a restart. With mock input of 15,500 input tokens, 1,200 output tokens and 8% context used, the script prints `[Opus] 8% context | in 15500 out 1200`.

You can also skip the file. The docs show an inline version that needs no script:

```json
{
  "statusLine": {
    "type": "command",
    "command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'"
  }
}
```

## Which fields show model and token usage

Claude Code sends session data to your script as JSON on stdin. These are the fields that matter for model and tokens.

| Field | What it holds |
| --- | --- |
| `model.display_name`, `model.id` | The current model's name and identifier |
| `context_window.total_input_tokens` | Tokens in the context window from the latest response, including cache reads and writes |
| `context_window.total_output_tokens` | Output tokens from the latest response |
| `context_window.context_window_size` | Maximum context size: 200,000 by default, 1,000,000 for models with extended context |
| `context_window.used_percentage` | Share of the context window used, already calculated |
| `context_window.current_usage` | The last call's tokens split into input, output, cache creation and cache read |
| `cost.total_cost_usd` | Estimated session cost at list price, which may differ from your bill |
| `rate_limits.five_hour.used_percentage` | Share of the 5-hour limit used (Pro, Max and Ultra subscribers only) |

Two details trip people up. These counts describe the context window as of the last API response, not a running total for the session. And `used_percentage` counts input tokens only (`input_tokens` plus cache creation and cache read tokens), so output tokens do not move it.

Some fields can be empty. `context_window.current_usage` is `null` before the first API call and again after `/compact`, and the percentages can be `null` early in a session. That is why the script uses `// 0` as a fallback. The `rate_limits` fields appear only for claude.ai subscribers and only after the first response, so read them with `// empty`.

## When the status line updates

The script runs when a session starts or resumes, then again after each new assistant message, when `/compact` finishes, and when the permission mode or vim mode changes. Updates are debounced at 300 ms. If your bar shows time-based data, add `"refreshInterval"` to the `statusLine` block to re-run the command every N seconds, with a minimum of 1.

The optional `padding` field adds horizontal spacing in characters. Your script can print several lines, and can use ANSI color codes if your terminal supports them.

## If the status line does not appear

The docs list these checks, in roughly this order:

- Make sure the script is executable and prints to stdout, not stderr.
- Run the script by hand with mock input: `echo '{"model":{"display_name":"Opus"},"context_window":{"used_percentage":25}}' | ./statusline.sh`
- Accept the workspace trust dialog. Until you do, the status line stays blank.
- Check for `disableAllHooks` set to `true`, or an organization-wide `allowManagedHooksOnly` setting, either of which can disable a custom status line.
- On Windows with Git Bash, write paths in `command` with forward slashes. Backslashes are consumed as escape characters and the command fails without an error.
- Run `claude --debug` to log your script's stderr and exit code.

A script that exits with a non-zero code, or prints nothing, leaves the bar blank. Keep it fast, because a slow script blocks updates.

## What the status line does not replace

A status line shows the last response's numbers at a glance. For a fuller breakdown of where your tokens went, see our guide on [how to check token usage in Claude](https://claudegpt.si/news/claude-how-to-check-token-usage). The docs also note that the `/context` command adds an estimate for messages sent since the last response, so it can read higher than the status line until the next response arrives.

## Frequently asked questions

### How do I show the model name in the Claude Code status line?

Read model.display_name from the JSON your script receives on stdin and print it. With jq, that is jq -r ".model.display_name". The /statusline command can also generate this for you.

### Does the Claude Code status line use tokens?

No. The docs say the status line runs locally and does not consume API tokens.

### Why is my Claude Code status line blank?

Common causes are a script that is not executable, prints nothing or exits with an error, an unaccepted workspace trust dialog, or disableAllHooks or allowManagedHooksOnly settings. Run claude --debug to see the script output and exit code.

### How do I remove the Claude Code status line?

Run /statusline and ask it to delete or clear the status line, or remove the statusLine field from your settings.json.

## Sources

- [Customize your status line](https://code.claude.com/docs/en/statusline), Anthropic
