diff --git a/config/claude/statusline.sh b/config/claude/statusline.sh new file mode 100755 index 0000000..96d9193 --- /dev/null +++ b/config/claude/statusline.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Claude Code statusLine command: model, dir/branch, context usage, rate limits. +# See: https://code.claude.com/docs/en/statusline + +input=$(cat) + +MODEL=$(echo "$input" | jq -r '.model.display_name') +DIR=$(echo "$input" | jq -r '.workspace.current_dir') +PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1) +FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty') +WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty') + +GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m' + +if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED" +elif [ "$PCT" -ge 70 ]; then BAR_COLOR="$YELLOW" +else BAR_COLOR="$GREEN"; fi + +BAR_WIDTH=10 +FILLED=$((PCT * BAR_WIDTH / 100)) +EMPTY=$((BAR_WIDTH - FILLED)) +BAR="" +[ "$FILLED" -gt 0 ] && printf -v FILL "%${FILLED}s" && BAR="${FILL// /▓}" +[ "$EMPTY" -gt 0 ] && printf -v PAD "%${EMPTY}s" && BAR="${BAR}${PAD// /░}" + +BRANCH="" +git -C "$DIR" rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git -C "$DIR" branch --show-current 2>/dev/null)" + +LIMITS="" +[ -n "$FIVE_H" ] && LIMITS="5h: $(printf '%.0f' "$FIVE_H")%" +[ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }7d: $(printf '%.0f' "$WEEK")%" + +echo -e "[$MODEL] 📁 ${DIR##*/}${BRANCH}" +if [ -n "$LIMITS" ]; then + echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}% | ${LIMITS}" +else + echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}%" +fi diff --git a/install.sh b/install.sh index 487faf5..ed0d933 100755 --- a/install.sh +++ b/install.sh @@ -141,6 +141,7 @@ libinput-gestures.conf # separately below, per-file, since a standalone claude-sandbox install # also symlinks into ~/.claude/hooks). claude_configs=" +statusline.sh " local_home_templates=" zshrc_local @@ -322,6 +323,12 @@ function link_dotfiles { jq '.hooks.PreToolUse = ((.hooks.PreToolUse // []) + [{"matcher": "Bash", "hooks": [{"type": "command", "command": "$HOME/.claude/hooks/deny-dangerous-bash.sh"}]}])' \ "$HOME/.claude/settings.json" > "$tmp_settings" && mv "$tmp_settings" "$HOME/.claude/settings.json" fi + if ! jq -e '.statusLine' "$HOME/.claude/settings.json" >/dev/null 2>&1; then + echo "Adding statusline.sh statusLine to ~/.claude/settings.json" + tmp_settings=$(mktemp) + jq '.statusLine = {"type": "command", "command": "$HOME/.claude/statusline.sh"}' \ + "$HOME/.claude/settings.json" > "$tmp_settings" && mv "$tmp_settings" "$HOME/.claude/settings.json" + fi fi fi # TODO: These are getting in the way of dotfiles-local install so disabling