SLOPSHOPPER

token-bar

Bar above the prompt showing account usage (5h and 7-day limits), context and cost

newband
v0.1.0no licenseupdated 2026-10-14Lerma4/claude-code-mods/token-bar
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · token-bar
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ⚡ 5h ████ ░░░░░░░░░░ 31% ↻ NaNm ctx 97k/200k $0.42 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts

Draws

Band
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ⚡ 5h ████ ░░░░░░░░░░ 31% ↻ NaNm ctx 97k/200k $0.42 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
README

claude-code-mods

A growing collection of mods for Claude Code.

ModWhat it does
agent-squadSide pane listing the agents at work: nickname, icon, role, status and current activity. /squadra flusso (or a click on an agent) opens a live map in the browser: call graph, timeline, files touched and crucial files. /squadra storico lists past sessions and the files each one changed (Windows only for now)
token-barBar above the prompt showing account usage (5h and 7-day limits), context and cost

The in-app labels are in Italian.

Install

Inside Claude Code:

/plugin marketplace add Lerma4/claude-code-mods
/plugin install agent-squad@claude-code-mods
/plugin install token-bar@claude-code-mods

Then restart Claude Code.

Update

/plugin marketplace update claude-code-mods

Or enable auto-update for this marketplace from the /plugin menu.

Source 2 files
hooks/register.tsx 91 lines
1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import type { Snapshot } from '../types'
5
6const snap = atom({ plugin: 'token-bar', key: 'snap' } as const, null)
7
8const LABEL: Record<string, string> = { five_hour: '5h', seven_day: '7gg', spend_limit: 'spesa' }
9const WIDTH = 14
10
11// verde < 60, giallo < 85, rosso oltre
12const tone = (p: number) => (p >= 85 ? '#f7768e' : p >= 60 ? '#e0af68' : '#9ece6a')
13
14const bar = (p: number) => {
15  const n = Math.round((Math.min(100, Math.max(0, p)) / 100) * WIDTH)
16  return { on: '█'.repeat(n), off: '░'.repeat(WIDTH - n) }
17}
18
19const fmtTokens = (n: number) => (n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${Math.round(n / 1e3)}k` : `${n}`)
20
21const until = (iso: string | undefined, now: number) => {
22  if (!iso) return ''
23  const m = Math.max(0, Math.round((Date.parse(iso) - now) / 60000))
24  const d = Math.floor(m / 1440)
25  const h = Math.floor((m % 1440) / 60)
26  return d > 0 ? `${d}g ${h}h` : h > 0 ? `${h}h ${m % 60}m` : `${m}m`
27}
28
29const toSnap = (u: {
30  rateLimits: Snapshot['limits']
31  context: { percent?: number; tokens?: number; window: number }
32  cost?: { usd: number }
33}): Snapshot => ({
34  limits: u.rateLimits,
35  contextPercent: u.context.percent,
36  contextTokens: u.context.tokens,
37  contextWindow: u.context.window,
38  usd: u.cost?.usd,
39})
40
41export const register: Register = on => {
42  on('session.start', async ($, e, next) => {
43    const u = await $.session.usage()
44    await update($, snap, () => toSnap(u))
45
46    return next(e)
47  })
48
49  on('session.measure', async ($, e, next) => {
50    await update($, snap, () => toSnap(e))
51
52    return next(e)
53  })
54
55  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
56    const s = await read($, snap)
57
58    if (e.props.hasSurvey || s === null) return next(e)
59
60    const { Box, Text } = $.ui.resolve(e)
61    const now = await $.clock.now()
62
63    const meters = s.limits.map(l => {
64      const b = bar(l.percentUsed)
65      const c = tone(l.percentUsed)
66      const reset = until(l.resetsAt, now)
67
68      return (
69        <Box key={l.kind} gap={1}>
70          <Text bold>{LABEL[l.kind] ?? l.kind}</Text>
71          <Text color={c}>{b.on}</Text>
72          <Text dimColor>{b.off}</Text>
73          <Text color={c} bold>{`${Math.round(l.percentUsed)}%`}</Text>
74          {reset ? <Text dimColor>{`↻ ${reset}`}</Text> : null}
75        </Box>
76      )
77    })
78
79    return (
80      <Box borderStyle="round" borderColor="#565f89" paddingX={1} gap={3}>
81        <Text bold color="#7aa2f7">⚡</Text>
82        {meters.length > 0 ? meters : <Text dimColor>limiti account non disponibili</Text>}
83        {s.contextTokens !== undefined ? (
84          <Text dimColor>{`ctx ${fmtTokens(s.contextTokens)}/${fmtTokens(s.contextWindow)}`}</Text>
85        ) : null}
86        {s.usd !== undefined ? <Text dimColor>{`$${s.usd.toFixed(2)}`}</Text> : null}
87      </Box>
88    )
89  })
90}
91
types/index.d.ts 15 lines
1export type Limit = { kind: string; percentUsed: number; resetsAt?: string }
2export type Snapshot = {
3  limits: Limit[]
4  contextPercent?: number
5  contextTokens?: number
6  contextWindow: number
7  usd?: number
8}
9
10declare module 'claude-code' {
11  interface PluginState {
12    'token-bar': { snap: Snapshot | null }
13  }
14}
15