The status line is a bar at the bottom of Claude Code that shows whatever your own script prints. It is the easiest way to keep an eye on how full the context window is without typing /context every few minutes.

What it is

A built-in Claude Code feature. You point the statusLine setting at a command; Claude Code runs it, passes session data as JSON on stdin, and displays what the command prints in its own row above the footer. The script runs on your machine and does not consume API tokens.

The JSON includes, among other things:

  • model.display_name: the current model;
  • context_window.used_percentage: how full the context window is (can be null early in the session);
  • rate_limits.five_hour and rate_limits.seven_day, each with used_percentage and resets_at (Unix seconds): your subscription limits, present only for claude.ai Pro and Max subscribers, after the first response;
  • prompt_cache: cache stats for the main conversation, such as hit_ratio and warm (see Prompt caching);
  • cost.total_cost_usd, workspace.current_dir, git worktree and repo info.

The script runs when a session starts, after each new assistant message, after /compact, when the permission mode changes, and at a few other points. Updates are debounced at 300 ms.

What problem it solves

Context fills up quietly: a few file reads and a test run can take a big share of the window without anything visible in the terminal. With the percentage always on screen, you notice when it is time to /clear or /compact at a break, instead of finding out when auto-compaction kicks in mid-task. On a subscription, the 5-hour and 7-day limits with their reset times tell you whether to start a big task now or later.

How to try it

The fastest way is to describe what you want and let Claude Code write it:

/statusline show model name, context percentage, and my 5h and 7d limits with time until reset

Claude Code generates a script in ~/.claude/ and updates your settings. To remove it later, run /statusline delete.

To set it up by hand, add this to ~/.claude/settings.json (or project settings):

{
  "statusLine": {
    "type": "command",
    "command": "node ~/.claude/statusline.ts"
  }
}

Node 22.18 and later can run a .ts file directly, so the script below needs no build step.

Usage example

Frontend

On a frontend project you mostly care about the model and how much room is left before the agent starts forgetting the component tree. This script shows both, plus the current directory name:

// ~/.claude/statusline.ts
import { readFileSync } from "node:fs";
import { basename } from "node:path";
 
type StatusInput = {
  model: { display_name: string };
  workspace: { current_dir: string };
  context_window: { used_percentage: number | null };
};
 
const input: StatusInput = JSON.parse(readFileSync(0, "utf8"));
const pct = Math.round(input.context_window.used_percentage ?? 0);
const bar = "█".repeat(Math.round(pct / 10)).padEnd(10, "░");
 
console.log(`[${input.model.display_name}] ${basename(input.workspace.current_dir)} ${bar} ${pct}%`);

Output: [Sonnet] web-app ███░░░░░░░ 31%.

Backend

For long backend sessions (migrations, debugging with logs), add the subscription limits with time until reset:

// ~/.claude/statusline.ts
import { readFileSync } from "node:fs";
 
type Window = { used_percentage: number; resets_at: number };
type StatusInput = {
  model: { display_name: string };
  context_window: { used_percentage: number | null };
  rate_limits?: { five_hour?: Window; seven_day?: Window };
};
 
const input: StatusInput = JSON.parse(readFileSync(0, "utf8"));
const pct = Math.round(input.context_window.used_percentage ?? 0);
 
function limit(name: string, w?: Window): string {
  if (!w) return "";
  const mins = Math.max(0, Math.round((w.resets_at * 1000 - Date.now()) / 60000));
  const left = mins >= 60 ? `${Math.floor(mins / 60)}h${mins % 60}m` : `${mins}m`;
  return ` | ${name} ${Math.round(w.used_percentage)}% (resets in ${left})`;
}
 
console.log(
  `[${input.model.display_name}] ctx ${pct}%` +
    limit("5h", input.rate_limits?.five_hour) +
    limit("7d", input.rate_limits?.seven_day),
);

Output: [Opus] ctx 8% | 5h 24% (resets in 1h23m) | 7d 41% (resets in 55h33m).

Who it’s for and when

Anyone who runs Claude Code sessions longer than a few minutes. It is most useful on a subscription, where the rate-limit fields appear, and for anyone learning to manage context: seeing the number climb after a big file read teaches more than any explanation. If you only run short one-off sessions, /context when you need it is enough.

Gotchas

  • context_window.used_percentage counts input tokens only (input plus cache reads and writes), not output.
  • rate_limits is missing for API-key users and before the first response; handle undefined.
  • The status line hides during some UI interactions, such as the help menu and permission prompts.
  • With a custom status line, Claude Code stops showing most footer keyboard hints, such as esc to interrupt.
  • Keep the script fast: if a new update arrives while it is still running, Claude Code cancels it.

Citations

  1. Customize your status line
  2. How Claude Code uses prompt caching: check cache performance
  3. Node.js: running TypeScript natively