AI Coding Tools

Claude Code Statusline: Configure Your Terminal Status Line for Productivity (2026)

Aug 14, 202613 min read

A Claude Code statusline is a customizable line at the bottom of your terminal session that shows the active model, how much context is left, session cost, your git branch, and even rate limits. Turn it on in about 30 seconds with the /statusline command, or configure it by hand in ~/.claude/settings.json. The script runs locally and burns zero API tokens. Worth showing: model, context % (so /compact never surprises you), cost, and git so you stay in control of the work.

Author: Jasmine, a dev who lives in Claude Code every day on Windows.

What is the Claude Code statusline?

The Claude Code statusline is a customizable line rendered at the bottom of every Claude Code session, generated by a shell script you configure yourself. Whenever the session state changes, Claude Code calls that script, pipes the whole session state to it as JSON over stdin, and prints whatever the script writes back to stdout as your status line. In other words: you get a blob of JSON, pick the fields you care about, format them however you like, print them, and Claude Code just displays the result.

The key thing to internalize right away: the statusline runs locally on your machine, makes no API calls, and costs no tokens. It is not an "AI" feature - it is just a bash/PowerShell/Python script reading stdin. So you can show as much or as little as you want without touching your session bill. Claude Code only re-runs the script on events (model switch, tool call, context update, and so on) and lightly debounces the calls so it isn't firing constantly - which means a slightly heavier script is fine, as long as you don't abuse it (see the performance section below).

Unlike the default status bar (which only shows your working directory), a custom statusline lets you pull in exactly what matters to you while coding. If you're just getting started, read what Claude Code is and what it's for first for context, then come back here to configure it.

What should you show on the statusline to be more productive?

Don't cram every field onto the statusline. A short line you can skim in half a second and still act on is the good line. After a few months of real use, these are the things I find most worth showing:

  • Context percentage remaining - the number one thing. When context drops into the danger zone, you can proactively /compact or split the work, instead of Claude Code compressing the conversation on you mid-task.
  • Active model - knowing whether you're on Opus or Sonnet so you don't use a sledgehammer on a thumbtack (or vice versa). It's easy to forget you just switched models.
  • Session cost - a running USD figure gives you a feel for which tasks are burning money, especially when you're paying per API token.
  • Git branch + staged/modified file count - avoid committing to the wrong branch, and see how many unsaved changes you have.
  • 5-hour / 7-day rate limits (Pro/Max plans) - see your allowance running low so you don't get cut off in the middle of a long task.
  • Directory / worktree - handy when you have several worktrees open at once.
FieldWhy show it
context %Avoid a surprise /compact, tidy the conversation on your terms
modelKnow which model you're on, pick the right one for the job
costKeep session spending under control
git branch + diffNever commit to the wrong branch, see work in progress
rate limitDon't run out of allowance mid-task (Pro/Max)

My rule: line 1 always has model + context %, and cost/git/rate limit get added only when I actually need them. For more of the commands I reach for daily, see the Claude Code cheat sheet.

The fastest way: the /statusline command

If you don't want to touch a config file, the fastest route is to just ask, in plain English, right inside your Claude Code session. Type /statusline followed by a description of what you want to see:

/statusline show model name and context percentage with a progress bar

Claude Code will write the script for you, save it under ~/.claude/, and add the configuration block to settings.json automatically. Because this step creates a new file and edits your config, Claude Code will ask you to approve the changes before writing - just read them over and accept. Once it's done, the statusline shows up on your very next interaction.

This is the best way to get a quick draft, which you can then open and hand-tune to taste. If you want to understand the basic controls and workflow first, see the Claude Code guide for beginners.

Manual setup via settings.json (step by step)

Want full control? Configure it by hand. It's only 3 steps.

Step 1 - Create the script ~/.claude/statusline.sh that reads JSON from stdin, uses jq to pull the fields you want, and prints one line:

#!/bin/bash
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name // "?"')
dir=$(echo "$input" | jq -r '.workspace.current_dir // "."' | xargs basename)
pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0')
printf "[%s] 📁 %s | %s%% context" "$model" "$dir" "$pct"

Step 2 - Make it executable:

chmod +x ~/.claude/statusline.sh

⚠️ The most common mistake: forgetting chmod +x means the statusline shows nothing at all, with no clear error. If your status line is "silent," check the execute permission first.

Step 3 - Declare it in ~/.claude/settings.json:

{
 "statusLine": {
 "type": "command",
 "command": "~/.claude/statusline.sh",
 "padding": 0
 }
}

