SLOPSHOPPER

streak

Your streak of days in a row using Claude Code, in the status line next to the model, with /streak for details

newcommandstatusprocess
v0.1.0no licenseupdated 2026-10-10bhargava-gumpula/claude-mods/streak
A shopper browsing a rack in a slop shop
README

claude-mods

Mods for Claude Code (terminal and the desktop Code tab).

ModWhat it does
usage-bandA band above the prompt: 5h and 7d limits as bars with time to reset, session cost with a mood emoji, total session tokens, and a pacing hint
chat-rosterA floating org-chart window for the sidebar group of the chat you're in: the orchestrator on top, the group's chats below, running subagents under their chat. Filled = working, hover a dot for its title, a flash runs along the lines when messages pass. Shown only while Claude is in front; opens when a chat starts
cube/cube, /cube 2, /cube 4: random-state scrambles (the WCA method, via cubing.js)
handoff/handoff [focus]: runs the project's checks, writes the dev log entry and HANDOFF.md update, commits (never pushes), and summarizes
streakYour streak of days in a row using Claude Code in the status line (streak ๐Ÿ”ฅ 3 days); /streak adds your longest streak and total days
prompt-cleanupFixes typos in what you type before Claude reads it (Haiku; skips commands, code and long pastes)
 5h โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘ 52% (1h 30m)     7d โ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘ 23% (3d 5h)     $1.23   ๐Ÿ’ฉ     6.1M tokens     ๐Ÿ‘Œ on pace

Cost emoji: ๐Ÿ’ฉ $0โ€“$5 ยท ๐Ÿ˜’ >$5 ยท ๐Ÿฅฑ >$10 ยท ๐Ÿ˜ฎโ€๐Ÿ’จ >$25 ยท ๐Ÿซช >$50 ยท ๐Ÿ˜› >$100 ยท ๐Ÿค‘ >$500 ยท ๐Ÿ™€ >$1000. Pacing: ๐Ÿš€ spend freely (under an hour to reset, 70% or less used) ยท ๐Ÿข slow down (15+ points ahead of the clock) ยท ๐Ÿ‘Œ on pace ยท ๐Ÿ›‘ nearly out (90%+).

Needs: python3 (usage-band tokens, chat-roster, streak), Xcode command line tools for swiftc (chat-roster builds its window on first use, macOS only), node and npm (cube installs cubing.js on first use).

Install

In a Claude Code terminal session, one line per mod you want:

/plugin install usage-band --marketplace bhargava-gumpula/claude-mods
/plugin install chat-roster --marketplace bhargava-gumpula/claude-mods
/plugin install cube --marketplace bhargava-gumpula/claude-mods
/plugin install handoff --marketplace bhargava-gumpula/claude-mods
/plugin install prompt-cleanup --marketplace bhargava-gumpula/claude-mods
/plugin install streak --marketplace bhargava-gumpula/claude-mods

Answer y to add the marketplace, then pick the user scope.

Source 1 files
hooks/register.ts 53 lines
1import type { EngineInterface, Register } from 'claude-code'
2
3const DAY = 86_400_000
4const iso = (ms: number) => new Date(ms).toISOString().slice(0, 10)
5
6// Current streak counts back from today (or yesterday, so it survives until you start today).
7export const streaks = (days: readonly string[], today: string) => {
8  const set = new Set(days)
9  const t = Date.parse(today)
10  const start = set.has(today) ? t : t - DAY
11  let current = 0
12  while (set.has(iso(start - current * DAY))) current++
13
14  let longest = 0
15  let run = 0
16  let prev = NaN
17  for (const d of [...set].sort()) {
18    const ms = Date.parse(d)
19    run = ms - prev === DAY ? run + 1 : 1
20    longest = Math.max(longest, run)
21    prev = ms
22  }
23  return { current, longest, total: set.size }
24}
25
26const localToday = (now: number) => {
27  const d = new Date(now)
28  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
29}
30
31const load = async ($: EngineInterface) => {
32  const ran = await $.process.run(['python3', '-I', `${$.plugin.root}/hooks/days.py`])
33  const days = ran.exitCode === 0 ? (JSON.parse(ran.stdout) as { days: string[] }).days : []
34  return streaks(days, localToday(await $.clock.now()))
35}
36
37export const register: Register = on => {
38  on('session.start', async ($, e, next) => {
39    const ran = await next(e)
40    await $.command.register({ name: 'streak', description: 'Show your Claude Code day streak' })
41    const s = await load($).catch(() => undefined)
42    // The app labels a mod's status with its name ("streak"), so the text leaves the word out.
43    if (s) $.ui.status(`๐Ÿ”ฅ ${s.current} days`)
44    return ran
45  })
46
47  on('command.run', { command: 'streak' }, async $ => {
48    const s = await load($)
49    $.ui.status(`๐Ÿ”ฅ ${s.current} days`)
50    return { text: `๐Ÿ”ฅ ${s.current}-day streak ยท longest ${s.longest} days ยท ${s.total} days with Claude in all` }
51  })
52}
53