Skip to main content
The status line is a customizable bar at the bottom of Claude Code that runs any shell script you configure. It receives JSON session data on stdin and displays whatever your script prints, giving you a persistent, at-a-glance view of context usage, costs, git status, or anything else you want to track. Status lines are useful when you:
  • Want to monitor context window usage as you work
  • Need to track session costs
  • Work across multiple sessions and need to distinguish them
  • Want git branch and status always visible
The status line renders in its own row above the built-in footer badges and does not replace them. With a custom status line configured, Claude Code stops showing most of the footer’s keyboard hints, including esc to interrupt, the ? for shortcuts fallback, and the hold space to speak voice dictation hint. To add clickable link badges to the footer when an ID appears in the conversation, without writing a script, configure footerLinksRegexes instead. Here’s an example of a multi-line status line that displays git info on the first line and a color-coded context bar on the second.
A multi-line status line showing model name, directory, git branch on the first line, and a context usage progress bar with cost and duration on the second line
This page walks through setting up a basic status line, explains how the data flows from Claude Code to your script, lists all the fields you can display, and provides ready-to-use examples for common patterns like git status, cost tracking, and progress bars.

Set up a status line

Use the /statusline command to have Claude Code generate a script for you, or manually create a script and add it to your settings.

Use the /statusline command

The /statusline command accepts natural language instructions describing what you want displayed. Claude Code generates a script file in ~/.claude/ and updates your settings automatically:
Approve the file edit prompts if Claude Code asks for permission during setup.

Manually configure a status line

Add a statusLine field to your user settings (~/.claude/settings.json, where ~ is your home directory) or project settings. Set type to "command" and point command to a script path or an inline shell command. For a full walkthrough of creating a script, see Build a status line step by step.
The command field runs in a shell, so you can also use inline commands instead of a script file. This example uses jq to parse the JSON input and display the model name and context percentage:
The optional padding field adds extra horizontal spacing (in characters) to the status line content. Defaults to 0. This padding is in addition to the interface’s built-in spacing, so it controls relative indentation rather than absolute distance from the terminal edge. The optional refreshInterval field re-runs your command every N seconds in addition to the event-driven updates. The minimum is 1. Set this when your status line shows time-based data such as a clock, or when background subagents change git state while the main session is idle. Leave it unset to run only on events. The optional hideVimModeIndicator field suppresses the built-in -- INSERT -- text below the prompt. Set this to true when your script renders vim.mode itself, so the mode is not shown twice.

Disable the status line

Run /statusline and ask it to remove or clear your status line (e.g., /statusline delete, /statusline clear, /statusline remove it). You can also manually delete the statusLine field from your settings.json.

Build a status line step by step

This walkthrough shows what’s happening under the hood by manually creating a status line that displays the current model, working directory, and context window usage percentage.
Running /statusline with a description of what you want configures all of this for you automatically.
These examples use Bash scripts, which work on macOS and Linux. On Windows, see Windows configuration for PowerShell and Git Bash examples.
A status line showing model name, directory, and context percentage
1

Create a script that reads JSON and prints output

Claude Code sends JSON data to your script via stdin. This script uses jq, a command-line JSON parser you may need to install, to extract the model name, directory, and context percentage, then prints a formatted line.Save this to ~/.claude/statusline.sh (where ~ is your home directory, such as /Users/username on macOS or /home/username on Linux):
2

Make it executable

Mark the script as executable so your shell can run it:
3

Add to settings

Tell Claude Code to run your script as the status line. Add this configuration to ~/.claude/settings.json, which sets type to "command" (meaning “run this shell command”) and points command to your script:
Your status line appears at the bottom of the interface. Settings reload automatically, but changes won’t appear until your next interaction with Claude Code.

How status lines work

Claude Code runs your script and pipes JSON session data to it via stdin. Your script reads the JSON, extracts what it needs, and prints text to stdout. Claude Code displays whatever your script prints. When it updates Your script runs once when a session starts, including when you resume one. After that, it runs again when:
  • A new assistant message arrives
  • /compact finishes
  • The permission mode changes
  • Vim mode toggles
  • A refreshInterval timer elapses, if you set one
Claude Code debounces updates at 300ms, so rapid changes batch together and your script runs once after the changes stop. If a new update triggers while your script is still running, Claude Code cancels the in-flight script. If you edit your script, the changes appear the next time an update trigger re-runs it. The event-driven triggers can go quiet when the main session is idle, for example while a coordinator waits on background subagents. To keep time-based or externally-sourced segments current during idle periods, set refreshInterval to also re-run the command on a fixed timer. What your script can output Sizing output to the terminal Claude Code captures your script’s output instead of connecting it directly to the terminal, so tput cols and language-level width detection cannot read the terminal size from inside the script. Read the COLUMNS and LINES environment variables instead. Claude Code sets these to the current terminal dimensions before running your script. Requires Claude Code v2.1.153 or later.
The status line runs locally and does not consume API tokens. It temporarily hides during certain UI interactions, including autocomplete suggestions, the help menu, and permission prompts.

Available data

Claude Code sends the following JSON fields to your script via stdin:
Your status line command receives this JSON structure via stdin:
Fields that may be absent (not present in JSON):
  • session_name: appears when a custom name has been set with --name or /rename, or once an AI-generated session title exists. The default display name, such as my-app-3f, doesn’t populate it
  • prompt_id: appears only after the first user input
  • workspace.git_worktree: appears only when the current directory is inside a linked git worktree
  • workspace.repo: appears only inside a git repository with an origin remote configured
  • effort: appears only when the current model supports the reasoning effort parameter
  • vim: appears only when vim mode is enabled
  • agent: appears only when running with the --agent flag or agent settings configured
  • pr: appears only while an open PR or GitLab merge request is found for the current branch, and is removed once it merges or closes. pr.review_state and pr.kind may be independently absent
  • worktree: appears only during --worktree sessions. When present, branch and original_branch may also be absent for hook-based worktrees
  • rate_limits: appears only for Claude.ai subscribers (Pro/Max) after the first API response in the session. Each window (five_hour, seven_day) may be independently absent. Use jq -r '.rate_limits.five_hour.used_percentage // empty' to handle absence gracefully.
Fields that may be null:
  • context_window.current_usage: null before the first API call in a session, and again after /compact until the next API call repopulates it
  • context_window.used_percentage, context_window.remaining_percentage: may be null early in the session
Handle missing fields with conditional access and null values with fallback defaults in your scripts.

Context window fields

The context_window object describes the live context window from the most recent API response.
  • Combined totals (total_input_tokens, total_output_tokens): tokens currently in the context window. total_input_tokens is the sum of input_tokens, cache_creation_input_tokens, and cache_read_input_tokens; total_output_tokens is the output tokens from the most recent response. Both are 0 before the first API response.
  • Per-component usage (current_usage): the same token counts broken out by category. Use this when you need cache hits separate from fresh input.
The