Rate-limit usage (5h, 1w) in the prompt footer

Claude Code mods (plugins of function hooks), published as a plugin marketplace.
/plugin marketplace add seiya8bit/claude-mods
/plugin install usage-status@claude-mods
| Mod | What it does |
|---|---|
| usage-status | Shows 5h 2% 1w 5% ↻ 10/10 at the right of the prompt footer; turns amber at 70% and red at 90%, and adds the 5h reset time near the limit |
plugins/<name>/ (.claude-plugin/plugin.json, hooks/hooks.json, hooks/register.tsx)..claude-plugin/marketplace.json and the table above.claude plugin validate plugins/<name> and claude plugin validate .hooks/register.tsx 61 lines1import type { Register } from 'claude-code'
2
3const LABEL: Record<string, string> = { five_hour: '5h', seven_day: '1w' }
4
5// The desktop footer ignores Box gaps, drops whitespace-only text and renders every
6// Unicode space as one plain space, so a wide gap is braille blanks and a narrow one a space
7// behind a zero-width space (never leading whitespace)
8const GAP = '\u2800\u2800'
9const SPACE = '\u200b '
10// before the model name: one blank, half the gap between windows
11const END_GAP = '\u2800'
12
13const colorOf = (pct: number) => (pct >= 90 ? '#e5534b' : pct >= 70 ? '#d29922' : undefined)
14const PCT_COLOR: Record<string, string> = { five_hour: '#56b4e9', seven_day: '#2ec4a0' }
15// the footer mutes plain text; the theme's own text color matches the model name beside it
16const TEXT = 'text'
17
18const resetLabel = (iso: string, now: number) => {
19 const d = new Date(iso)
20 return d.toDateString() === new Date(now).toDateString()
21 ? d.toTimeString().slice(0, 5)
22 : `${d.getMonth() + 1}/${d.getDate()}`
23}
24
25export const register: Register = on => {
26 on('session.measure', ($, e, next) => {
27 $.ui.invalidate('ui.render')
28 return next(e)
29 })
30
31 on('ui.render', { component: 'SessionMode' }, async ($, e, next) => {
32 const { rateLimits } = await $.session.usage()
33 if (rateLimits.length === 0) return next(e)
34
35 const { Box, Text } = $.ui.resolve(e)
36 const now = await $.clock.now()
37 const modes = e.props.modes.join(' & ')
38
39 return (
40 <Box>
41 {modes && <Text color={TEXT}>{modes}</Text>}
42 {rateLimits.map((r, i) => {
43 const color = colorOf(r.percentUsed)
44 // weekly reset always; the others only near the limit
45 const showReset = r.resetsAt && (color || r.kind === 'seven_day')
46 return (
47 <Box key={r.kind} gap={1}>
48 <Text color={TEXT}>{(i > 0 || modes ? GAP : '') + (LABEL[r.kind] ?? r.kind)}</Text>
49 <Text bold={!!color} color={color ?? PCT_COLOR[r.kind] ?? TEXT}>{Math.round(r.percentUsed)}%</Text>
50 {showReset && (
51 <Text color={color}>{`${SPACE}↻ ${resetLabel(r.resetsAt!, now)}`}</Text>
52 )}
53 </Box>
54 )
55 })}
56 <Text>{END_GAP}</Text>
57 </Box>
58 )
59 })
60}
61