1+ #! /bin/bash
2+ # Description: Full-featured statusline with comprehensive metrics and daily tracking
3+ # =============================================================================
4+ # Claude Code Custom Statusline
5+ # =============================================================================
6+ # Author: Mark Shawn (https://github.com/markshawn2020)
7+ # Community: Vibe Genius
8+ # Version: 1.0.0
9+ # Date: 2025-08-27
10+ #
11+ # Description:
12+ # A comprehensive statusline for Claude Code that displays:
13+ # - Current time and daily cost tracking
14+ # - Working directory and git branch
15+ # - Session metrics (duration, cost, code changes)
16+ # - Model information
17+ #
18+ # Features:
19+ # ✓ Real-time session cost and duration tracking
20+ # ✓ Daily cost accumulation with automatic reset
21+ # ✓ Git branch awareness
22+ # ✓ Code changes statistics (lines added/removed)
23+ # ✓ Beautiful ANSI color formatting
24+ #
25+ # Installation:
26+ # 1. Save this script to ~/.claude/statusline.sh
27+ # 2. Make it executable: chmod +x ~/.claude/statusline.sh
28+ # 3. Add to ~/.claude/settings.json:
29+ # {
30+ # "statusLine": {
31+ # "type": "command",
32+ # "command": "~/.claude/statusline.sh",
33+ # "padding": 0
34+ # }
35+ # }
36+ #
37+ # =============================================================================
38+
39+ # Read JSON input
40+ input=$( cat)
41+
42+ # Extract values using jq
43+ DURATION_MS=$( echo " $input " | jq -r ' .cost.total_duration_ms // 0' )
44+ COST_USD=$( echo " $input " | jq -r ' .cost.total_cost_usd // 0' )
45+ MODEL=$( echo " $input " | jq -r ' .model.display_name // "Claude"' )
46+ CURRENT_DIR=$( echo " $input " | jq -r ' .workspace.current_dir // "~"' )
47+ SESSION_ID=$( echo " $input " | jq -r ' .session_id // ""' )
48+ LINES_ADDED=$( echo " $input " | jq -r ' .cost.total_lines_added // 0' )
49+ LINES_REMOVED=$( echo " $input " | jq -r ' .cost.total_lines_removed // 0' )
50+
51+ # Get current time with date (without year and seconds)
52+ CURRENT_TIME=$( date +" %m-%d %H:%M" )
53+
54+ # Daily cost tracking file
55+ TODAY=$( date +" %Y-%m-%d" )
56+ COST_FILE=" $HOME /.claude/.daily_costs"
57+ COST_SESSIONS_FILE=" $HOME /.claude/.daily_sessions"
58+
59+ # Initialize or update daily cost
60+ if [ -n " $SESSION_ID " ]; then
61+ # Check if this session has been tracked today
62+ if [ -f " $COST_SESSIONS_FILE " ]; then
63+ SESSION_TRACKED=$( grep " ^$TODAY :$SESSION_ID :" " $COST_SESSIONS_FILE " 2> /dev/null | cut -d: -f3)
64+ else
65+ SESSION_TRACKED=" 0"
66+ fi
67+
68+ # Calculate new cost for this session
69+ SESSION_COST_DIFF=$( echo " $COST_USD - ${SESSION_TRACKED:- 0} " | bc 2> /dev/null || echo " 0" )
70+
71+ # Update session tracking
72+ if [ " $SESSION_COST_DIFF " != " 0" ] && [ " $SESSION_COST_DIFF " != " 0.000" ]; then
73+ # Update session record
74+ grep -v " ^$TODAY :$SESSION_ID :" " $COST_SESSIONS_FILE " 2> /dev/null > " $COST_SESSIONS_FILE .tmp" || true
75+ echo " $TODAY :$SESSION_ID :$COST_USD " >> " $COST_SESSIONS_FILE .tmp"
76+ mv " $COST_SESSIONS_FILE .tmp" " $COST_SESSIONS_FILE " 2> /dev/null || true
77+
78+ # Update daily total
79+ if [ -f " $COST_FILE " ]; then
80+ DAILY_COST=$( grep " ^$TODAY :" " $COST_FILE " 2> /dev/null | cut -d: -f2 || echo " 0" )
81+ else
82+ DAILY_COST=" 0"
83+ fi
84+ NEW_DAILY_COST=$( echo " $DAILY_COST + $SESSION_COST_DIFF " | bc 2> /dev/null || echo " 0" )
85+ grep -v " ^$TODAY :" " $COST_FILE " 2> /dev/null > " $COST_FILE .tmp" || true
86+ echo " $TODAY :$NEW_DAILY_COST " >> " $COST_FILE .tmp"
87+ mv " $COST_FILE .tmp" " $COST_FILE " 2> /dev/null || true
88+ fi
89+ fi
90+
91+ # Read daily cost
92+ if [ -f " $COST_FILE " ]; then
93+ DAILY_COST=$( grep " ^$TODAY :" " $COST_FILE " 2> /dev/null | cut -d: -f2 || echo " 0" )
94+ else
95+ DAILY_COST=" 0"
96+ fi
97+
98+ # Format daily cost
99+ DAILY_COST_STR=$( printf " $%.2f" $DAILY_COST 2> /dev/null || echo " $0 .00" )
100+
101+ # Get directory name (basename)
102+ DIR_NAME=$( basename " $CURRENT_DIR " )
103+
104+ # Get git branch if in a git repo
105+ GIT_BRANCH=" "
106+ if [ -d " $CURRENT_DIR /.git" ] || git -C " $CURRENT_DIR " rev-parse --git-dir > /dev/null 2>&1 ; then
107+ BRANCH=$( git -C " $CURRENT_DIR " branch --show-current 2> /dev/null)
108+ if [ -n " $BRANCH " ]; then
109+ GIT_BRANCH=" \033[91m(\033[0m\033[91m$BRANCH \033[0m\033[91m)\033[0m"
110+ fi
111+ fi
112+
113+ # Format duration (convert ms to human-readable)
114+ format_duration () {
115+ local ms=$1
116+ local seconds=$(( ms / 1000 ))
117+ local minutes=$(( seconds / 60 ))
118+ local hours=$(( minutes / 60 ))
119+
120+ if [ $hours -gt 0 ]; then
121+ printf " %dh %dm" $hours $(( minutes % 60 ))
122+ elif [ $minutes -gt 0 ]; then
123+ printf " %dm %ds" $minutes $(( seconds % 60 ))
124+ else
125+ printf " %ds" $seconds
126+ fi
127+ }
128+
129+ DURATION_STR=$( format_duration $DURATION_MS )
130+
131+ # Format cost with proper decimal places
132+ COST_STR=$( printf " $%.3f" $COST_USD )
133+
134+ # Format lines changes
135+ if [ " $LINES_ADDED " -gt 0 ] || [ " $LINES_REMOVED " -gt 0 ]; then
136+ LINES_STR=" 📊 \033[92m+$LINES_ADDED \033[0m/\033[91m-$LINES_REMOVED \033[0m"
137+ else
138+ LINES_STR=" "
139+ fi
140+
141+ # Format session ID (first 8 chars)
142+ SESSION_SHORT=" ${SESSION_ID: 0: 8} "
143+
144+ # Get Claude Code version
145+ CC_VERSION=$( claude code --version 2> /dev/null | grep -oE ' [0-9]+\.[0-9]+\.[0-9]+' | head -1)
146+ if [ -n " $CC_VERSION " ]; then
147+ VERSION_STR=" V$CC_VERSION "
148+ else
149+ VERSION_STR=" "
150+ fi
151+
152+ # Detect provider from ANTHROPIC_BASE_URL
153+ detect_provider () {
154+ local base_url=" ${ANTHROPIC_BASE_URL:- } "
155+
156+ if [ -z " $base_url " ]; then
157+ echo " anthropic"
158+ return
159+ fi
160+
161+ case " $base_url " in
162+ * " zenmux" * ) echo " zenmux" ;;
163+ * " openrouter" * ) echo " openrouter" ;;
164+ * " modelgate" * ) echo " modelgate" ;;
165+ * " openai" * ) echo " openai" ;;
166+ * " anthropic" * ) echo " anthropic" ;;
167+ * " localhost" * |* " 127.0.0.1" * ) echo " local" ;;
168+ * ) echo " custom" ;;
169+ esac
170+ }
171+
172+ PROVIDER=$( detect_provider)
173+
174+ # Output with colors (using ANSI escape codes)
175+ # Format: 💥 MM-DD HH:MM ($X.XX) │ Model (provider) │ directory (branch) #session │ V2.0.73
176+ echo -e " 💥 \033[37m$CURRENT_TIME \033[0m \033[90m($DAILY_COST_STR )\033[0m \033[36m│\033[0m \033[35m$MODEL \033[0m \033[90m($PROVIDER )\033[0m \033[36m│\033[0m \033[96m$DIR_NAME \033[0m$GIT_BRANCH \033[90m#$SESSION_SHORT \033[0m \033[36m│\033[0m \033[33m$VERSION_STR \033[0m"
177+
178+ # End of statusline script
179+ # Shared with love by Mark Shawn for the Vibe Genius community 💜
0 commit comments