Post your build ideas
LocalASO Track App Store keyword ranks in every countryFind your vibe. Find you job which is just for you and your dataDealtab Brand Deal Tracker That Does The Work For YouIs Major Cooked? Free AI risk score + roast for your college majorWiral.Social LinkedIn, Scheduler, Scheduling Tool, Ghostwriter
Solo Era solo activities, solo maxxing, sidequests, challengeCadentiq daily routine, wellbeing, self care, healthy habitsTexeva Your businessKeepsake Project Management, Freelancers, DesignersOrvyx AI You create

How to set up the Claude Code status line

The Claude Code status line is a customizable bar at the bottom of the interface that runs any shell script you configure. Claude Code pipes JSON session data into the script on stdin and shows whatever the script prints. The quickest setup is the /statusline command, where you describe what you want in plain English. Manual setup adds a statusLine entry to settings.json that points at your script.

What is the Claude Code status line?

The status line documentation describes a bar at the bottom of Claude Code that runs a shell script you configure. It gives you a persistent, at-a-glance view of context usage, cost, git status or anything else you can compute in a script. It is useful when you want to watch the context window while you work, track session cost, tell several sessions apart, or keep the git branch in view.

A few facts help set expectations. 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 and the ? for shortcuts fallback. It runs locally and does not consume API tokens. It temporarily hides during certain UI interactions, including the help menu and permission prompts.

If you only want clickable link badges in the footer when an ID such as a ticket number appears in the conversation, the docs point to a different setting, footerLinksRegexes, which needs no script.

How do you set up a status line with /statusline?

The /statusline command accepts natural language instructions. Claude Code then generates a script file in ~/.claude/ and updates your settings automatically. Approve the file edit prompts if Claude Code asks for permission.

Ask Claude Code to build it
/statusline show model name and context percentage with a progress bar

Run /statusline without arguments to auto-configure from your shell prompt, according to the command reference. To remove the status line later, run /statusline delete, /statusline clear or /statusline remove it, or delete the statusLine field from settings.json by hand.

Use the command when you want a result in a minute. Use the manual route below when you want to understand and version the script, which matters once the script shows anything slow or personal to your setup.

How do you configure the status line manually?

Add a statusLine field to your user settings at ~/.claude/settings.json, or to project settings. Set type to "command" and point command at a script path or an inline shell command.

~/.claude/settings.json
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh",
    "padding": 2
  }
}
Fields inside statusLine
FieldRequiredWhat it does
typeYesSet to "command": run this shell command
commandYesA script path or an inline shell command, run in a shell
paddingNoExtra horizontal spacing in characters, default 0. It adds to the interface's built-in spacing, so it controls indentation, not distance from the terminal edge
refreshIntervalNoRe-runs the command every N seconds in addition to event-driven updates. The minimum is 1. Use it for clocks or git state changed by background subagents
hideVimModeIndicatorNoSet to true to hide the built-in -- INSERT -- text when your script renders vim.mode itself

Claude Code reloads settings automatically and runs your script as soon as you save the file. Because the status line executes a shell command, Claude Code applies the same workspace trust rule as for hooks in settings files. Until you accept the trust dialog for the folder, the status line stays blank.

You can also skip the script file. The docs show an inline jq command that prints the model name and context percentage straight from the command field. That works for one-liners; anything with a branch or a condition is easier to read in a file.

What does a working status line script look like?

This one shows the model, the folder, the git branch, a ten-character context bar, the estimated session cost, minutes elapsed and, for subscribers, the rate-limit percentage for the week. It uses only fields listed in the docs, and every field has a fallback, because values can be null before the first API response. It needs jq, a command-line JSON parser you may have to install.

~/.claude/statusline.sh
#!/bin/bash
# Claude Code sends session JSON on stdin; print one line to stdout.
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name // "Claude"')
DIR=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // "."')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
MINS=$(echo "$input" | jq -r '((.cost.total_duration_ms // 0) / 60000) | floor')
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty' | cut -d. -f1)

# Git branch for the working directory; empty outside a repository
BRANCH=$(git -C "$DIR" branch --show-current 2>/dev/null)