Claude Code reloads it on your next interaction - no restart needed. A couple of useful options: padding controls the left margin (set it to 0 to sit flush against the edge), and refreshInterval (in milliseconds) forces the script to re-run on a timer for time-based data like a clock or rate limits. For a really short script you can even inline the jq -r command directly in the command field with no separate file - but a separate file is much easier to maintain.

The JSON data table - what the statusline receives

On each run, the script receives a full JSON object over stdin. Here's a reference for the fields you'll use most (source: the official docs at code.claude.com/docs/en/statusline, accessed 08/2026):

FieldMeaning
model.display_name / model.idDisplay name and ID of the active model
workspace.current_dirCurrent working directory
workspace.project_dirProject root directory
workspace.git_worktree / repo.*Worktree and git repo information
context_window.used_percentagePercentage of context used
context_window.remaining_percentagePercentage of context remaining
context_window.context_window_sizeSize of the context window
context_window.current_usageTokens currently in use
cost.total_cost_usdSession cost (USD)
cost.total_duration_msSession duration (milliseconds)
cost.total_lines_addedLines of code added
rate_limits.five_hour.used_percentage5-hour allowance used (Pro/Max)
rate_limits.seven_day.used_percentage7-day allowance used
rate_limits.*.resets_atWhen the allowance resets
effort.levelCurrent "effort" level
output_style.nameName of the active output style
pr.number / pr.url / pr.review_statePR number, URL and review state
session_idSession ID (use it for caching - see the performance section)
versionClaude Code version

Important note: many fields can be missing or null, especially before the first API response. Always use fallbacks in jq: // 0 for numbers, // "empty" or // "" for strings. Some newer fields require a recent enough Claude Code build; don't claim a field doesn't exist unless you've tested it on the build you're running.

Copy-paste sample scripts (pick the one you need)

The presets below use bash + jq. If you write yours in Python or Node, JSON parsing is built in, so they get even shorter.

1) Context bar - progress bar + %:

#!/bin/bash
input=$(cat)
pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
filled=$((pct / 10)); empty=$((10 - filled))
bar=$(printf '▓%.0s' $(seq 1 $filled))$(printf '░%.0s' $(seq 1 $empty))
printf "%s %s%%" "$bar" "$pct"

2) Colored git - branch + staged (green) / modified (yellow) files, using ANSI color codes:

#!/bin/bash
input=$(cat)
branch=$(git branch --show-current 2>/dev/null)
staged=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')
modified=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')
printf " %s \033[32m+%s\033[0m \033[33m~%s\033[0m" "$branch" "$staged" "$modified"

3) Cost + duration:

#!/bin/bash
input=$(cat)
cost=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
ms=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
sec=$((ms / 1000)); min=$((sec / 60)); s=$((sec % 60))
printf "\$%.2f | %dm %ds" "$cost" "$min" "$s"

4) Multi-line + color thresholds - line 1: model/dir/branch; line 2: a bar that changes color (green <70, yellow 70-89, red 90+) + cost + rate limit:

#!/bin/bash
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name // "?"')
dir=$(echo "$input" | jq -r '.workspace.current_dir // "."' | xargs basename)
branch=$(git branch --show-current 2>/dev/null)
pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
cost=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
rl=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
if [ "$pct" -ge 90 ]; then c="\033[31m"; elif [ "$pct" -ge 70 ]; then c="\033[33m"; else c="\033[32m"; fi
printf "[%s] 📁 %s %s\n" "$model" "$dir" "$branch"
printf "${c}%s%% context\033[0m | \$%.2f" "$pct" "$cost"
[ -n "$rl" ] && printf " | 5h: %s%%" "$rl"

This multi-line preset is the one I actually run every day: the top line to orient myself, the bottom line changing color to warn me when context is filling up - very effective for not getting /compact-ed mid-flow.

Setting it up on Windows (PowerShell + Git Bash)

Most guides out there are bash-only. If you're on Windows (like me), there are two paths that work.

Option A - Git Bash: the simplest. The .sh scripts above run directly, as long as Git Bash and jq are installed. Point command at the .sh file as usual.

Option B - PowerShell: write a .ps1 script that reads stdin and parses the JSON:

# C:/Users/you/.claude/statusline.ps1
$data = $input | Out-String | ConvertFrom-Json
$model = $data.model.display_name
$pct = [math]::Floor($data.context_window.used_percentage)
Write-Host "[$model] $pct% context" -NoNewline

Then declare it in settings.json:

{
 "statusLine": {
 "type": "command",
 "command": "powershell -NoProfile -File C:/Users/you/.claude/statusline.ps1"
 }
}

