Guide · Updated

Claude Code statusline: show model, branch, context and cost under your prompt

How the Claude Code status line works: /statusline, the statusLine setting, the JSON fields you get, and copyable scripts for model, branch, context and cost.

The Claude Code status line is a row under the prompt that shows whatever a script of yours prints. Claude Code runs the script with session data as JSON on stdin (model, folder, context use, estimated cost, rate limits) and displays its output. The fastest setup is /statusline plus a description of what you want; for full control, set statusLine in ~/.claude/settings.json to your own script. It runs locally and uses no tokens. Details below are as of October 2026.

Set it up

The quick way

Describe what you want, and Claude Code writes the script and the setting for you:

/statusline show model, current folder, git branch and context percentage

Approve the file edits it asks for. To undo it later, run /statusline delete.

The manual way

Point statusLine at a command in ~/.claude/settings.json, or in a project's .claude/settings.json:

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh",
    "padding": 1,
    "refreshInterval": 10
  }
}
  • command runs in a shell, so it can be a script path or an inline command.
  • padding adds horizontal space, in characters.
  • refreshInterval reruns the command every N seconds (minimum 1), on top of the normal updates. Leave it out unless you show a clock or data that changes while Claude is idle.
  • hideVimModeIndicator: true hides the built-in -- INSERT -- text when your script shows vim.mode itself.

When it updates

The script runs when a session starts or resumes, then again when a new assistant message arrives, /compact finishes, the permission mode changes, vim mode toggles, a refreshInterval timer fires, or a rate-limit window reaches its reset time. Updates are debounced by 300ms, and a new update cancels a script that's still running, so a slow script means a stale or empty row. Output appears only when the script exits with code 0. The row hides while a permission prompt is open.

The data your script gets

The full schema has more, but these are the fields people show most:

FieldWhat it holds
model.display_nameModel name, such as Opus
workspace.current_dir, workspace.project_dirCurrent folder, and the folder Claude Code started in
context_window.used_percentageShare of the context window in use, counted from input tokens
context_window.context_window_sizeWindow size in tokens
cost.total_cost_usdEstimated session cost at list price
cost.total_duration_msWall-clock time the session has run
cost.total_lines_added, cost.total_lines_removedLines changed this session
rate_limits.five_hour, rate_limits.seven_dayused_percentage and resets_at, for Pro and Max, after the first response
session_id, session_nameWhich session this is
pr.number, pr.review_stateOpen pull request for the current branch
worktree.name, worktree.branchSet while the session runs in a worktree
effort.level, vim.mode, agent.nameReasoning effort, vim mode, and the --agent name

