Skip to content

Commit 95474e2

Browse files
lroolleclaude
andcommitted
feat: v0.12.1 — bump flash uses reverse-video ▲N outside brackets
Bold-only +N crammed between % and @ inside the brackets was too subtle in most terminals and read as noise. Move the indicator outside the badge with a reverse-video ▲ glyph — spatially distinct and unmissable without adding a fourth color lane. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 16396ec commit 95474e2

4 files changed

Lines changed: 41 additions & 28 deletions

File tree

CHANGELOG.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
11
# Changelog
22

3-
## v0.12.0 — 2026-07-02 — quota bump flash (+N when 5h/7d usage climbs)
3+
## v0.12.1 — 2026-07-02 — bump flash: reverse-video ▲N outside brackets
4+
5+
### Changed
6+
7+
- **Bump flash visual**: the quota-climb indicator moved from bold `+N`
8+
inside the badge to a **reverse-video `▲N`** outside the brackets:
9+
`5h[44%@1h18m] ▲2` / `7d[10%] ▲1`. Spatially distinct + reverse video
10+
(inverted bg/fg) makes it unmissable without adding a fourth color lane.
11+
Bold-only was too subtle in most terminals, and cramming `+N` between
12+
`%` and `@` inside the brackets made it read as noise.
13+
- `REVERSE`/`NO_REVERSE` (`ESC[7m`/`ESC[27m`) replaces `BOLD`/`NO_BOLD`.
14+
15+
218 tests, shellcheck warning count unchanged.
16+
17+
## v0.12.0 — 2026-07-02 — quota bump flash (▲N when 5h/7d usage climbs)
418

519
### Added
620

