- 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
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.

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:
Manually configure a status line
Add astatusLine 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.
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:
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.
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 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.
~/.claude/settings.json, which sets type to "command" (meaning “run this shell command”) and points command to your script: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
/compactfinishes- The permission mode changes
- Vim mode toggles
- A
refreshIntervaltimer elapses, if you set one
refreshInterval to also re-run the command on a fixed timer.
What your script can output
- Multiple lines: each
echoorprintstatement displays as a separate row. See the multi-line example. - Colors: use ANSI escape codes like
\033[32mfor green (terminal must support them). See the git status example. - Links: use OSC 8 escape sequences to make text clickable (Cmd+click on macOS, Ctrl+click on Windows/Linux). Requires a terminal that supports hyperlinks like iTerm2, Kitty, or WezTerm. See the clickable links example.
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:Full JSON schema
Full JSON schema
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--nameor/rename, or once an AI-generated session title exists. The default display name, such asmy-app-3f, doesn’t populate itprompt_id: appears only after the first user inputworkspace.git_worktree: appears only when the current directory is inside a linked git worktreeworkspace.repo: appears only inside a git repository with anoriginremote configuredeffort: appears only when the current model supports the reasoning effort parametervim: appears only when vim mode is enabledagent: appears only when running with the--agentflag or agent settings configuredpr: 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_stateandpr.kindmay be independently absentworktree: appears only during--worktreesessions. When present,branchandoriginal_branchmay also be absent for hook-based worktreesrate_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. Usejq -r '.rate_limits.five_hour.used_percentage // empty'to handle absence gracefully.
null:context_window.current_usage:nullbefore the first API call in a session, and again after/compactuntil the next API call repopulates itcontext_window.used_percentage,context_window.remaining_percentage: may benullearly in the session
Context window fields
Thecontext_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_tokensis the sum ofinput_tokens,cache_creation_input_tokens, andcache_read_input_tokens;total_output_tokensis the output tokens from the most recent response. Both are0before 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.