Directory, Node version when a package.json is around, added and removed lines with a net-direction arrow, a token bar, and a session cost that changes color as it grows.
MIT licensed · original source
Updated 2026-07-06
0 copies
Preview
Clean repo
app ⏱ 10m ▲ +128 -34 ▓░░░░░░░ 22% $0.41 ◆ OpusNew session
app ⏱ 10m $0.00 ◆ OpusDirty branch
app ⏱ 10m ▲ +128 -34 ▓▓▓░░░░░ 48% $0.41 ◇ SonnetNear-full
app ⏱ 10m ▲ +128 -34 ▓▓▓▓▓▓▓░ 91% $4.12 ◆ Opus1M context
app ⏱ 10m ▲ +128 -34 ▓▓▓▓▓░░░ 64% $0.41 ● Fable 5Post-compact
app ⏱ 10m ▲ +128 -34 $0.41 ○ HaikuWorktree
feature ⏱ 10m ▲ +128 -34 ▓▓░░░░░░ 37% $0.41 ◆ OpusNon-git
scratch ⏱ 10m ▲ +128 -34 ▓░░░░░░░ 22% $0.41 ◆ OpusSource
#!/bin/bash
export TERM=xterm-256color
input=$(cat)
cwd=$(echo "$input" | jq -r '.workspace.current_dir')
model=$(echo "$input" | jq -r '.model.display_name // empty')
# Token usage
input_tokens=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
output_tokens=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
context_limit=$(echo "$input" | jq -r '.context_window.context_window_size // 0')
total_tokens=$((input_tokens + output_tokens))
# Cost & stats
cost=$(echo "$input" | jq -r '.cost.total_cost_usd // empty')
duration_ms=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
lines_added=$(echo "$input" | jq -r '.cost.total_lines_added // 0')
lines_removed=$(echo "$input" | jq -r '.cost.total_lines_removed // 0')
# Colors - basic ANSI codes compatible with most terminals
RED=$'\033[31m'
GREEN=$'\033[32m'
YELLOW=$'\033[33m'
BLUE=$'\033[34m'
MAGENTA=$'\033[35m'
CYAN=$'\033[36m'
GRAY=$'\033[90m'
RESET=$'\033[0m'
SEP="${GRAY}${RESET}"
short_dir=$(basename "$cwd")
# Node version (only if package.json exists)
node_info=""
if [ -f "$cwd/package.json" ] 2>/dev/null; then
node_ver=$(node -v 2>/dev/null | sed 's/v//')
[ -n "$node_ver" ] && node_info=" ${SEP} ${GREEN}⬢ ${node_ver}${RESET}"
fi
# Session duration
duration_info=""
if [ "$duration_ms" -gt 0 ] 2>/dev/null; then
duration_sec=$((duration_ms / 1000))
if [ "$duration_sec" -ge 3600 ]; then
hours=$((duration_sec / 3600))
mins=$(((duration_sec % 3600) / 60))
duration_fmt="${hours}h${mins}m"
elif [ "$duration_sec" -ge 60 ]; then
mins=$((duration_sec / 60))
duration_fmt="${mins}m"
else
duration_fmt="${duration_sec}s"
fi
duration_info=" ${SEP} ${CYAN}⏱ ${duration_fmt}${RESET}"
fi
# Lines changed
lines_info=""
if [ "$lines_added" -gt 0 ] || [ "$lines_removed" -gt 0 ] 2>/dev/null; then
net=$((lines_added - lines_removed))
if [ "$net" -gt 0 ]; then
net_symbol="${GREEN}▲${RESET}"
elif [ "$net" -lt 0 ]; then
net_symbol="${RED}▼${RESET}"
else
net_symbol="${GRAY}=${RESET}"
fi
lines_info=" ${SEP} ${net_symbol} ${GREEN}+${lines_added}${RESET} ${RED}-${lines_removed}${RESET}"
fi
# Token usage with progress bar
token_info=""
if [ "$total_tokens" -gt 0 ] 2>/dev/null; then
if [ "$total_tokens" -ge 1000 ]; then
tokens_fmt="$((total_tokens / 1000))k"
else
tokens_fmt="$total_tokens"
fi
if [ "$context_limit" -gt 0 ] 2>/dev/null; then
pct=$((total_tokens * 100 / context_limit))
# Color based on usage
if [ "$pct" -ge 75 ]; then
bar_color="$RED"
elif [ "$pct" -ge 50 ]; then
bar_color="$YELLOW"
else
bar_color="$GREEN"
fi
# Build progress bar using simple chars: ▓ filled, ░ empty
bar_width=8
filled=$((pct * bar_width / 100))
[ "$filled" -gt "$bar_width" ] && filled=$bar_width
[ "$filled" -lt 1 ] && [ "$pct" -gt 0 ] && filled=1
empty=$((bar_width - filled))
bar="${bar_color}"
for ((i=0; i<filled; i++)); do bar+="▓"; done
bar+="${GRAY}"
for ((i=0; i<empty; i++)); do bar+="░"; done
bar+="${RESET}"
token_info=" ${SEP} ${bar} ${GRAY}${pct}%${RESET}"
fi
fi
# Cost with meaningful colors
cost_info=""
if [ -n "$cost" ] && [ "$cost" != "null" ]; then
cost_fmt=$(printf "%.2f" "$cost")
cost_cents=$(printf "%.0f" "$(echo "$cost * 100" | bc)")
if [ "$cost_cents" -ge 1000 ] 2>/dev/null; then
cost_color="$RED"
elif [ "$cost_cents" -ge 200 ] 2>/dev/null; then
cost_color="$YELLOW"
else
cost_color="$GREEN"
fi
cost_info=" ${SEP} ${cost_color}\$${cost_fmt}${RESET}"
fi
# Model with tier colors
model_info=""
if [ -n "$model" ]; then
case "$model" in
*Opus*) model_color="$MAGENTA"; model_symbol="◆"; short_model="Opus" ;;
*Sonnet*) model_color="$BLUE"; model_symbol="◇"; short_model="Sonnet" ;;
*Haiku*) model_color="$GREEN"; model_symbol="○"; short_model="Haiku" ;;
*) model_color="$GRAY"; model_symbol="●"; short_model="$model" ;;
esac
model_info=" ${SEP} ${model_color}${model_symbol} ${short_model}${RESET}"
fi
printf "${BLUE}${short_dir}${RESET}%s%s%s%s%s%s" "$node_info" "$duration_info" "$lines_info" "$token_info" "$cost_info" "$model_info"
What it shows
- Current directory name (basename of the working directory)
- Node.js version, shown only when a package.json exists in the current directory
- Session duration, formatted as seconds, minutes, or hours and minutes
- Lines added and removed in the session, with a net-direction symbol (up arrow, down arrow, or equals sign)
- Context window usage as an 8-character progress bar plus a percentage
- Total session cost in US dollars, rounded to cents
- Model name shortened to its tier (Opus, Sonnet, Haiku) with a tier-specific symbol and color, or the full display name for other models
Requirements
- Bash
- jq for parsing the JSON that Claude Code sends on stdin
- bc for converting the cost to cents
- node on the PATH if you want the Node version segment; the segment is silently skipped when node is missing
- A terminal that renders basic ANSI colors and Unicode symbols (▓ ░ ▲ ▼ ⏱ ⬢ ◆ ◇ ○ ●); no Nerd Font needed
- No network access
Behavior notes
- In a brand-new session with zero tokens and zero changed lines, the token bar and the lines segment disappear entirely, leaving directory, duration, cost, and model
- A cost of exactly zero still renders, as a green $0.00
- The progress bar and percentage change color with usage: green below 50% (22%, 37%), yellow from 50% (64%), red from 75% (91%)
- The cost changes color as it grows: green below $2 ($0.41), yellow from $2 ($4.12), red from $10
- The percentage is computed against the session's actual context window size, so a 1M-token window shows 64% rather than overflowing
- Model matching is by display-name substring: Opus, Sonnet, and Haiku get their own colors and symbols, while Fable 5 falls through to the gray default and keeps its full name
- In a git worktree the directory segment is just the basename of the current directory (feature), not the branch or project name
- The Node version segment never appears in the rendered previews because none of the sandbox directories contained a package.json
- Vim mode, rate limits, PR state, effort level, and git branch are present in the input JSON but have no effect on the output
More status lines
Dreambase Panel
150 copies
╭─ CONTEXT ────────────────────────────────────────────╮
│ ████▊░░░░░░░░░░░░░░░░░ 22% of 200K · GOOD │
├─ STATS ──────────────────────────────────────────────┤
│ ↓ 44.0K ↑ 1.4K │ $0.41 │ ⏱ 10m 12s │ +128/-34 │
├─ REPO ───────────────────────────────────────────────┤
│ ◆ Opus 4.8 · main · 16:21 │
╰──────────────────────────────────────────────────────╯
Single-line usage
87 copies
app · main · Opus-4.8 · effort high · ctx 22% · 5h 26% ↻2h6m · 7d 7% ↻2d0hPace Dot Meters
63 copies
Opus 4.8 [high] ~/app main
16:20:55 | ⛁ ██░░░░░░░░ 22% | 5h ●◔○○○ 26% ↻2h7m | 7d ◔○○○○○○ 7% ↻2d1h │ $0.41 ⏱ 10m
Catppuccin Frappé
38 copies
Opus 4.8 │ main │ app │ ▓▓░░░░░░░░ 44k/200k │ $0.41
Activity Feed
36 copies
Opus 4.8 high ✦ │ ctx 22% │ app (main) │ PR #1287 ● │ $0.41 · 10m +128 -34
Session ● ● ● ● ● ● ● ● ○ ○ ○ 74% left Resets in 2h 6m
Weekly ● ● ● ● ● ● ● ● ● ● ○ 93% left Resets in 2d 0h
Fable ● ● ● ● ● ● ● ● ● ○ ○ 85% left Resets in 2d 0h
◐ Read:index.ts ✓ Read×1 ✓ Bash×1 ✓ Edit×1 ✓ Grep×1
◐ code-reviewer Review the change for regressions
Dreambase Flat
29 copies
████▊░░░░░░░░░░░░░░░░░ 22% of 200K · GOOD │ ↓ 44.0K ↑ 1.4K │ $0.41 │ ⏱ 10m 12s │ +128/-34 │ ◆ Opus 4.8 · main · 16:22