Skip to content

Instantly share code, notes, and snippets.

@mavwolverine
Last active May 6, 2026 06:23
Show Gist options
  • Select an option

  • Save mavwolverine/535cc7ca1fdaafee5fc7b2a27eff690f to your computer and use it in GitHub Desktop.

Select an option

Save mavwolverine/535cc7ca1fdaafee5fc7b2a27eff690f to your computer and use it in GitHub Desktop.
claude status line for showing context usage to avoid auto compact surprises
{
"statusLine": {
"type": "command",
"command": "/bin/sh ~/.claude/scripts/statusline-command.sh"
}
}

Claude Code Status Line

A custom statusLine script for Claude Code that displays workspace context in the terminal status bar.

Output format

~/path/to/project [develop ⇡2 !1 ?2] | Sonnet 4.6 ctx:12% 5h:7% 7d:3%

Segment Description
~/path/to/project Workspace directory (home shortened to ~)
[develop ⇡2 !1 ?2] Git branch, commits ahead/behind, modified files, untracked entries
Sonnet 4.6 Active Claude model
ctx:12% Context window usage for the current session
5h:7% 5-hour rolling rate limit usage
7d:3% 7-day rolling rate limit usage

Color coding

Percentages are color-coded (label stays plain, value is colored):

  • Green — 0–50%
  • Amber — 51–80%
  • Red — 81–100%

Notes

  • ctx defaults to 0% on first launch before any API call is made.
  • 5h and 7d show - on first launch — Claude Code does not provide rate limit data until after the first message in a session.

Installation

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

Requirements

  • jq — for parsing JSON input from Claude Code
  • git — for branch/status information
# ~/.claude/scripts/statusline-command.sh
#!/bin/sh
# Claude Code status line: dir | git branch+status | model | context% (color-coded)
input=$(cat)
cwd=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // ""')
model=$(echo "$input" | jq -r '.model.display_name // ""')
used_pct=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
# Shorten home directory to ~
short_cwd=$(echo "$cwd" | sed "s|^$HOME|~|")
# Git branch and status
git_info=""
if git -C "$cwd" rev-parse --git-dir > /dev/null 2>&1; then
branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null || git -C "$cwd" rev-parse --short HEAD 2>/dev/null)
if [ -n "$branch" ]; then
git_info=" [$branch"
# Ahead/behind remote
upstream=$(git -C "$cwd" rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null)
if [ -n "$upstream" ]; then
ahead=$(git -C "$cwd" rev-list --count @{u}..HEAD 2>/dev/null)
behind=$(git -C "$cwd" rev-list --count HEAD..@{u} 2>/dev/null)
[ "$ahead" -gt 0 ] 2>/dev/null && git_info="${git_info} ⇡${ahead}"
[ "$behind" -gt 0 ] 2>/dev/null && git_info="${git_info} ⇣${behind}"
fi
# Modified files
modified=$(git -C "$cwd" diff --name-only 2>/dev/null | wc -l | tr -d ' ')
staged=$(git -C "$cwd" diff --cached --name-only 2>/dev/null | wc -l | tr -d ' ')
total_modified=$(( modified + staged ))
[ "$total_modified" -gt 0 ] && git_info="${git_info} !${total_modified}"
# Untracked files (count ?? entries like p10k — directories count as 1)
untracked=$(git -C "$cwd" status --porcelain 2>/dev/null | grep -c '^??')
[ "$untracked" -gt 0 ] && git_info="${git_info} ?${untracked}"
git_info="${git_info}]"
fi
fi
# Helper: color for a percentage value (value only, not label)
pct_color() {
if [ "$1" -le 50 ]; then printf '\033[32m'
elif [ "$1" -le 80 ]; then printf '\033[33m'
else printf '\033[31m'
fi
}
reset=$(printf '\033[0m')
# Context window usage (default 0% if not yet available)
ctx_int=0
[ -n "$used_pct" ] && ctx_int=$(printf "%.0f" "$used_pct")
ctx_info=" ctx:$(pct_color "$ctx_int")${ctx_int}%${reset}"
# Helper: format a rate limit label — usage: rate_label <prefix> <pct> <resets_at> <date_fmt>
rate_label() {
prefix="$1" pct="$2" resets_at="$3" fmt="$4"
if [ -z "$pct" ]; then
printf "%s(-):-" "$prefix"
return
fi
pct_int=$(printf "%.0f" "$pct")
if [ -n "$resets_at" ]; then
time_part="($(date -r "$resets_at" "$fmt" 2>/dev/null || date -d "@$resets_at" "$fmt" 2>/dev/null))"
else
time_part="(-)"
fi
printf "%s%s:%s%s%%%s" "$prefix" "$time_part" "$(pct_color "$pct_int")" "$pct_int" "$reset"
}
# Rate limits
five_label=$(rate_label "5h" \
"$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')" \
"$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')" \
'+%H:%M')
seven_label=$(rate_label "7d" \
"$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')" \
"$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')" \
'+%m/%d %H:%M')
rate_info=" ${five_label} ${seven_label}"
printf "%s%s | %s%s%s\n" "$short_cwd" "$git_info" "$model" "$ctx_info" "$rate_info"
@mavwolverine
Copy link
Copy Markdown
Author

Screenshot 2026-05-05 at 11 21 32 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment