コンテキスト残量とプランの使用量をステータス行に常時表示する

Claude Code 用の自作モッドのマーケットプレイス。
入力欄の下に、コンテキスト残量とプランの使用量(5時間・週間の上限とリセットまでの時間)を常時表示する。
ctx 残り 72% · セッション 4% (4時間50分後) · 週間 33% (18時間10分後)
claude plugin marketplace add kj-nakamura/claude-mods
claude plugin install context-remaining@kenji-modshooks/register.ts 47 lines1import type { Register, EngineInterface, SessionRateLimit } from 'claude-code'
2
3const LABELS: Record<string, string> = { five_hour: 'セッション', seven_day: '週間' }
4
5function untilReset(resetsAt: string | undefined, now: number) {
6 if (resetsAt === undefined) return ''
7 const resetMs = Date.parse(resetsAt)
8 if (!Number.isFinite(resetMs) || !Number.isFinite(now)) return ''
9 const minutes = Math.max(0, Math.round((resetMs - now) / 60000))
10 const h = Math.floor(minutes / 60)
11 const m = minutes % 60
12 return h > 0 ? ` (${h}時間${m}分後)` : ` (${m}分後)`
13}
14
15function formatLimit(limit: SessionRateLimit, now: number) {
16 const label = LABELS[limit.kind] ?? limit.kind
17 return `${label} ${Math.round(limit.percentUsed)}%${untilReset(limit.resetsAt, now)}`
18}
19
20async function refresh($: EngineInterface) {
21 const { context, rateLimits } = await $.session.usage()
22 const now = await $.clock.now()
23 const parts = [`ctx 残り ${100 - (context.percent ?? 0)}%`]
24 for (const limit of rateLimits) parts.push(formatLimit(limit, now))
25 $.ui.status(parts.join(' · '))
26}
27
28export const register: Register = on => {
29 on('session.start', async ($, e, next) => {
30 const result = await next(e)
31 await refresh($)
32 return result
33 })
34
35 on('session.measure', async ($, e, next) => {
36 const result = await next(e)
37 await refresh($)
38 return result
39 })
40
41 on('tool.call', async ($, e, next) => {
42 const result = await next(e)
43 await refresh($)
44 return result
45 })
46}
47