Shows the remaining usage (5-hour and 7-day windows) above the prompt

Shows how much of your Claude usage is left, in a single quiet line above the message box: for example 残りの使用量: 5時間 残り77%(回復まで2時間15分) · 7日間 残り60%(回復まで3日4時間). The figures are the rate-limit windows the last response reported; the line turns yellow when a window is 80% used or more. It needs no setup. The time until reset is shown as a duration, so it does not depend on the time zone.
/plugin install usage-band --marketplace rwkmty-maker/claude-mods
hooks/register.tsx 64 lines1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import type { Limit, Limits } from '../types'
5
6const limits = atom({ plugin: 'usage-band', key: 'limits' } as const, [] as Limits)
7
8const NAMES: Record<string, string> = { five_hour: '5時間', seven_day: '7日間', spend_limit: '利用上限' }
9
10// time left until the window resets, as 2時間15分 / 3日4時間 / 12分 (no time zone needed)
11function until(iso: string | undefined, now: number): string {
12 if (!iso) return ''
13 const ms = Date.parse(iso) - now
14 if (!(ms > 0)) return ''
15 const min = Math.ceil(ms / 60000)
16 const d = Math.floor(min / 1440), h = Math.floor((min % 1440) / 60), m = min % 60
17 if (d > 0) return `${d}日${h}時間`
18 if (h > 0) return `${h}時間${m}分`
19 return `${m}分`
20}
21
22function line(l: Limit, now: number): string {
23 const left = Math.max(0, Math.round((100 - l.percentUsed) * 10) / 10)
24 const reset = until(l.resetsAt, now)
25 return `${NAMES[l.kind] ?? l.kind} 残り${left}%` + (reset ? `(回復まで${reset})` : '')
26}
27
28export const register: Register = on => {
29 on('session.start', async ($, e, next) => {
30 const r = await next(e)
31 const u = await $.session.usage()
32 await update($, limits, () => u.rateLimits)
33 return r
34 })
35
36 on('session.measure', async ($, e, next) => {
37 await update($, limits, () => e.rateLimits)
38 return next(e)
39 })
40
41 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
42 const ls = await read($, limits)
43 if (e.props.hasSurvey) return next(e)
44 const { Box, Text } = $.ui.resolve(e)
45 if (ls.length === 0) {
46 // say so, instead of showing nothing: the engine has no usage reading in this environment (yet)
47 return (
48 <Box>
49 <Text dimColor>残りの使用量: まだ取得できていません(この環境では使用量の情報が届いていません)</Text>
50 </Box>
51 )
52 }
53 const now = await $.clock.now()
54 const low = ls.some(l => l.percentUsed >= 80)
55 return (
56 <Box>
57 <Text dimColor={!low} color={low ? 'yellow' : undefined}>
58 {'残りの使用量: ' + ls.map(l => line(l, now)).join(' · ')}
59 </Text>
60 </Box>
61 )
62 })
63}
64types/index.d.ts 9 lines1export type Limit = { kind: string; percentUsed: number; resetsAt?: string }
2export type Limits = Limit[]
3
4declare module 'claude-code' {
5 interface PluginState {
6 'usage-band': { limits: Limits }
7 }
8}
9