Some fields are missing or null early in a session, so always give jq a fallback (// 0 or // empty). Note that cost.total_cost_usd is computed on your machine at list prices; on a subscription it is not what you pay.

Scripts you can copy

The scripts use jq. Save one as ~/.claude/statusline.sh and run chmod +x ~/.claude/statusline.sh.

Model, folder, branch and a context bar

The percentage turns yellow at 50% and red at 80%:

#!/bin/bash
input=$(cat)
model=$(jq -r '.model.display_name' <<<"$input")
dir=$(jq -r '.workspace.current_dir' <<<"$input")
pct=$(jq -r '.context_window.used_percentage // 0' <<<"$input" | cut -d. -f1)
branch=$(git -C "$dir" branch --show-current 2>/dev/null)
filled=$((pct / 10))
printf -v fill '%*s' "$filled" ''
printf -v rest '%*s' $((10 - filled)) ''
bar="${fill// /▓}${rest// /░}"
if [ "$pct" -ge 80 ]; then c='\033[31m'; elif [ "$pct" -ge 50 ]; then c='\033[33m'; else c='\033[32m'; fi
printf '%b\n' "[$model] ${dir##*/}${branch:+ ($branch)} ${c}${bar} ${pct}%\033[0m"

Cost, time and lines changed

#!/bin/bash
input=$(cat)
cost=$(jq -r '.cost.total_cost_usd // 0' <<<"$input")
ms=$(jq -r '.cost.total_duration_ms // 0' <<<"$input")
added=$(jq -r '.cost.total_lines_added // 0' <<<"$input")
removed=$(jq -r '.cost.total_lines_removed // 0' <<<"$input")
printf '$%.2f | %dm | +%s -%s\n' "$cost" $((ms / 60000)) "$added" "$removed"

The cost resets when /clear starts a new session. For limits across your whole plan, use /usage or the next script.

Usage limits and when they reset

#!/bin/bash
input=$(cat)
model=$(jq -r '.model.display_name' <<<"$input")
five=$(jq -r '.rate_limits.five_hour.used_percentage // empty' <<<"$input")
reset=$(jq -r '.rate_limits.five_hour.resets_at // empty' <<<"$input")
week=$(jq -r '.rate_limits.seven_day.used_percentage // empty' <<<"$input")
out="[$model]"
[ -n "$five" ] && out="$out 5h $(printf '%.0f' "$five")%"
[ -n "$reset" ] && out="$out until $(date -d "@$reset" +%H:%M 2>/dev/null || date -r "$reset" +%H:%M)"
[ -n "$week" ] && out="$out | 7d $(printf '%.0f' "$week")%"
echo "$out"

date -d is the Linux form and date -r the macOS one; the script tries both. The dashboard guide covers usage monitors that keep history and predict when you'll hit a limit.

Keep it fast in big repositories

The script runs often, and git status can be slow in a large repository. Cache slow results for a few seconds in a file named after session_id, which stays the same for a session but differs between sessions:

#!/bin/bash
input=$(cat)
dir=$(jq -r '.workspace.current_dir' <<<"$input")
cache="/tmp/statusline-git-$(jq -r '.session_id' <<<"$input")"
age=$(( $(date +%s) - $(stat -c %Y "$cache" 2>/dev/null || stat -f %m "$cache" 2>/dev/null || echo 0) ))
if [ "$age" -gt 5 ]; then
  b=$(git -C "$dir" branch --show-current 2>/dev/null)
  n=$(git -C "$dir" status --porcelain 2>/dev/null | wc -l | tr -d ' ')
  printf '%s\n%s\n' "$b" "$n" > "$cache"
fi
{ read -r branch; read -r changed; } < "$cache"
echo "${branch:-no git} | ${changed:-0} changed"

Don't use $$ for the file name: it changes on every run and defeats the cache.

Layout tips

  • Each line your script prints becomes its own row, so two echo lines give a two-row status line.
  • ANSI colors work, and so do OSC 8 links in terminals that support them, such as iTerm2, Kitty and WezTerm.
  • tput cols can't see the terminal from inside the script. Read the COLUMNS environment variable instead, which Claude Code sets before each run.
  • Test without Claude Code by piping sample JSON in:
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/me/app"},"context_window":{"used_percentage":42},"session_id":"test"}' | ~/.claude/statusline.sh

Ready-made status lines

If you'd rather configure than script, two community projects are linked from Anthropic's docs:

  • ccstatusline opens a terminal configurator with widgets for model, git, tokens and usage, Powerline styling and themes. Start it with npx -y ccstatusline@latest; it writes the statusLine setting for you.
  • starship-claude renders the status line with Starship, including a context progress bar. It installs as a Claude Code plugin or as a standalone script.

Status rows for subagents

A separate subagentStatusLine setting replaces the default row for each subagent in the agent panel. Its command receives every visible row at once (with fields such as name, status, label, model and tokenCount) and prints one JSON line per row it wants to change, in the form {"id": "...", "content": "..."}. The agent teams guide covers when subagents run in the background.

If it doesn't show

  • The script must be executable, print to stdout and exit 0. Empty output leaves the row blank.
  • Until you accept the workspace trust dialog for the folder, the status line doesn't run, because it executes a shell command just like a hook.
  • disableAllHooks also turns off the status line, and an organization setting, allowManagedHooksOnly, allows only a status line from managed settings.
  • On Windows with Git Bash, write the script path with forward slashes.
  • Start claude --debug to log the script's stderr and its first exit code.

One session's status line, every session's status

A status line describes the one session in front of you. Once you run several, in different terminals, on a server or in Codex and Cursor too, you need the same at-a-glance view across all of them. Briefkin turns each session into a card that shows whether it is working, waiting on you or done, with a one-line status summary. Your own agent CLI writes that summary on your machine (Claude Haiku through claude -p, for example), so Briefkin never sees or pays for it. The docs show the one-command setup.

Questions

How do I add a status line to Claude Code?

Run /statusline followed by what you want to see, for example /statusline show model, git branch and context percentage. Claude Code writes a script in ~/.claude/ and adds a statusLine entry to your settings. You can also write the script yourself and point statusLine.command at it.

Does the Claude Code status line use tokens?

No. The script runs locally on data Claude Code already has, and it doesn't make API calls unless your own script does.

Why is my Claude Code status line blank?

Usually the script isn't executable, writes to stderr instead of stdout, exits with a non-zero code, or prints nothing. The status line also stays blank until you accept the workspace trust dialog for the folder, and when disableAllHooks is on. Run the script by hand with sample JSON, or start claude --debug to log its errors.

Can the status line show my 5-hour and weekly limits?

Yes, on claude.ai Pro and Max plans. Claude Code sends rate_limits.five_hour and rate_limits.seven_day, each with used_percentage and resets_at, after the first response of a session. With an API key the fields are absent, so read them with a fallback such as // empty in jq.

How do I remove the status line?

Run /statusline delete, or delete the statusLine entry from your settings file.

More guides

All guides

Know when your agents need you

Briefkin puts your Claude Code, Codex and Cursor sessions on one board: working, needs you, done or failed. Telegram pings you when one is waiting on you, and scheduled skills post their reports next to them.

Free during the open beta. No card.