Files
dotfiles/home/dot_claude/executable_statusline-command.sh
domverse 893ec8e3cb feat: shell + dotfiles setup for a fresh box
Two layers with a deliberate privilege split: setup.sh does the root work
(apt, rustup, cargo tools, starship, chsh) and hands off to chezmoi, which
owns everything under $HOME.

Tools are built with `cargo install --locked` to match the versions currently
running rather than whatever apt ships, at the cost of a 10-20 min cold setup.

Excluded on purpose: the atuin sync key and ~/.git-credentials (secrets),
~/.claude/settings.json (per-box decision), fnm/opencode conf.d (out of scope),
and fish_variables (machine-local).

chezmoi tracks only the executable and private attributes and derives modes
from the umask, so setup.sh pins umask 022 and atuin uses private_ to keep
0700/0600. Without both, a 002 umask silently relaxes them to 0775/0664.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 10:53:46 +02:00

144 lines
5.0 KiB
Bash

#!/usr/bin/env bash
# Claude Code status line - based on PS1 from ~/.bashrc
# Format: user@host:cwd | model | ctx: X% | 5h:X%↻Y | 7d:X%↻Y [CAVEMAN]
input=$(cat)
# Normalize reset timestamp: epoch int -> "@<epoch>", ISO string -> as-is
norm_ts() {
local v=$1
[ -z "$v" ] || [ "$v" = "null" ] && return
case "$v" in
''|*[!0-9]*) printf '%s' "$v" ;; # non-numeric => ISO
*) printf '@%s' "$v" ;; # all-digits => epoch
esac
}
model=$(echo "$input" | jq -r '.model.display_name // empty')
used=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
five_h_pct=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
five_h_reset=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
five_h_reset=$(norm_ts "$five_h_reset")
seven_d_pct=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
seven_d_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')
seven_d_reset=$(norm_ts "$seven_d_reset")
# PS1-derived portion: bold green user@host, reset, colon, bold blue cwd, reset
user=$(whoami)
host=$(hostname -s)
cwd=$(echo "$input" | jq -r '.workspace.current_dir // empty')
[ -z "$cwd" ] && cwd=$(pwd)
prompt_part=$(printf '\033[01;32m%s@%s\033[00m:\033[01;34m%s\033[00m' "$user" "$host" "$cwd")
# Color by usage pct: green <50, yellow 50-75, orange 75-90, red >=90
color_for_pct() {
local pct=$1
if [ "$pct" -ge 90 ]; then printf '\033[31m'
elif [ "$pct" -ge 75 ]; then printf '\033[38;5;172m'
elif [ "$pct" -ge 50 ]; then printf '\033[38;5;227m'
else printf '\033[32m'
fi
}
# Countdown ISO timestamp -> now (GNU date)
countdown() {
local reset_ts=$1
[ -z "$reset_ts" ] && return
local reset_epoch now_epoch diff_s
reset_epoch=$(date -d "$reset_ts" +%s 2>/dev/null) || return
now_epoch=$(date +%s)
diff_s=$((reset_epoch - now_epoch))
[ "$diff_s" -le 0 ] && printf "now" && return
local days=$((diff_s / 86400))
local hours=$(( (diff_s % 86400) / 3600 ))
local mins=$(( (diff_s % 3600) / 60 ))
if [ "$days" -gt 0 ]; then printf "%dd%dh" "$days" "$hours"
elif [ "$hours" -gt 0 ]; then printf "%dh%02dm" "$hours" "$mins"
else printf "%dm" "$mins"
fi
}
# Format reset timestamp as local clock time. fmt: GNU date format string
reset_clock() {
local reset_ts=$1
local fmt=$2
[ -z "$reset_ts" ] && return
date -d "$reset_ts" "+$fmt" 2>/dev/null
}
# Window elapsed pct: (window - time_until_reset) / window * 100, clamp 0-100
elapsed_pct() {
local reset_ts=$1
local window_s=$2
[ -z "$reset_ts" ] && return
local reset_epoch now_epoch diff_s elapsed
reset_epoch=$(date -d "$reset_ts" +%s 2>/dev/null) || return
now_epoch=$(date +%s)
diff_s=$((reset_epoch - now_epoch))
elapsed=$(( (window_s - diff_s) * 100 / window_s ))
[ "$elapsed" -lt 0 ] && elapsed=0
[ "$elapsed" -gt 100 ] && elapsed=100
printf '%d' "$elapsed"
}
# Claude info portion
info_parts=""
[ -n "$model" ] && info_parts="$model"
if [ -n "$used" ]; then
used_int=$(printf '%.0f' "$used")
[ -n "$info_parts" ] && info_parts="$info_parts | " || true
info_parts="${info_parts}ctx: ${used_int}%"
fi
# Rate limit segments (colored inside dim brackets via reset+recolor trick)
rate_segment=""
DIM='\033[02m'
PINK='\033[38;5;213m' # ~#EE6FF8, used for elapsed-pace pct
if [ -n "$five_h_pct" ]; then
five_int=${five_h_pct%.*}
five_color=$(color_for_pct "$five_int")
five_cd=$(countdown "$five_h_reset")
five_el=$(elapsed_pct "$five_h_reset" 18000)
five_clk=$(reset_clock "$five_h_reset" '%-l%P')
seg="${five_color}5h"
[ -n "$five_clk" ] && seg="${seg}(${five_clk})"
seg="${seg}:${five_int}%"
[ -n "$five_el" ] && seg="${seg}/${PINK}${five_el}%${five_color}"
[ -n "$five_cd" ] && seg="${seg}${five_cd}"
rate_segment="${rate_segment} | ${seg}\033[0m${DIM}"
fi
if [ -n "$seven_d_pct" ]; then
seven_int=${seven_d_pct%.*}
seven_color=$(color_for_pct "$seven_int")
seven_cd=$(countdown "$seven_d_reset")
seven_el=$(elapsed_pct "$seven_d_reset" 604800)
seven_clk=$(reset_clock "$seven_d_reset" '%a %-l%P')
seg="${seven_color}7d"
[ -n "$seven_clk" ] && seg="${seg}(${seven_clk})"
seg="${seg}:${seven_int}%"
[ -n "$seven_el" ] && seg="${seg}/${PINK}${seven_el}%${seven_color}"
[ -n "$seven_cd" ] && seg="${seg}${seven_cd}"
rate_segment="${rate_segment} | ${seg}\033[0m${DIM}"
fi
if [ -n "$info_parts" ] || [ -n "$rate_segment" ]; then
printf '%s \033[02m[%s' "$prompt_part" "$info_parts"
[ -n "$rate_segment" ] && printf '%b' "$rate_segment"
printf ']\033[00m'
else
printf '%s' "$prompt_part"
fi
#caveman
FLAG="$HOME/.claude/.caveman-active"
[ ! -f "$FLAG" ] && exit 0
MODE=$(cat "$FLAG" 2>/dev/null)
if [ -z "$MODE" ]; then
printf '\033[38;5;172m[CAVEMAN]\033[0m'
else
SUFFIX=$(echo "$MODE" | tr '[:lower:]' '[:upper:]')
printf '\033[38;5;172m[CAVEMAN:%s]\033[0m' "$SUFFIX"
fi