⚠️ The Windows backslash trap: always write paths with forward slashes (/) in the command field. Git Bash "eats" the backslash \, so the command fails silently - the statusline shows nothing and reports no error. The ~ character still works fine.

This is exactly the thing that trips up a lot of Windows users: the script is correct but the path has the wrong slashes. Swap \ for / and it runs.

Performance tip: don't let the statusline slow your session down

The script runs very often. On a big repo, git status or git diff can take a few hundred milliseconds each time - multiply that out and the whole session feels slightly sluggish. A few tips to keep the statusline fast:

  • Cache git results to a temp file keyed by session_id, refreshing every ~5 seconds instead of calling git on every run. Use session_id as the cache key - do not use $$/PID, because it changes on every script run and makes the cache useless.
  • Keep the output short - one line, a few fields. A long line is both slow and hard to read.
  • Use refreshInterval for time-based data (clock, rate limits) instead of recomputing it the hard way.
  • Read COLUMNS/LINES to gauge the width and trim when the terminal is narrow.

Rule of thumb: if the script takes more than ~300ms, you'll feel the lag. Caching and trimming are the two biggest levers.

Common problems & how to fix them

SymptomCause & fix
Nothing shows upForgot chmod +x on the script (mistake #1); or the script prints to stderr instead of stdout
Still blank after chmodHaven't accepted workspace trust - the statusline needs trust like hooks; or disableAllHooks: true is set
Works in Bash, breaks on WindowsPath uses \ - switch to /
Shows -- or blanks right after openingFields are still null before the first API response - use fallbacks // 0 / // empty

To diagnose, run claude --debug and look at the script's exit code and stderr. Also, some emulators (Terminal.app, for example) don't support OSC 8 links, so if you embed a hyperlink in your statusline it may not be clickable - that's a terminal limitation, not a script bug.

Don't want to edit scripts? Use a visual status line builder

Not everyone wants to write bash or PowerShell just to get one status line. If that's you, one no-code option is the AgentKit bundle — now $149 (from $198): its desktop app has a visual status line builder - drag and drop fields (model, context, cost, git, and so on) instead of hand-coding - alongside one place to manage your license, skills and MCP integrations. For anyone wary of the terminal, it's a way to build a statusline without touching settings.json.

To be straight with you: /statusline and the scripts above are completely free and good enough for almost everyone - the visual builder is just more convenient if you want no-code or want to manage your whole skill/agent set in one place. If you want to dig in before deciding, read what AgentKit is and whether it's worth it (review).

Frequently asked questions (FAQ)

Does the statusline cost tokens?

No. The statusline runs a local script on your machine and makes no Claude API calls, so it uses no tokens. You can display as much information as you want without affecting your session cost.

Does it work on Windows?

Yes. You can run .sh scripts through Git Bash, or write a .ps1 and call it with powershell -NoProfile -File. Just write your paths with forward slashes (/) to avoid the backslash trap.

Why isn't my statusline showing up?

The most common cause is forgetting chmod +x on the script. Others: the script prints to stderr instead of stdout, you haven't accepted workspace trust, disableAllHooks is on, or the path has the wrong slashes on Windows. Run claude --debug to see the error.

How is /statusline different from editing settings.json?

The /statusline command lets Claude Code generate the script and configure it for you from a plain-English description - fast, and great for beginners. Editing settings.json by hand gives you full control over the content and formatting. Many people use /statusline to get a draft, then hand-tune the file.

What's the point of showing context %?

To manage the conversation proactively. When context is nearly full, you can /compact or split the work yourself instead of Claude Code compressing it on you mid-task - which tends to break your train of context.

Is there a ready-made config that needs no code?

Yes. The fastest is /statusline, which lets Claude write it for you. If you want a fully drag-and-drop, no-code interface, the visual status line builder in AgentKit's desktop app is one option.

Conclusion + next steps

You don't need an elaborate script. A single simple line showing model + context % already gives a noticeable productivity boost; just level it up as you feel the need. Start with /statusline, then open the file and tune it to taste. Read the Claude Code cheat sheet to collect the commands you'll use often, and the CLAUDE.md guide to help Claude Code understand your project better. Just starting out? Head back to what Claude Code is.

Want Claude Code more powerful right away? If you'd rather not write scripts and want to build your statusline with a drag-and-drop interface, plus a full set of ready-made skills and agents, take a look at this toolkit.

Try AgentKit (20% off via link) →

J

Jasmine

Author · Jasmine Daily

The writer behind Jasmine Daily - jotting down thoughts, experiences, and everyday moments. Honest, unhurried, imperfect.

Jasmine Daily

There's more waiting to be read.

If this piece spoke to you, browse a few more pages from the journal.

Read next

Related posts