#!/bin/bash # Claude Code statusLine command (wired in via claude-settings.json). Claude pipes # its status JSON in on every update; we keep a snapshot per DevDesk session for # the web UI (context, plan usage, PR) and print a one-line status for Claude's footer. # Runs often while Claude streams, so it stays cheap and never fails loudly. input=$(cat) # Only record for panes on DevDesk's own tmux server. session="" outer=${TMUX:-} if [ "${outer%%,*}" = "${DEVDESK_SOCKET:-/run/devdesk/tmux.sock}" ] && [ -n "${TMUX_PANE:-}" ]; then session=$(tmux display-message -p -t "$TMUX_PANE" '#S' 2>/dev/null) session=${session:-${DEVDESK_SESSION:-}} fi if [[ $session =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$ ]]; then dir="${DEVDESK_STATE_DIR:-/var/lib/devdesk}/context" if mkdir -p "$dir" 2>/dev/null && tmp=$(mktemp "$dir/.$session.XXXXXX" 2>/dev/null); then if jq -cM '{ updated: (now | floor), claude_session_id: .session_id, model: .model.display_name, model_id: .model.id, effort: .effort.level, used_pct: .context_window.used_percentage, window: .context_window.context_window_size, used_tokens: (.context_window.current_usage | if . then ((.input_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)) else null end), cost_usd: .cost.total_cost_usd, lines_added: .cost.total_lines_added, lines_removed: .cost.total_lines_removed, # devdesk#25: plan usage (account-wide) and the pull request of the branch rate_limits: (.rate_limits // null | if . then { five_hour: (.five_hour | if . then {pct: .used_percentage, resets_at} else null end), seven_day: (.seven_day | if . then {pct: .used_percentage, resets_at} else null end)} else null end), pr: (.pr // null | if . then {number, url, review_state, kind} else null end) }' <<<"$input" >"$tmp" 2>/dev/null; then mv -f "$tmp" "$dir/$session.json" else rm -f "$tmp" fi fi fi # Footer line: session · model · context % · cost. ANSI colour numbers, not RGB, # so the browser's dark or light palette applies (devdesk#31). jq -rM --arg s "$session" ' def c($sgr; $t): "\u001b[\($sgr)m\($t)\u001b[0m"; def pct: if . == null then "—" else "\(. | floor)%" end; [ (if $s != "" then c("33"; "◈ \($s)") else empty end), c("36"; .model.display_name // "Claude"), c("37"; "ctx \(.context_window.used_percentage | pct)"), c("37"; "$\((.cost.total_cost_usd // 0) * 100 | round / 100)") ] | join(c("90"; " · "))' <<<"$input" 2>/dev/null || true