Files
fleet-dotfiles-template/dot_claude/executable_statusline-command.sh
Anthony Cardinale ebccdda936 Initial public release
A chezmoi-based fleet-dotfiles template for macOS workstations:

- Two-way auto-sync via launchd watcher + 5-min puller
- Mesh SSH via modify_authorized_keys driven by .chezmoidata/fleet.yaml
- age-encrypted secrets file
- Bundled Claude Code agentic team (11 agents) + /lite + /lite-sub commands
- Verify-before-claiming Stop hook
- Generic statusline + project-boundary validate-path hook
- Reference launchd plist for cross-fleet task-durations aggregation
  (companion repo: gitea.tojo.team/cardinale/task-durations)
- AGENTS.md walks an agent through the entire setup Q&A interactively
- docs/ covers architecture, security model, fleet onboarding
2026-05-02 17:26:32 -04:00

142 lines
5.0 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
# Claude Code statusLine script
# Format: user@host /path/base | Model ·effort | ctx:N% | 5h:N%→proj% 7d:N%→proj%
#
# The arrow/projection for 5h and 7d rate limits is a "quota pacer":
# - current usage % → projected final usage % (based on current burn rate)
# - color reflects projected exhaustion risk:
# green = projected ≤ 80% (safe)
# yellow = projected 80100% (warning)
# red = projected > 100% (will exhaust before reset)
# - no projection shown until ≥5% of the window has elapsed (avoids noise)
#
# The effort meter shows the current reasoning effort level (low/med/high/max/auto).
# Source priority: $CLAUDE_CODE_EFFORT_LEVEL env var > .effortLevel in
# ~/.claude/settings.json. Omitted if neither is set. Note: /effort max does
# not persist to settings.json, so it will only appear if the env var is set.
input=$(cat)
user=$(whoami)
host=$(hostname -s)
dir=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // "?"')
base=$(basename "$dir")
parent=$(dirname "$dir")
if [ "$parent" = "/" ]; then
parent_prefix="/"
else
parent_prefix="$parent/"
fi
model=$(echo "$input" | jq -r '.model.display_name // "Claude"' | sed -E 's/\([^)]*1M[^)]*\)/(1M)/')
ctx_used=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
five_used=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
five_reset=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
week_used=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
week_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')
now=$(date +%s)
# Compute a pacer fragment: "label:NN%→MM%" with the arrow+projection colored
# by risk. Prints only the label+current if not enough data to project.
# If unit="m", appends " (Nm)" (minutes until reset) in dim gray.
# If unit="d", appends " (N.Nd)" (days until reset, one decimal) in dim gray.
# If unit="" (or anything else), no time suffix.
#
# Args: label, used%, resets_at_epoch, window_seconds, unit ("m"|"d"|"")
pacer() {
label="$1"
u="$2"
reset="$3"
window="$4"
unit="$5"
if [ -z "$u" ]; then
return
fi
if [ -z "$reset" ] || [ "$reset" = "null" ]; then
printf " %s:%.0f%%" "$label" "$u"
return
fi
awk -v label="$label" -v u="$u" -v reset="$reset" -v window="$window" -v now="$now" -v unit="$unit" 'BEGIN {
start = reset - window
elapsed = now - start
if (elapsed < 1) elapsed = 1
elapsed_pct = (elapsed / window) * 100
time_suffix = ""
if (unit == "m") {
mins_left = int((reset - now) / 60)
if (mins_left < 0) mins_left = 0
time_suffix = sprintf(" \033[0;90m(%dm)\033[0m", mins_left)
} else if (unit == "d") {
days_left = (reset - now) / 86400
if (days_left < 0) days_left = 0
time_suffix = sprintf(" \033[0;90m(%.1fd)\033[0m", days_left)
}
# Not enough data yet: show current only.
# 5% for short windows (5h → 15min blackout); 1% for the 7d window
# (drops blackout from 8.4h to 1.7h while keeping early projections sane).
threshold = (unit == "d") ? 1 : 5
if (elapsed_pct < threshold) {
printf " %s:%.0f%%%s", label, u, time_suffix
exit
}
# Burn rate per % of elapsed time, projected to end of window
burn = u / elapsed_pct
projected = u + (burn * (100 - elapsed_pct))
if (projected > 100) {
color = "0;31" # red — will exhaust
} else if (projected > 80) {
color = "0;33" # yellow — warning
} else {
color = "0;32" # green — safe
}
printf " %s:%.0f%%\033[%sm→%.0f%%\033[0m%s", label, u, color, projected, time_suffix
}'
}
# Effort level: env var wins, then settings.json, otherwise omit.
effort=""
if [ -n "$CLAUDE_CODE_EFFORT_LEVEL" ]; then
effort="$CLAUDE_CODE_EFFORT_LEVEL"
elif [ -f "$HOME/.claude/settings.json" ]; then
effort=$(jq -r '.effortLevel // empty' "$HOME/.claude/settings.json" 2>/dev/null)
fi
# No space between model and · when model already ends with ")",
# otherwise use a single space separator.
case "$model" in
*")") eff_sep="" ;;
*) eff_sep=" " ;;
esac
effort_part=""
case "$effort" in
low) effort_part=$(printf "%s\033[0;90m·low\033[0m" "$eff_sep") ;;
medium) effort_part=$(printf "%s\033[0;32m·med\033[0m" "$eff_sep") ;;
high) effort_part=$(printf "%s\033[0;33m·high\033[0m" "$eff_sep") ;;
max) effort_part=$(printf "%s\033[1;35m·max\033[0m" "$eff_sep") ;;
auto) effort_part=$(printf "%s\033[0;36m·auto\033[0m" "$eff_sep") ;;
esac
ctx_part=""
if [ -n "$ctx_used" ]; then
ctx_part=$(printf " | ctx:%.0f%%" "$ctx_used")
fi
rate_part=""
if [ -n "$five_used" ] || [ -n "$week_used" ]; then
rate_part=" |"
rate_part="${rate_part}$(pacer 5h "$five_used" "$five_reset" 18000 m)"
rate_part="${rate_part}$(pacer 7d "$week_used" "$week_reset" 604800 d)"
fi
printf "\033[1;32m%s@%s\033[0m \033[0;90m%s\033[0m\033[1;34m%s\033[0m | \033[0;33m%s\033[0m%s%s%s" \
"$user" "$host" "$parent_prefix" "$base" "$model" "$effort_part" "$ctx_part" "$rate_part"