Skip to content

Instantly share code, notes, and snippets.

@kyxap1
Last active May 28, 2026 15:52
Show Gist options
  • Select an option

  • Save kyxap1/f50c0d80479ad0bc8bdfe0cfe4ac12fd to your computer and use it in GitHub Desktop.

Select an option

Save kyxap1/f50c0d80479ad0bc8bdfe0cfe4ac12fd to your computer and use it in GitHub Desktop.
My statusline for claude code

My statusline for Claude Code

A powerline-style two-line status bar for Claude Code that shows model, git branch, directory, effort level, cost, session duration, context usage, token counts, and rate limits — all at a glance.

image

Structure

Line 1:  <model> ❯ <branch> ❯ <directory>  5h:<rate-limit>%
Line 2:  <effort> ❯ $<cost> ❯ <duration> <context-bar> <context-%>  t:<input>/<output>
Segment Source field Example
Model model.display_name Opus
Branch git branch --show-current feat/statusline
Directory workspace.current_dir (basename) claude-sandbox
5h rate limit rate_limits.five_hour.used_percentage 5h:23%
Effort effort.level high
Cost cost.total_cost_usd $1.42
Duration cost.total_duration_ms 12m05s
Context bar context_window.used_percentage ▰▰▰▰▱▱▱▱▱▱ 42%
Tokens context_window.total_input_tokens / total_output_tokens t:156k/12k

Prerequisites

  • jq — JSON parser (brew install jq)
  • A Nerd Font — the powerline separators ( ) and icons (branch, folder) require patched font glyphs

Installation

  1. Save statusline.sh to ~/.claude/statusline.sh
  2. chmod +x ~/.claude/statusline.sh
  3. Add to ~/.claude/settings.json:
    {
      "statusLine": {
        "type": "command",
        "command": "~/.claude/statusline.sh"
      }
    }

Customization

Colors

The script uses 256-color ANSI codes. Key values:

Variable Color code Used for
A_BG 234 Dark background (model, effort segments)
B_BG 236 Mid background (branch, cost segments)
C_BG 234 Dark background (dir, duration segments)
GREEN_FG 148 Filled context bar blocks, percentage
DIM_FG 240 Empty context bar blocks

Preview 256-color codes:

for i in {0..255}; do printf "\033[48;5;%sm %3s \033[0m" $i $i; ((i%16==15)) && echo; done

Segments

Each segment follows the pattern:

printf "$(fg COLOR)$(bg BG) CONTENT ${R}"
printf "$(fg BG)$(bg NEXT_BG)${SEP}${R}"

The SEP variable ( ) creates the powerline arrow. Set its foreground to the current segment's background and its background to the next segment's background.

Token formatting

fmt_tokens converts raw counts: 500500, 1560015k, 12000001.2M.

Available data fields

Full list of JSON fields Claude Code sends via stdin
Field Description
model.id, model.display_name Model identifier and name
workspace.current_dir Current working directory
workspace.project_dir Directory where Claude Code was launched
workspace.added_dirs Additional dirs added via /add-dir
workspace.git_worktree Git worktree name (if in a linked worktree)
workspace.repo.host, .owner, .name Repository identity from origin remote
cost.total_cost_usd Estimated session cost in USD
cost.total_duration_ms Wall-clock time since session start
cost.total_api_duration_ms Time spent waiting for API responses
cost.total_lines_added, .total_lines_removed Lines of code changed
context_window.total_input_tokens Input tokens in current context window
context_window.total_output_tokens Output tokens from most recent response
context_window.context_window_size Max context size (200k or 1M)
context_window.used_percentage Pre-calculated context usage %
context_window.current_usage.* Per-component breakdown (input, cache write, cache read)
effort.level Reasoning effort: low / medium / high / xhigh / max
thinking.enabled Whether extended thinking is on
rate_limits.five_hour.used_percentage 5-hour rate limit usage %
rate_limits.seven_day.used_percentage 7-day rate limit usage %
exceeds_200k_tokens Whether total tokens exceed 200k
session_id, session_name Session ID and custom name
version Claude Code version
vim.mode NORMAL / INSERT / VISUAL / VISUAL LINE
agent.name Agent name (when using --agent)
pr.number, pr.url, pr.review_state Open PR info for current branch
worktree.name, .path, .branch Worktree session info

