diff --git a/adapters/claude/statusline.sh b/adapters/claude/statusline.sh index 17a4697..d7c0661 100755 --- a/adapters/claude/statusline.sh +++ b/adapters/claude/statusline.sh @@ -18,28 +18,37 @@ if command -v git >/dev/null 2>&1; then [ "$branch" = "HEAD" ] && branch=$(git -C "${cwd/#\~/$HOME}" rev-parse --short HEAD 2>/dev/null) fi -# 3. Model display name +# 3. Model display name and id (id used to size the context window below) model=$(printf '%s' "$input" | jq -r '.model.display_name // empty' 2>/dev/null) +model_id=$(printf '%s' "$input" | jq -r '.model.id // .model.display_name // empty' 2>/dev/null) -# 4. Token count from transcript JSONL +# 4. Context-window occupancy from transcript JSONL. +# Matches /context: input + cache_read + cache_creation of the most recent +# request is exactly what currently occupies the context window. The usage +# object nests sub-objects, so parse each JSONL line as JSON rather than +# grepping (a brace-bounded grep truncates at the first nested "}"). ctx="" transcript=$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null) if [ -n "$transcript" ] && [ -r "$transcript" ] && command -v jq >/dev/null 2>&1; then - raw=$(grep -o '"usage":{[^}]*}' "$transcript" 2>/dev/null | tail -1) - if [ -n "$raw" ]; then - total=$(printf '%s' "{$raw}" | jq -r ' - .usage | - ((.input_tokens // 0) - + (.cache_read_input_tokens // 0) - + (.cache_creation_input_tokens // 0) - + (.output_tokens // 0)) - ' 2>/dev/null) - if [ -n "$total" ] && [ "$total" -gt 0 ] 2>/dev/null; then - if [ "$total" -ge 1000 ]; then - ctx=$(awk "BEGIN { printf \"%.1fk ctx\", $total/1000 }") - else - ctx="${total} ctx" - fi + total=$(tail -n 300 "$transcript" 2>/dev/null | jq -rR ' + fromjson? | (.message.usage // .usage) // empty + | select(.input_tokens != null) + | (.input_tokens + (.cache_read_input_tokens // 0) + (.cache_creation_input_tokens // 0)) + ' 2>/dev/null | tail -1) + if [ -n "$total" ] && [ "$total" -gt 0 ] 2>/dev/null; then + # 1M-context models report a [1m]/"1M" marker in the id/name; else 200k. + case "$model_id" in + *1m*|*1M*) limit=1000000; label="1m" ;; + *) limit=200000; label="200k" ;; + esac + ctx=$(awk -v t="$total" -v lim="$limit" -v lab="$label" 'BEGIN { + if (t >= 1000) ts = sprintf("%.1fk", t/1000); else ts = sprintf("%d", t); + printf "%s/%s tokens (%.0f%%)", ts, lab, t*100/lim + }') + # Turn the token segment red once context reaches 200k; reset after so the + # rest of the line keeps its default styling. + if [ "$total" -ge 200000 ] 2>/dev/null; then + ctx=$(printf '\033[31m%s\033[0m' "$ctx") fi fi fi