From all-skills
Guides creation and debugging of the Claude Code status line: a customizable shell-script-driven bar showing token usage, model, cost, git context, and more. Use when configuring statusLine in settings.json or writing status scripts.
How this skill is triggered — by the user, by Claude, or both
Slash command
/all-skills:claude-statuslineThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Guide for designing, configuring, and debugging the Claude Code status line — a customizable bar rendered at the bottom of the UI that runs a user-supplied shell script on each session update.
Guide for designing, configuring, and debugging the Claude Code status line — a customizable bar rendered at the bottom of the UI that runs a user-supplied shell script on each session update.
Activate this skill when:
statusLine block in settings.jsonsubagentStatusLineThe status line is a shell command that Claude Code executes locally on each session update. Claude Code pipes a JSON payload (model, workspace, context-window, cost, etc.) to the script's stdin and renders the script's stdout verbatim as the bar at the bottom of the UI. It runs on the user's machine, consumes no API tokens, and is temporarily hidden during autocomplete, help menus, and permission prompts.
The status line is gated by the same workspace-trust acceptance as hooks. Setting disableAllHooks: true in settings also disables the status line.
Add a statusLine block to ~/.claude/settings.json (user) or .claude/settings.json (project):
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh",
"padding": 2,
"refreshInterval": 5
}
}
Fields:
type — must be "command"command — path to a script, or an inline shell commandpadding (optional) — extra horizontal spacing in characters (default 0)refreshInterval (optional, seconds, min 1) — re-runs on a fixed timer in addition to event-driven updates; set this when displaying time-based data or when state changes during idle (e.g. subagent progress). Omit for event-only updates./statusline slash commandClaude Code ships a built-in /statusline <description> command that generates a script and updates settings for you (e.g. /statusline show model name and context percentage with a progress bar). Use /statusline delete to remove the configuration.
Every invocation receives a JSON object on stdin containing session metadata. Key top-level fields:
| Need | Field path |
|---|---|
| Model label | model.display_name (human) or model.id (stable) |
| Current folder | workspace.current_dir (basename for display) |
| Project root | workspace.project_dir |
| Context % | context_window.used_percentage (null-guard with // 0) |
| Cumulative tokens | context_window.total_input_tokens, .total_output_tokens |
| Cost USD | cost.total_cost_usd |
| Wall time ms | cost.total_duration_ms |
| Lines changed | cost.total_lines_added, .total_lines_removed |
| Cache key | session_id |
| Transcript file | transcript_path |
| Rate limits | rate_limits.five_hour.used_percentage (Pro/Max only) |
| Output style | output_style.name |
| Vim mode | vim.mode (absent when vim off) |
| Worktree | worktree.* / workspace.git_worktree |
See references/input-schema.md for the full JSON schema, nullable fields, and per-field semantics.
Note on context_window.used_percentage: pre-calculated by Claude Code as (input + cache_creation + cache_read) / context_window_size — output tokens are not included. Use this field rather than computing from current_usage or total_input_tokens (which is cumulative and can exceed the window size).
The default script shipped in assets/statusline-default.sh surfaces model, folder, context %, and git branch:
#!/usr/bin/env bash
input=$(cat)
MODEL=$(jq -r '.model.display_name // "Claude"' <<<"$input")
DIR=$(jq -r '.workspace.current_dir // .cwd' <<<"$input")
PCT=$(jq -r '.context_window.used_percentage // 0' <<<"$input" | cut -d. -f1)
BRANCH=""
if git -C "$DIR" rev-parse --git-dir >/dev/null 2>&1; then
B=$(git -C "$DIR" branch --show-current 2>/dev/null)
[ -n "$B" ] && BRANCH=" | 🌿 $B"
fi
echo "[$MODEL] 📁 ${DIR##*/} | ${PCT}% ctx${BRANCH}"
Install it:
cp assets/statusline-default.sh ~/.claude/statusline.sh
chmod +x ~/.claude/statusline.sh
Then add to ~/.claude/settings.json:
{ "statusLine": { "type": "command", "command": "~/.claude/statusline.sh" } }
Renders e.g. [Opus] 📁 my-project | 42% ctx | 🌿 main.
echo/print line becomes a separate row (multi-line supported).\033[32m green, \033[33m yellow, \033[31m red, \033[0m reset.FORCE_HYPERLINK=1 for terminals that aren't auto-detected.PCT=$(jq -r '.context_window.used_percentage // 0' <<<"$input" | cut -d. -f1)
if [ "$PCT" -lt 70 ]; then COLOR="\033[32m" # green
elif [ "$PCT" -lt 90 ]; then COLOR="\033[33m" # yellow
else COLOR="\033[31m"; fi # red
printf "${COLOR}%d%% ctx\033[0m\n" "$PCT"
refreshInterval to keep time-based data live.Expensive operations (git branch lookups, network calls, file reads) should be cached because the script runs on every update.
session_id — stable per session. Do not use $$ / pid; those change on every invocation./tmp or $XDG_CACHE_HOME with the session id in the filename.SID=$(jq -r '.session_id' <<<"$input")
CACHE="/tmp/statusline-${SID}.branch"
if [ ! -f "$CACHE" ] || [ $(($(date +%s) - $(stat -f %m "$CACHE" 2>/dev/null || stat -c %Y "$CACHE"))) -gt 30 ]; then
git -C "$DIR" branch --show-current 2>/dev/null > "$CACHE"
fi
BRANCH=$(cat "$CACHE" 2>/dev/null)
A parallel subagentStatusLine setting customizes the row rendered inside the subagent panel. Input adds a tasks array with {id, name, tokenCount, ...}. Output expects NDJSON — one JSON object per line:
{"id":"task-abc","content":"analyzing schema..."}
{"id":"task-def","content":"✓ done"}
Use this to project per-subagent progress into the UI.
Pipe canned JSON to the script:
echo '{
"model": {"display_name": "Opus"},
"workspace": {"current_dir": "/tmp/x"},
"context_window": {"used_percentage": 42},
"session_id": "test"
}' | ~/.claude/statusline.sh
Iterate until the output looks right, then trigger an assistant message in Claude Code to see it rendered.
used_percentage is null before the first API call — always // 0 or similar fallback.total_input_tokens is cumulative across the session and can exceed the window size. Never divide it by context_window_size for a percentage — use used_percentage.rate_limits is Pro/Max only and absent before the first API response.git ... 2>/dev/null.session_name, workspace.git_worktree, vim, agent, worktree, rate_limits. Default them with // "fallback" in jq.powershell -NoProfile -File %USERPROFILE%\.claude\statusline.ps1.disableAllHooks: true also disables the status line.npx claudepluginhub vinnie357/claude-skills --plugin qaDevelops custom status lines for Claude Code to display git branch, context usage, model name, and session costs using bash scripts that process JSON stdin input.
Interactive wizard sets up Claude Code's custom status line with progress bars, token counts, git branch, model name, and session info. Cross-platform for Mac/Linux/Windows via bash/PowerShell scripts.
Configures Claude Code status lines using /statusline command, settings.json, Bash/Python/Node.js scripts. Covers JSON input, git integration, ANSI colors, helper functions, and troubleshooting.