# Ten-character context bar
FILLED=$((PCT / 10))
[ "$FILLED" -gt 10 ] && FILLED=10
BAR=$(printf '%*s' "$FILLED" '' | tr ' ' '#')$(printf '%*s' "$((10 - FILLED))" '' | tr ' ' '-')

LINE="[$MODEL] ${DIR##*/}"
[ -n "$BRANCH" ] && LINE="$LINE ($BRANCH)"
LINE="$LINE | [$BAR] ${PCT}%"
LINE="$LINE | $(printf '%.2f' "$COST") USD | ${MINS}m"
[ -n "$WEEK" ] && LINE="$LINE | week ${WEEK}%"
echo "$LINE"

Make it executable and register it:

Make it executable
chmod +x ~/.claude/statusline.sh

With sample input, the script prints a line like this:

Example output
[Opus] my-app (main) | [###-------] 37% | 1.23 USD | 12m | week 12%

Two cautions about the numbers. The cost field is an estimate: the docs say it is computed client-side at list price and may differ from your actual bill. And rate_limits is only present for claude.ai Pro, Max and Ultra subscribers, or behind a Claude apps gateway with spend limits, and only after the first API response. That is why the script reads it with // empty and leaves the segment out when it is absent. For what the limits mean, see the usage limits guide.

How do you test a status line script before using it?

Pipe fake JSON into it from your shell. The docs recommend this, since you see output and errors immediately instead of waiting for Claude Code to run it.

Test with mock input
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/user/project"},"context_window":{"used_percentage":25},"session_id":"test-session-abc"}' | ~/.claude/statusline.sh

Test a second time with an almost empty object, echo '{}' | ~/.claude/statusline.sh. If the script prints something sensible, it will survive the start of a session, before any API response has filled in the fields. Claude Code shows your script's output only after the script exits with code 0, so a non-zero exit or empty output makes the status line go blank.

What data can the status line show?

Claude Code sends JSON to your script on stdin. These are some of the fields documented as of October 2026; the docs page has the full list, including prompt cache and spend-limit fields.

Selected status line JSON fields
FieldWhat it holds
model.id, model.display_nameCurrent model identifier and display name
workspace.current_dir, workspace.project_dirCurrent directory, and the directory Claude Code was launched in
workspace.repo.owner, workspace.repo.nameRepository identity parsed from the origin remote; absent outside a repository
context_window.used_percentage, remaining_percentagePre-calculated share of the context window used or remaining
context_window.context_window_sizeMaximum context window in tokens: 200000 by default, 1000000 for models with extended context
cost.total_cost_usd, cost.total_duration_msEstimated session cost in USD and total wall-clock time; cost resets when /clear starts a new session
cost.total_lines_added, cost.total_lines_removedLines of code changed
rate_limits.five_hour.used_percentage, rate_limits.seven_day.used_percentagePercentage of the five-hour or seven-day limit used, from 0 to 100. Subscribers only
rate_limits.*.resets_atUnix epoch seconds when the window resets
effort.level, thinking.enabled, fast_modeReasoning effort, extended thinking and fast mode state for the session
session_id, session_name, versionSession identifier, custom or generated session name, and the Claude Code version
output_style.name, vim.modeCurrent output style; vim mode when enabled

Fields can be null early in a session, so give each a fallback, as // 0 does in jq. If the context percentage looks different from /context, the docs explain why: the status line reports counts from the last API response, while /context adds an estimate for messages added since. Use used_percentage for the simplest accurate reading. The context window guide covers what fills it.

When does the status line refresh?

Your script runs once when a session starts, including on resume. After that it runs again when:

  • a new assistant message arrives
  • /compact finishes
  • the permission mode changes
  • vim mode toggles
  • you change the command in your statusLine settings
  • a refreshInterval timer elapses, if you set one
  • a rate-limit window in the data your script last received reaches its reset time

Updates are debounced at 300 ms, so rapid changes batch into one run. If a new update triggers while your script is still running, Claude Code cancels the in-flight script. If you edit the script, the change appears the next time one of those triggers fires. The event triggers can go quiet when the main session is idle, for example while a coordinator waits on background subagents. Set refreshInterval if you show time-based or externally sourced segments.

Slow scripts block the status line from updating until they finish. The docs suggest caching slow operations such as git status, since the script runs often during active sessions, and keeping output short, since the bar has limited width.

Can the status line show colors, several lines or links?

  • Multiple lines: each echo or print becomes a separate row.
  • Colors: use ANSI escape codes such as \033[32m for green, in a terminal that supports them.
  • Links: OSC 8 escape sequences make text clickable (Cmd+click on macOS, Ctrl+click on Windows and Linux) in terminals that support hyperlinks, such as iTerm2, Kitty or WezTerm. The docs say Terminal.app does not support clickable links. If detection fails, set FORCE_HYPERLINK=1 before launching claude.
  • Terminal size: Claude Code captures your script's output, so tput cols cannot read the terminal. Read the COLUMNS and LINES environment variables instead.

Complex escape sequences can occasionally garble output when they overlap with other UI updates, and multi-line scripts with escape codes are more prone to it than plain single-line text. If you see corrupted output, simplify to plain text first. For prebuilt themes, the docs mention community projects such as ccstatusline and starship-claude.

A status line is a small, buildable thing, which makes it a good first project for a Claude Code session. If you want ideas for tools in the same spirit, browse the developer tools category on the board.

Why is my Claude Code status line not showing?

Work down this list; the first four cause most blank status lines.

  1. The script is not executable. Run chmod +x ~/.claude/statusline.sh.
  2. The script writes to stderr, not stdout. Only stdout is displayed.
  3. Workspace trust is not accepted. The status line stays blank until you accept the trust dialog. claude --debug logs Status line command skipped: workspace trust not accepted. Restart Claude Code and accept it.
  4. The script exits non-zero or hangs. The output only shows after exit code 0. Run the script manually to see what happens.
  5. Hooks are disabled by policy. If disableAllHooks is true outside managed settings, only a managed statusLine runs. If your organization sets allowManagedHooksOnly, your custom status line disappears without warning.
  6. Windows path. With Git Bash, backslashes in the command path are likely consumed as escape characters. Use forward slashes.

Run claude --debug to log your script's stderr on every status line invocation and its exit code on the first. If values show -- or are empty, handle nulls with fallbacks and restart Claude Code if they remain empty after several messages. On narrow terminals, notifications that share the status line row can truncate your output.

The status line is a hooks-adjacent feature: it runs your own command with session data. For commands that run on events rather than draw a bar, see Claude Code hooks, and for the commands you can type, Claude Code commands.

Frequently asked questions

How do I set up the Claude Code status line?

Run /statusline followed by a plain-English description, such as /statusline show model name and context percentage with a progress bar. Claude Code writes a script into ~/.claude/ and updates settings for you. To do it by hand, add a statusLine entry with type command to ~/.claude/settings.json and point it at your script.

What can the Claude Code status line display?

Anything your script can compute from the JSON Claude Code sends: model name, directory, git branch, context window percentage, estimated cost, session duration, lines changed, effort level, vim mode, and for subscribers the rate-limit percentages for the five-hour window and the week. Scripts can use colors, several lines and clickable links.

Does the status line use tokens or cost money?

No. The documentation says the status line runs locally and does not consume API tokens. Your script runs on your machine, so keep it fast, because slow scripts delay updates. The cost figure it can show is a local estimate computed at list price and may differ from your bill.

Why is my Claude Code status line blank?

The usual causes are a script that is not executable, output sent to stderr instead of stdout, a non-zero exit code, or an untrusted workspace, since the status line stays blank until you accept the trust dialog. Run claude --debug to see the script's stderr and exit code.

How do I remove the Claude Code status line?

Run /statusline delete, /statusline clear or /statusline remove it. You can also delete the statusLine field from your settings.json by hand. Claude Code then returns to its default footer, including the usual keyboard hints that a custom status line suppresses.

How often does the status line update?

It runs when a session starts, when a new assistant message arrives, when /compact finishes, when the permission mode changes, and when vim mode toggles. Updates are debounced at 300 ms. Set refreshInterval in the statusLine settings to re-run on a fixed timer, with a minimum of 1 second.

Created with AI assistance and edited for this site. Examples are illustrative and do not represent customer research. About the publisher.