7-
- **Bump flash**: when the 5h or 7d utilization climbs between renders, the
8-
badge shows the increment in bold at its current color for ~60s:
9-
`5h[44%+2@1h18m]` / `7d[10%+1]` — "you just burned 2%". Vivid without a
10-
new hue, so the three color lanes stay unambiguous (bold is emphasis, not
11-
a fourth status color).
21+
- **Bump flash**: when the 5h or 7d utilization climbs between renders, a
22+
reverse-video `▲N` glyph appears outside the badge for ~60s:
23+
`5h[44%@1h18m] ▲2` / `7d[10%] ▲1` — "you just burned 2%". Vivid without
24+
a new hue, so the three color lanes stay unambiguous.
1225
- `quota_bump_notice()` + per-session state file
1326
(`sessions/<session_id>_quota_seen`, same lifecycle as `_cache_health`).
1427
Per-session on purpose: the flash compares against what THIS statusline
1528
last rendered, so concurrent sessions each get their own notice instead
1629
of racing over shared account state.
1730
- Semantics: first sighting is quiet; a climb records the increment; an
1831
unchanged value keeps a still-fresh notice alive; a second climb
19-
overwrites (latest increment, not a running sum — "+N" answers "what just
32+
overwrites (latest increment, not a running sum — "N" answers "what just
2033
happened"); a drop (window reset) clears silently, the fresh low number
2134
being its own signal.
22-
- `QUOTA_BUMP_NOTICE_SECS` (60) constant; `BOLD`/`NO_BOLD` attribute
23-
toggles (`ESC[22;1m` / `ESC[22m` — 22-first so bold applies cleanly even
24-
inside recovery-dimmed text).
35+
- `QUOTA_BUMP_NOTICE_SECS` (60) constant.
2536

2637
### Fixed
2738

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Every component earns its place:
8282
| Effort | Compact lowercase badge: `lo` / `md` / `xh` / `max` / `ultra` / `auto` (`high` is the default and stays hidden). Dim for routine levels; `max` / `ultra` use the pressure color; `fast` shows in fast mode. |
8383
| Context bar | Merged with model. Green / yellow / red by window pressure. On 1M models the bar also carries the premium input-pricing band: yellow past 200k tokens, red past 800k — the % alone looks calm (320k = 32%) while every request bills at the premium rate. A real 0% (e.g. right after `/compact` resets the window) renders a visibly empty bar `[░░░░░░0%]` — the snap to empty *is* the refresh signal; the bar hides only when no context data exists at all. |
8484
| User tier | Neutral white-weight (MAX bold, PRO normal, dim otherwise) — identity, never a status color. Truncated display name. |
85-
| Quota | Integer percentages. The 5h badge always carries its window countdown while a window is live — `5h[42%@1h20m]` reads "42% used, resets in 1h20m" — because on a 5h horizon the time remaining is the number you plan the current sitting around. Same `@remaining` language as the 7d badge; relative, not wall-clock, so no mental subtraction. When a window's utilization climbs between renders, the badge flashes the increment for ~60s in bold at its current color: `5h[44%+2@1h18m]` means "you just burned 2%". A drop (window reset) stays quiet — the fresh low number is its own signal. **7d is forecast, not leveled**: a learned per-weekday burn profile (EWMA over your own usage history) plus your recent 24h burn project whether the quota outlasts the window — your heavy Tuesday counts more than a generic average. The verdict is color alone; under pressure the badge shows explicit time remaining in the window: `7d[44%@5d]` red means "at your pace, dry days before the reset 5 days from now". Cold start (<14 days history) falls back to window-average pacing. Recovery color when reset is imminent. |
85+
| Quota | Integer percentages. The 5h badge always carries its window countdown while a window is live — `5h[42%@1h20m]` reads "42% used, resets in 1h20m" — because on a 5h horizon the time remaining is the number you plan the current sitting around. Same `@remaining` language as the 7d badge; relative, not wall-clock, so no mental subtraction. When a window's utilization climbs between renders, a reverse-video `▲N` glyph appears outside the badge for ~60s: `5h[44%@1h18m] ▲2` means "you just burned 2%". A drop (window reset) stays quiet — the fresh low number is its own signal. **7d is forecast, not leveled**: a learned per-weekday burn profile (EWMA over your own usage history) plus your recent 24h burn project whether the quota outlasts the window — your heavy Tuesday counts more than a generic average. The verdict is color alone; under pressure the badge shows explicit time remaining in the window: `7d[44%@5d]` red means "at your pace, dry days before the reset 5 days from now". Cold start (<14 days history) falls back to window-average pacing. Recovery color when reset is imminent. |
8686
| Extra usage | Monthly spend, limit, prepaid balance. `--extra auto` shows when quota runs out. |
8787
| Cache health | Detects observed prompt-cache rebuilds and cache-read drops. `cache!` on break, `cache~` when building. If a future Claude Code stdin includes TTL breakdown, `--cache always` can show `cache:1h@14:20`; current stdin usually exposes aggregate cache tokens only. Hidden when healthy by default. |
8888

@@ -107,7 +107,7 @@ red, matching its Claude Code TUI color) = model family; everything else is
107107
| 5 themes, 9 bar styles | -- | Yes |
108108
| Prompt cache break detection | -- | Yes |
109109
| OAuth + macOS Keychain | -- | Yes |
110-
| Quota bump flash (+N) | -- | Yes |
110+
| Quota bump flash (N) | -- | Yes |
111111
| 230 bats tests + CI | -- | Yes |
112112

113113
## Configuration

statusline.sh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -368,10 +368,10 @@ CYAN='\033[0;36m'
368368
DIM_CYAN='\033[2;36m'
369369
WHITE='\033[0;37m'
370370
BOLD_WHITE='\033[1;37m'
371-
# Attribute toggles for a brief emphasis at the CURRENT hue (quota bump flash).
372-
# 22 first clears any dim so bold applies cleanly even inside DIM_GREEN text.
373-
BOLD='\033[22;1m'
374-
NO_BOLD='\033[22m'
371+
# Reverse video for the quota bump flash — inverts fg/bg at whatever the
372+
# badge's current color is, so the ▲N glyph pops without adding a new hue.
373+
REVERSE='\033[7m'
374+
NO_REVERSE='\033[27m'
375375
RESET='\033[0m'
376376

377377
# Usage quota tracking
@@ -1655,11 +1655,11 @@ build_usage_display() {
16551655
local rel=$(format_reset_relative "$five_reset")
16561656
[ -n "$rel" ] && reset_suffix="${DIM}@${rel}${color}"
16571657
fi
1658-
# Bump flash: bold "+N" at the badge's current hue — vivid without a
1659-
# new color, so the status lanes stay unambiguous.
1658+
# Bump flash: reverse-video ▲N outside the brackets — spatially
1659+
# distinct and unmissable without adding a fourth color lane.
16601660
local bump_part=""
1661-
[ "$five_bump" -gt 0 ] 2>/dev/null && bump_part="${BOLD}+${five_bump}${NO_BOLD}${color}"
1662-
parts+=("${DIM}5h${color}[${five_int}%${bump_part}${reset_suffix}]${RESET}")
1661+
[ "$five_bump" -gt 0 ] 2>/dev/null && bump_part=" ${color}${REVERSE}${five_bump}${NO_REVERSE}"
1662+
parts+=("${DIM}5h${color}[${five_int}%${reset_suffix}]${bump_part}${RESET}")
16631663
fi
16641664

16651665
# 7d aggregate quota (if present and >0). Color comes from PACE, not level:
@@ -1727,8 +1727,8 @@ build_usage_display() {
17271727
reset_suffix="${DIM}@${rem}${color}"
17281728
fi
17291729
local bump_part=""
1730-
[ "$seven_bump" -gt 0 ] 2>/dev/null && bump_part="${BOLD}+${seven_bump}${NO_BOLD}${color}"
1731-
parts+=("${DIM}7d${color}[${seven_int}%${bump_part}${reset_suffix}]${RESET}")
1730+
[ "$seven_bump" -gt 0 ] 2>/dev/null && bump_part=" ${color}${REVERSE}${seven_bump}${NO_REVERSE}"
1731+
parts+=("${DIM}7d${color}[${seven_int}%${reset_suffix}]${bump_part}${RESET}")
17321732
fi
17331733

17341734
# Model-specific 7d quotas

t/statusline.bats

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ JSON
11481148
rm -rf "$tmpdir"
11491149
}
11501150

1151-
@test "integration: 5h utilization climb flashes +N on the next render" {
1151+
@test "integration: 5h utilization climb flashes N on the next render" {
11521152
tmpdir=$(mktemp -d)
11531153
mkdir -p "$tmpdir/.claude"
11541154
echo '{"claudeAiOauth":{"accessToken":"fake"}}' > "$tmpdir/.claude/.credentials.json"
@@ -1160,7 +1160,8 @@ JSON
11601160
payload 40 | HOME="$tmpdir" CLAUDE_DATA_DIR="$tmpdir/.claude/statusline" CLAUDE_CACHE_DIR="$tmpdir/sessions" bash "$SCRIPT_DIR/statusline.sh" >/dev/null
11611161
result=$(payload 43 | HOME="$tmpdir" CLAUDE_DATA_DIR="$tmpdir/.claude/statusline" CLAUDE_CACHE_DIR="$tmpdir/sessions" bash "$SCRIPT_DIR/statusline.sh")
11621162
plain=$(strip_ansi "$result")
1163-
[[ "$plain" == *"5h[43%+3@"* ]]
1163+
# ▲N lives outside the badge brackets: 5h[43%@3h...] ▲3
1164+
[[ "$plain" == *"5h[43%@3h"*"▲3"* ]]
11641165
# State is per-session and lives beside the cache-health files.
11651166
[ -f "$tmpdir/sessions/sess-bump_quota_seen" ]
11661167
rm -rf "$tmpdir"
@@ -1273,15 +1274,15 @@ JSON
12731274
[ "$result" = "0 0" ]
12741275
}
12751276

1276-
@test "build_usage_display: bump renders +N inside the badge" {
1277+
@test "build_usage_display: bump renders ▲N outside the badge" {
12771278
tmpdir=$(mktemp -d)
12781279
usage1='{"five_hour":{"utilization":42},"seven_day":{"utilization":10}}'
12791280
usage2='{"five_hour":{"utilization":45},"seven_day":{"utilization":12}}'
12801281
build_usage_display "$usage1" "" "$tmpdir/state" >/dev/null
12811282
result=$(build_usage_display "$usage2" "" "$tmpdir/state")
12821283
plain=$(strip_ansi "$result")
1283-
[[ "$plain" == *"5h[45%+3]"* ]]
1284-
[[ "$plain" == *"7d[12%+2]"* ]]
1284+
[[ "$plain" == *"5h[45%]"*"▲3"* ]]
1285+
[[ "$plain" == *"7d[12%]"*"▲2"* ]]
12851286
rm -rf "$tmpdir"
12861287
}
12871288

@@ -1293,7 +1294,8 @@ JSON
12931294
build_usage_display "$usage1" "" "$tmpdir/state" >/dev/null
12941295
result=$(build_usage_display "$usage2" "" "$tmpdir/state")
12951296
plain=$(strip_ansi "$result")
1296-
[[ "$plain" == *"5h[45%+3@2h"* ]]
1297+
# ▲N outside: 5h[45%@2h...] ▲3
1298+
[[ "$plain" == *"5h[45%@2h"*"▲3"* ]]
12971299
rm -rf "$tmpdir"
12981300
}
12991301

0 commit comments

Comments
 (0)