Tips

  • The statusline runs locally and does not consume API tokens.
  • Updates after each assistant message, after /compact, and on permission mode changes (debounced at 300ms).
  • Add "refreshInterval": 5 to the settings block to also refresh on a timer (useful while subagents run).
  • COLUMNS and LINES env vars are available inside the script for terminal-width-aware layouts.
  • Use /statusline command with a natural-language description to generate or regenerate interactively.

Docs

#!/bin/bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
EFFORT=$(echo "$input" | jq -r '.effort.level // "?"')
INPUT_T=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
OUTPUT_T=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
RATE_5H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
fmt_tokens() {
local t=$1
if [ "$t" -ge 1000000 ]; then
local m=$((t / 100000))
echo "$((m / 10)).$((m % 10))M"
elif [ "$t" -ge 1000 ]; then
echo "$((t / 1000))k"
else
echo "${t}"
fi
}
IN_FMT=$(fmt_tokens "$INPUT_T")
OUT_FMT=$(fmt_tokens "$OUTPUT_T")
MINS=$((DURATION_MS / 60000)); SECS=$(((DURATION_MS % 60000) / 1000))
COST_FMT=$(printf '$%.2f' "$COST")
TIME_FMT=$(printf '%3dm%02ds' "$MINS" "$SECS")
BRANCH=""
git rev-parse --git-dir > /dev/null 2>&1 && BRANCH=$(git branch --show-current 2>/dev/null)
ICON_BRANCH=$'\xee\x82\xa0'
ICON_FOLDER=$'\xef\x84\x95'
SEP=$'\xee\x82\xb0'
A_BG='234'; B_BG='236'; C_BG='234'
R='\033[0m'; BOLD='\033[1m'
GREEN_FG='\033[38;5;148m'
DIM_FG='\033[38;5;240m'
fg() { printf '\033[38;5;%sm' "$1"; }
bg() { printf '\033[48;5;%sm' "$1"; }
DIR_SHORT="${DIR##*/}"
# build bar
FILLED=$((PCT * 10 / 100)); EMPTY=$((10 - FILLED))
[ "$FILLED" -gt 10 ] && FILLED=10 && EMPTY=0
BAR=""
for ((i=0;i<FILLED;i++)); do BAR+="${GREEN_FG}▰"; done
for ((i=0;i<EMPTY;i++)); do BAR+="${DIM_FG}▱"; done
# line 1: MODEL > BRANCH > FOLDER DIR > 5h:XX%
printf "${BOLD}$(fg 245)$(bg $A_BG) ${MODEL} ${R}"
printf "$(fg $A_BG)$(bg $B_BG)${SEP}${R}"
if [ -n "$BRANCH" ]; then
printf "$(fg 252)$(bg $B_BG) ${ICON_BRANCH} ${BRANCH} ${R}"
printf "$(fg $B_BG)$(bg $C_BG)${SEP}${R}"
fi
printf "$(fg 245)$(bg $C_BG) ${ICON_FOLDER} ${DIR_SHORT} ${R}"
printf "$(fg $C_BG)${SEP}${R}"
if [ -n "$RATE_5H" ]; then
printf " $(fg 245)5h:$(printf '%.0f' "$RATE_5H")%%"
fi
echo ""
# line 2: EFFORT > COST > TIME BAR PCT% > t:IN/OUT
printf "${BOLD}$(fg 245)$(bg $A_BG) ${EFFORT} ${R}"
printf "$(fg $A_BG)$(bg $B_BG)${SEP}${R}"
printf "$(fg 252)$(bg $B_BG) ${COST_FMT} ${R}"
printf "$(fg $B_BG)$(bg $C_BG)${SEP}${R}"
printf "$(fg 245)$(bg $C_BG) ${TIME_FMT} ${BAR}${R}$(bg $C_BG) $(fg 148)${PCT}%% ${R}"
printf "$(fg $C_BG)${SEP}${R}"
printf " $(fg 245)t:${IN_FMT}/${OUT_FMT}"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment