SLOPSHOPPER

usage-limits

Progress bars for the session (5h) and week (7d) rate limits in the prompt footer

newspinner
★ 2v1.0.0MITupdated 2026-10-06Abdallah-Abdelazim/usage-limits-cc-mod
A shopper browsing a rack in a slop shop
README

usage-limits

A Claude Code mod that shows your session (5-hour) and week (7-day) rate-limit usage as progress bars in the prompt footer.

Session ████░░░░░░ 42%  ·  Week █░░░░░░░░░ 7%

The bars appear next to the session mode indicator and update whenever Claude Code re-measures your rate limits.

Install

From inside Claude Code:

/plugin marketplace add Abdallah-Abdelazim/usage-limits-cc-mod
/plugin install usage-limits@usage-limits-local

Then reload plugins (or restart the session).

How it works

The mod is a plugin of function hooks (hooks/hooks.json → hooks/register.ts):

HookWhat it does
session.startReads current usage via $.session.usage() and stores the formatted line.
session.measureRefreshes the line when rateLimits changed.
ui.render (SessionMode)Appends the line to the session mode indicators.

hooks/format.ts renders each limit as a 10-cell bar (█ filled, ░ empty), clamped to 0–100%. Only the five_hour (Session) and seven_day (Week) limits are shown; other kinds are ignored. If no limits are reported, nothing is rendered.

Development

hooks/
  hooks.json     module manifest
  register.ts    hook registration
  format.ts      bar / line formatting
  format.test.ts tests (claude-code/testing)
types/index.d.ts plugin state typings

Tests use the claude-code/testing harness provided by Claude Code.

License

MIT

Source 3 files
hooks/register.ts 28 lines
1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import { line } from './format'
5
6const text = atom({ plugin: 'usage-limits', key: 'text' } as const, null)
7
8export const register: Register = on => {
9  on('session.start', async ($, e, next) => {
10    const latest = line((await $.session.usage()).rateLimits) ?? null
11    await update($, text, () => latest)
12
13    return next(e)
14  })
15
16  on('session.measure', async ($, e, next) => {
17    if (e.changed.includes('rateLimits')) await update($, text, () => line(e.rateLimits) ?? null)
18
19    return next(e)
20  })
21
22  on('ui.render', { component: 'SessionMode' }, async ($, e, next) => {
23    const current = await read($, text)
24
25    return next(current ? { ...e, props: { ...e.props, modes: [...e.props.modes, current] } } : e)
26  })
27}
28
hooks/format.ts 19 lines
1import type { SessionRateLimit } from 'claude-code'
2
3const WIDTH = 10
4const LABELS: Record<string, string> = { five_hour: 'Session', seven_day: 'Week' }
5
6export const bar = (percent: number): string => {
7  const filled = Math.round((Math.min(Math.max(percent, 0), 100) / 100) * WIDTH)
8
9  return '█'.repeat(filled) + '░'.repeat(WIDTH - filled)
10}
11
12export const line = (limits: readonly SessionRateLimit[]): string | undefined => {
13  const parts = limits
14    .filter(l => l.kind in LABELS)
15    .map(l => `${LABELS[l.kind]} ${bar(l.percentUsed)} ${Math.round(l.percentUsed)}%`)
16
17  return parts.length ? parts.join('  ·  ') : undefined
18}
19
types/index.d.ts 6 lines
1declare module 'claude-code' {
2  interface PluginState {
3    'usage-limits': { text: string | null }
4  }
5}
6