- Nerd Font in your terminal emulator https://www.nerdfonts.com/
Copy the statusline.sh script in this gist to ~/.claude and make it executable
chmod +x ~/.claude/statusline.shUpdate the statusline in your claude config
Copy the statusline.sh script in this gist to ~/.claude and make it executable
chmod +x ~/.claude/statusline.shUpdate the statusline in your claude config
| #!/bin/bash | |
| # Powerline/Nerd Font symbols (UTF-8 hex bytes) | |
| SEP=$'\xee\x82\xb4' # U+E0B4 rounded powerline | |
| SEP_THIN=$'\xee\x82\xb5' # U+E0B5 thin separator | |
| # Nerd Font icons (UTF-8 hex bytes) | |
| ICON_BOLT=$'\xef\x83\xa7' # U+F0E7 bolt | |
| ICON_FOLDER=$'\xef\x81\xbc' # U+F07C folder | |
| ICON_CHART=$'\xef\x87\xbe' # U+F1FE chart | |
| ICON_DOLLAR=$'\xef\x85\x95' # U+F155 dollar | |
| ICON_CLOCK=$'\xef\x80\x97' # U+F017 clock | |
| ICON_PENCIL=$'\xef\x81\x84' # U+F044 pencil | |
| ICON_BRANCH=$'\xef\x90\x98' # U+E0A0 git branch | |
| # ANSI color codes (foreground/background) | |
| RESET='\033[0m' | |
| BOLD='\033[1m' | |
| # Color palette for powerline segments | |
| BG_PURPLE='\033[48;5;141m' | |
| FG_PURPLE='\033[38;5;141m' | |
| FG_ON_PURPLE='\033[38;5;235m' | |
| BG_BLUE='\033[48;5;75m' | |
| FG_BLUE='\033[38;5;75m' | |
| FG_ON_BLUE='\033[38;5;235m' | |
| BG_GREEN='\033[48;5;150m' | |
| FG_GREEN='\033[38;5;150m' | |
| FG_ON_GREEN='\033[38;5;235m' | |
| BG_YELLOW='\033[48;5;222m' | |
| FG_YELLOW='\033[38;5;222m' | |
| FG_ON_YELLOW='\033[38;5;235m' | |
| BG_ORANGE='\033[48;5;216m' | |
| FG_ORANGE='\033[38;5;216m' | |
| FG_ON_ORANGE='\033[38;5;235m' | |
| BG_RED='\033[48;5;210m' | |
| FG_RED='\033[38;5;210m' | |
| FG_ON_RED='\033[38;5;235m' | |
| BG_CYAN='\033[48;5;117m' | |
| FG_CYAN='\033[38;5;117m' | |
| FG_ON_CYAN='\033[38;5;235m' | |
| BG_PINK='\033[48;5;218m' | |
| FG_PINK='\033[38;5;218m' | |
| FG_ON_PINK='\033[38;5;235m' | |
| # Read JSON input once | |
| input=$(cat) | |
| # Helper functions for common extractions | |
| get_model_name() { echo "$input" | jq -r '.model.display_name'; } | |
| get_current_dir() { echo "$input" | jq -r '.workspace.current_dir'; } | |
| get_project_dir() { echo "$input" | jq -r '.workspace.project_dir'; } | |
| get_cost() { echo "$input" | jq -r '.cost.total_cost_usd'; } | |
| get_duration() { echo "$input" | jq -r '.cost.total_duration_ms'; } | |
| get_lines_added() { echo "$input" | jq -r '.cost.total_lines_added'; } | |
| get_lines_removed() { echo "$input" | jq -r '.cost.total_lines_removed'; } | |
| get_context_size() { echo "$input" | jq -r '.context_window.context_window_size'; } | |
| get_current_usage() { echo "$input" | jq '.context_window.current_usage'; } | |
| get_git_branch() { | |
| local dir=$(get_current_dir) | |
| if [[ -d "$dir" ]]; then | |
| git -C "$dir" rev-parse --abbrev-ref HEAD 2>/dev/null | |
| fi | |
| } | |
| # Powerline segment builder | |
| # Usage: segment "bg_color" "fg_color" "fg_for_sep" "next_bg" "content" | |
| segment() { | |
| local bg="$1" | |
| local fg="$2" | |
| local fg_sep="$3" | |
| local next_bg="$4" | |
| local content="$5" | |
| if [[ -z "$content" ]]; then | |
| return | |
| fi | |
| # Print segment with content | |
| printf "%b%b%b %s %b" "$bg" "$fg" "$BOLD" "$content" "$RESET" | |
| # Print separator to next segment | |
| if [[ -z "$next_bg" ]]; then | |
| # Last segment - separator to transparent background | |
| printf "%b%s%b" "$fg_sep" "$SEP" "$RESET" | |
| else | |
| # Separator to next colored segment | |
| printf "%b%b%s%b" "$next_bg" "$fg_sep" "$SEP" "$RESET" | |
| fi | |
| } | |
| format_model() { | |
| local model=$(get_model_name) | |
| echo "${ICON_BOLT} ${model}" | |
| } | |
| format_directory() { | |
| local dir=$(get_current_dir) | |
| echo "${ICON_FOLDER} ${dir##*/}" | |
| } | |
| format_git_branch() { | |
| local branch=$(get_git_branch) | |
| if [[ -n "$branch" ]]; then | |
| echo "${ICON_BRANCH} ${branch}" | |
| else | |
| echo "" | |
| fi | |
| } | |
| format_cost() { | |
| local cost=$(get_cost) | |
| if [[ "$cost" == "null" || -z "$cost" ]]; then | |
| echo "" | |
| else | |
| printf "%s \$%.3f" "$ICON_DOLLAR" "$cost" | |
| fi | |
| } | |
| format_duration() { | |
| local duration=$(get_duration) | |
| if [[ "$duration" == "null" || -z "$duration" ]]; then | |
| echo "" | |
| else | |
| local seconds=$((duration / 1000)) | |
| if [[ $seconds -lt 60 ]]; then | |
| echo "${ICON_CLOCK} ${seconds}s" | |
| else | |
| local minutes=$((seconds / 60)) | |
| local remaining_seconds=$((seconds % 60)) | |
| if [[ $remaining_seconds -eq 0 ]]; then | |
| echo "${ICON_CLOCK} ${minutes}m" | |
| else | |
| echo "${ICON_CLOCK} ${minutes}m${remaining_seconds}s" | |
| fi | |
| fi | |
| fi | |
| } | |
| format_lines() { | |
| local added=$(get_lines_added) | |
| local removed=$(get_lines_removed) | |
| local result="" | |
| if [[ "$added" != "null" && "$added" -gt 0 ]]; then | |
| result+="+${added}" | |
| fi | |
| if [[ "$removed" != "null" && "$removed" -gt 0 ]]; then | |
| [[ -n "$result" ]] && result+=" " | |
| result+="-${removed}" | |
| fi | |
| if [[ -n "$result" ]]; then | |
| echo "${ICON_PENCIL} ${result}" | |
| else | |
| echo "" | |
| fi | |
| } | |
| get_context_percentage() { | |
| local context_size=$(get_context_size) | |
| local usage=$(get_current_usage) | |
| if [[ "$context_size" == "null" || -z "$context_size" || "$context_size" -eq 0 ]]; then | |
| echo "" | |
| return | |
| fi | |
| if [[ "$usage" == "null" ]]; then | |
| echo "0" | |
| return | |
| fi | |
| local input_tokens=$(echo "$usage" | jq -r '.input_tokens // 0') | |
| local cache_create=$(echo "$usage" | jq -r '.cache_creation_input_tokens // 0') | |
| local cache_read=$(echo "$usage" | jq -r '.cache_read_input_tokens // 0') | |
| local used=$((input_tokens + cache_create + cache_read)) | |
| echo $((used * 100 / context_size)) | |
| } | |
| format_context() { | |
| local context_size=$(get_context_size) | |
| local usage=$(get_current_usage) | |
| if [[ "$context_size" == "null" || -z "$context_size" || "$context_size" -eq 0 ]]; then | |
| echo "" | |
| return | |
| fi | |
| if [[ "$usage" == "null" ]]; then | |
| echo "${ICON_CHART} 0% 0K" | |
| return | |
| fi | |
| local input_tokens=$(echo "$usage" | jq -r '.input_tokens // 0') | |
| local cache_create=$(echo "$usage" | jq -r '.cache_creation_input_tokens // 0') | |
| local cache_read=$(echo "$usage" | jq -r '.cache_read_input_tokens // 0') | |
| local used=$((input_tokens + cache_create + cache_read)) | |
| local used_k=$((used / 1000)) | |
| local percentage=$((used * 100 / context_size)) | |
| echo "${ICON_CHART} ${percentage}% ${used_k}K" | |
| } | |
| # Build the status line | |
| output="" | |
| # Model segment (purple) | |
| model=$(format_model) | |
| if [[ -n "$model" ]]; then | |
| output+="$(segment "$BG_PURPLE" "$FG_ON_PURPLE" "$FG_PURPLE" "$BG_BLUE" "$model")" | |
| fi | |
| # Directory segment (blue) | |
| directory=$(format_directory) | |
| git_branch=$(format_git_branch) | |
| context=$(format_context) | |
| context_pct=$(get_context_percentage) | |
| # Determine context segment colors based on percentage | |
| if [[ -n "$context_pct" && "$context_pct" -gt 80 ]]; then | |
| CTX_BG="$BG_RED" | |
| CTX_FG="$FG_ON_RED" | |
| CTX_FG_SEP="$FG_RED" | |
| else | |
| CTX_BG="$BG_GREEN" | |
| CTX_FG="$FG_ON_GREEN" | |
| CTX_FG_SEP="$FG_GREEN" | |
| fi | |
| if [[ -n "$directory" ]]; then | |
| if [[ -n "$git_branch" ]]; then | |
| output+="$(segment "$BG_BLUE" "$FG_ON_BLUE" "$FG_BLUE" "$BG_PINK" "$directory")" | |
| else | |
| output+="$(segment "$BG_BLUE" "$FG_ON_BLUE" "$FG_BLUE" "$CTX_BG" "$directory")" | |
| fi | |
| fi | |
| # Git branch segment (pink) | |
| if [[ -n "$git_branch" ]]; then | |
| output+="$(segment "$BG_PINK" "$FG_ON_PINK" "$FG_PINK" "$CTX_BG" "$git_branch")" | |
| fi | |
| # Context segment (green or red if >80%) | |
| if [[ -n "$context" ]]; then | |
| output+="$(segment "$CTX_BG" "$CTX_FG" "$CTX_FG_SEP" "$BG_YELLOW" "$context")" | |
| fi | |
| # Cost segment (yellow) | |
| cost=$(format_cost) | |
| if [[ -n "$cost" ]]; then | |
| if [[ -n "$(format_duration)" ]]; then | |
| output+="$(segment "$BG_YELLOW" "$FG_ON_YELLOW" "$FG_YELLOW" "$BG_ORANGE" "$cost")" | |
| else | |
| if [[ -n "$(format_lines)" ]]; then | |
| output+="$(segment "$BG_YELLOW" "$FG_ON_YELLOW" "$FG_YELLOW" "$BG_CYAN" "$cost")" | |
| else | |
| output+="$(segment "$BG_YELLOW" "$FG_ON_YELLOW" "$FG_YELLOW" "" "$cost")" | |
| fi | |
| fi | |
| fi | |
| # Duration segment (orange) | |
| duration=$(format_duration) | |
| if [[ -n "$duration" ]]; then | |
| if [[ -n "$(format_lines)" ]]; then | |
| output+="$(segment "$BG_ORANGE" "$FG_ON_ORANGE" "$FG_ORANGE" "$BG_CYAN" "$duration")" | |
| else | |
| output+="$(segment "$BG_ORANGE" "$FG_ON_ORANGE" "$FG_ORANGE" "" "$duration")" | |
| fi | |
| fi | |
| # Lines changed segment (cyan) | |
| lines=$(format_lines) | |
| if [[ -n "$lines" ]]; then | |
| output+="$(segment "$BG_CYAN" "$FG_ON_CYAN" "$FG_CYAN" "" "$lines")" | |
| fi | |
| printf "%s \n" "$output" |
{ "$schema": "https://json.schemastore.org/claude-code-settings.json", // ... // add the following snippet, with the full path to your statusline.sh "statusLine": { "type": "command", "command": "/Users/catkins/.claude/statusline.sh" } }