SLOPSHOPPER

usage-bar

Строка под окном ввода: контекст, 5-часовой и недельный лимиты

newspinner
v0.2.0NOASSERTIONupdated 2026-10-10GafarovMaxim/Claude/mods/usage-bar
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · usage-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 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › Context 49% · 5h 31% · week —

Draws

Prompt hint
Context 49% · 5h 31% · week —
README

usage-bar

Мод для Claude Desktop: строка под окном ввода с тремя значениями: заполненность контекста, расход 5-часового лимита, расход недельного лимита.

Значения читаются через $.session.usage() при каждой отрисовке подсказки под окном ввода (PromptHint, её рисуют терминал и Desktop). Значение от 85% помечается «!». Пока лимит не пришёл (нет подписки или ещё не было ответа), показывается «—». Подсказка заменяет стандартную строку подсказок под вводом.

Язык: берётся из настройки language в settings.json (иначе из LANG/LC_ALL): ru, en, de, fr, es, иначе английский. Язык интерфейса самого приложения мод узнать не может, только эту настройку.

На макете проверено, что подсказка рисуется на терминале и Desktop; в живом приложении мод ещё не видели.

Установка (только по согласию Максима): положить папку в ~/.claude/dev-mods/<сессия>/usage-bar/ или подключить через --plugin-dir.

Проверка: claude plugin validate mods/usage-bar и claude plugin test mods/usage-bar.

Установка одной строкой в терминальной сессии Claude Code (после слияния PR):

/plugin install usage-bar --marketplace GafarovMaxim/Claude
Source 1 files
hooks/register.tsx 51 lines
1import type { Register } from 'claude-code'
2
3const words = {
4  ru: { context: 'Контекст', five: '5 ч', week: 'неделя' },
5  en: { context: 'Context', five: '5h', week: 'week' },
6  de: { context: 'Kontext', five: '5 Std', week: 'Woche' },
7  fr: { context: 'Contexte', five: '5 h', week: 'semaine' },
8  es: { context: 'Contexto', five: '5 h', week: 'semana' }
9} as const
10
11type Lang = keyof typeof words
12
13// Язык берём из настройки language (язык ответов Claude), иначе из LANG/LC_ALL; по умолчанию английский.
14const pickLang = (raw: unknown): Lang => {
15  const s = String(raw ?? '').toLowerCase()
16  const code = (Object.keys(words) as Lang[]).find(
17    l => s === l || s.startsWith(l + '_') || s.startsWith(l + '-') || s.startsWith(l === 'ru' ? 'рус' : l === 'en' ? 'english' : '\0')
18  )
19
20  return code ?? 'en'
21}
22
23const find = (limits: readonly { kind: string; percentUsed: number }[], kind: string) =>
24  limits.find(l => l.kind === kind)?.percentUsed ?? null
25
26const fmt = (v: number | null) => (v === null ? '—' : `${Math.round(v)}%${v >= 85 ? '!' : ''}`)
27
28export const register: Register = on => {
29  let lang: Lang = 'en'
30
31  on('session.start', async ($, e, next) => {
32    const { language } = (await $.settings.read()) as { language?: string }
33    const env = language ?? (await $.env.get('LC_ALL')) ?? (await $.env.get('LANG'))
34    lang = pickLang(env)
35
36    return next(e)
37  })
38
39  // Подсказка под окном ввода (PromptHint) рисуется и в терминале, и в Desktop.
40  on('ui.render', { component: 'PromptHint' }, async ($, e, next) => {
41    const u = await $.session.usage()
42    const w = words[lang]
43    const ctx = fmt(u.context.percent ?? null)
44    const five = fmt(find(u.rateLimits, 'five_hour'))
45    const week = fmt(find(u.rateLimits, 'seven_day'))
46    const { Text } = $.ui.resolve(e)
47
48    return <Text dimColor>{`${w.context} ${ctx} · ${w.five} ${five} · ${w.week} ${week}`}</Text>
49  })
50}
51