#!/usr/bin/env bash # # Complete statusline script for Claude Code - Shell implementation # Replicates the functionality of the Go implementation from rsmdt/the-startup # # Features: # - Shows current directory (with ~ for home) # - Shows git branch (if in a git repo) # - Shows model name and output style # - Shows help text with styling # - Terminal width aware # - ANSI color support # # Input: JSON from Claude Code via stdin # Output: Single formatted statusline with ANSI colors # # Performance target: <50ms execution time # # ANSI color codes # Main text color: #FAFAFA (very light gray/white) MAIN_COLOR="\033[38;2;250;250;250m" # Help text color: #606060 (gray, muted) HELP_COLOR="\033[38;2;96;96;96m" # Italic style ITALIC="\033[3m" # Reset all styles RESET="\033[0m" # Read JSON from stdin in one go IFS= read -r -d '' json_input || true # Extract fields from JSON using regex (no jq dependency for speed) # Pattern: "field": "value" or "field":"value" # Extract current_dir from workspace.current_dir current_dir="" if [[ "$json_input" =~ \"workspace\"[^}]*\"current_dir\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then current_dir="${BASH_REMATCH[1]}" fi # Fallback to cwd if current_dir not found if [[ -z "$current_dir" && "$json_input" =~ \"cwd\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then current_dir="${BASH_REMATCH[1]}" fi # Use current directory if still empty [[ -z "$current_dir" ]] && current_dir="$PWD" # Extract model display_name model_name="" if [[ "$json_input" =~ \"model\"[^}]*\"display_name\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then model_name="${BASH_REMATCH[1]}" fi [[ -z "$model_name" ]] && model_name="Claude" # Extract output_style name output_style="" if [[ "$json_input" =~ \"output_style\"[^}]*\"name\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then output_style="${BASH_REMATCH[1]}" fi [[ -z "$output_style" ]] && output_style="default" # Home directory substitution # Replace /Users/username or /home/username with ~ home_dir="$HOME" if [[ -n "$home_dir" && "$current_dir" == "$home_dir" ]]; then # Exact match: /Users/username -> ~ current_dir="~" elif [[ -n "$home_dir" && "$current_dir" == "$home_dir"/* ]]; then # Prefix match: /Users/username/Documents -> ~/Documents current_dir="~${current_dir#$home_dir}" fi # Get git branch information get_git_branch() { local dir="$1" # Expand tilde to home directory if present [[ "$dir" =~ ^~ ]] && dir="${dir/#\~/$HOME}" # Fast path: Direct .git/HEAD file read local git_head="${dir}/.git/HEAD" if [[ -f "$git_head" && -r "$git_head" ]]; then # Read file content local head_content head_content=$(<"$git_head") # Extract branch from "ref: refs/heads/branch-name" if [[ "$head_content" =~ ^ref:[[:space:]]*refs/heads/(.+)$ ]]; then echo "${BASH_REMATCH[1]}" return 0 fi # If HEAD is detached, return HEAD echo "HEAD" return 0 fi # Fallback: Use git command if available and in git repo if command -v git &>/dev/null && [[ -d "${dir}/.git" ]]; then local branch branch=$(cd "$dir" 2>/dev/null && git symbolic-ref --short HEAD 2>/dev/null || echo "") if [[ -n "$branch" ]]; then echo "$branch" return 0 fi # Check if in detached HEAD state if (cd "$dir" 2>/dev/null && git rev-parse --git-dir &>/dev/null); then echo "HEAD" return 0 fi fi # No git repo echo "" } # Get git info with branch symbol git_branch=$(get_git_branch "$current_dir") git_info="" if [[ -n "$git_branch" ]]; then git_info="⎇ $git_branch" fi # Get terminal width get_term_width() { local width # Method 1: COLUMNS environment variable (most reliable in hooks/scripts) if [[ -n "$COLUMNS" && "$COLUMNS" =~ ^[0-9]+$ && "$COLUMNS" -gt 0 ]]; then echo "$COLUMNS" return 0 fi # Method 2: tput cols command (if available) if command -v tput &>/dev/null; then width=$(tput cols 2>/dev/null) if [[ -n "$width" && "$width" =~ ^[0-9]+$ && "$width" -gt 0 ]]; then echo "$width" return 0 fi fi # Method 3: stty size command (if available) if command -v stty &>/dev/null; then local size size=$(stty size 2>/dev/null) if [[ -n "$size" ]]; then width=$(echo "$size" | cut -d' ' -f2) if [[ -n "$width" && "$width" =~ ^[0-9]+$ && "$width" -gt 0 ]]; then echo "$width" return 0 fi fi fi # Default fallback echo "120" } term_width=$(get_term_width) # Build the statusline parts # Format: 📁